Jepsen kiểm định Orkes Conductor 5.3.2: Phát hiện 3 lỗi an toàn nghiêm trọng
Jepsen vừa công bố báo cáo kiểm định Orkes Conductor 5.3.2, phát hiện ba lỗi an toàn nghiêm trọng khiến workflow được xác nhận nhưng không bao giờ chạy, biến mất hoàn toàn, hoặc bị đánh dấu COMPLETED dù chưa thực thi. Nhiều lỗi trong số này đã được khắc phục ở phiên bản 5.5.6, trong khi một số vấn đề khác vẫn đang được điều tra.
Jepsen, nhóm nghiên cứu nổi tiếng chuyên kiểm định tính an toàn của các hệ phân tán, vừa công bố báo cáo về Orkes Conductor 5.3.2 — nền tảng điều phối workflow (workflow orchestrator) vốn bắt nguồn từ dự án mã nguồn mở Conductor của Netflix. Kết quả kiểm định cho thấy hệ thống này có nhiều điểm yếu liên quan đến tính nhất quán và độ bền dữ liệu, trong đó có ba lỗi an toàn nghiêm trọng.
Bối cảnh: Conductor là gì?
Conductor là hệ thống điều phối workflow được Netflix xây dựng và mở mã nguồn từ năm 2016. Phiên bản mã nguồn mở hiện do Conductor OSS Foundation duy trì, với Orkes — công ty do chính những người sáng lập Conductor tại Netflix lập nên — đóng vai trò dẫn dắt. Bên cạnh bản mã nguồn mở, Orkes còn cung cấp phiên bản dịch vụ được lưu trữ với nhiều tính năng bổ sung, gọi là Orkes Conductor.
Trong Conductor, một định nghĩa workflow là cấu trúc JSON mô tả các task cần thực thi, thứ tự chạy, đầu vào và đầu ra. Mỗi định nghĩa có tên và phiên bản riêng, có thể được chạy nhiều lần — mỗi lần như vậy là một workflow execution với ID duy nhất.
Kiến trúc của Conductor gồm năm thành phần chính: các Conductor server không trạng thái chịu trách nhiệm quản lý và lập lịch; cơ sở dữ liệu (Postgres, Cassandra, Redis) lưu trạng thái; hàng đợi (thường là Redis) phân phối công việc; cùng hai nhóm worker — worker chuẩn chạy các task tích hợp sẵn và worker tùy chỉnh do người dùng viết bằng SDK.
Conductor cam kết giao tin ít nhất một lần (at-least-once delivery) và đảm bảo mọi workflow đã khởi động sẽ chạy đến trạng thái kết thúc: COMPLETED, FAILED, TIMED_OUT hoặc TERMINATED.
Cách Jepsen kiểm định
Nhóm nghiên cứu dựng cụm 10 máy Debian, mô phỏng môi trường triển khai thực tế của Orkes: một node Postgres làm cơ sở dữ liệu, một node Redis (hoặc Redis Cluster) làm hàng đợi, phần còn lại chia đều cho Conductor server, worker chuẩn và một worker tùy chỉnh viết bằng Java SDK.
Bài kiểm thử chạy workflow một task, mỗi task "ngủ" tối đa 30 giây để giả lập xử lý rồi trả về kết quả ngẫu nhiên. Trong giai đoạn chính, nhóm liên tục gây lỗi có chủ đích: tạm dừng tiến trình, kill tiến trình, và chia cắt mạng giữa các thành phần. Sau đó hệ thống được để tự phục hồi, và Jepsen kiểm tra chéo toàn bộ trạng thái để tìm các hành vi bất thường.
Những phát hiện chính
Task chạy song song ngoài ý muốn (#1)
Ngay cả trên cụm khỏe mạnh, Conductor đôi khi để hai worker thực thi cùng một task của cùng một workflow đồng thời. Trong một lần chạy, task bắt đầu trên worker n9 ở giây 70,110 và trên n10 ở giây 70,113 — chênh nhau chỉ vài mili giây. Với cấu hình mặc định, hiện tượng này xảy ra khoảng 6 giờ một lần; giảm thời gian lease khóa xuống 1 giây thì tần suất tăng lên vài phút một lần.
Vấn đề trầm trọng hơn do một lỗi time-of-check to time-of-use trong tiến trình sweeper chuyên đưa các task bị kẹt trở lại hàng đợi, dẫn đến việc giao trùng lặp. Orkes cho biết lỗi này đã được sửa ở phiên bản 5.5.6.
Task bị treo trước khi thực thi (#2)
Khi dùng Postgres và Redis, Conductor 5.3.2 thường để một vài workflow bị treo trước khi task chạy. Workflow hiển thị trạng thái RUNNING, task trông như đang chạy trên một worker cụ thể, nhưng phương thức execute() của worker không bao giờ được gọi. Trạng thái này kéo dài đến khi hết thời gian chờ phản hồi (mặc định một giờ) rồi Conductor mới lập lịch lại.
Jepsen nhận định hành vi này không vi phạm cam kết của Conductor và Orkes quyết định không thay đổi. Người dùng có thể giảm tham số responseTimeoutSeconds để rút ngắn thời gian chờ.
Workflow bị bỏ rơi vĩnh viễn (#5)
Đây là một trong những lỗi nghiêm trọng nhất. Ở các phiên bản 5.3.2, 5.4.0 và 5.5.0-rc1, nhiều loại lỗi khác nhau có thể khiến Conductor bỏ rơi vĩnh viễn một số workflow: chúng mãi ở trạng thái RUNNING, task không bao giờ chạy, nhưng cả hàng đợi decider lẫn hàng đợi task đều trống rỗng. Khởi động lại node cũng không giúp gì.
Nguyên nhân: khi khởi động workflow, Conductor ghi bản ghi vào Postgres rồi đưa vào hàng đợi decider. Nếu bước thứ hai thất bại, workflow tồn tại trong cơ sở dữ liệu nhưng không có trong hàng đợi — và tiến trình sweeper lại chỉ giám sát hàng đợi chứ không kiểm tra cơ sở dữ liệu. Phiên bản 5.5.0 đã bổ sung tiến trình nền đưa các execution bị bỏ rơi trở lại hàng đợi.
Workflow biến mất (#7)
Cũng ở các phiên bản trên, chia cắt mạng giữa server và Postgres hoặc kill Postgres có thể khiến Conductor quên hẳn sự tồn tại của workflow từng hiển thị với client. Gọi getWorkflow() trả về null, còn HTTP request trả về lỗi 404 — và tình trạng này kéo dài vô hạn.
Nguyên nhân là khi server không thể thêm workflow vào hàng đợi decider, nó quyết định xóa bản ghi trong Postgres để "hoàn tác" — nhưng trong khoảng thời gian chờ đó, workflow vẫn hiển thị với client. Từ 5.5.0, Conductor không còn xóa execution khi một bước thất bại.
Workflow "hoàn thành" nhưng chưa từng chạy (#9)
Khi Postgres bị kill, Jepsen phát hiện những workflow ở trạng thái COMPLETED mà task chưa từng được thực thi. Cơ chế: task hết thời gian chờ, sweeper cố lập lịch lại, nhưng quá trình này gồm hai lần ghi riêng biệt vào Postgres — một tạo bản ghi task mới, một đánh dấu task cũ đã bị thay thế. Khi Postgres sập giữa hai lần ghi, Conductor bỏ qua lỗi và đánh dấu task cũ là bị thay thế mà không có task mới. Sau đó sweeper thấy mọi task đều ở trạng thái kết thúc và kết luận workflow đã hoàn thành.
Một giao dịch cơ sở dữ liệu bao trọn hai lần ghi sẽ ngăn được lỗi này, nhưng vì chúng nằm ở hai tầng mã khác nhau nên việc sửa đòi hỏi thay đổi lớn. Phiên bản 5.5.6 đã không còn bỏ qua lỗi khi ghi bản ghi task retry.
Các lỗi nhỏ khác
Ngoài ra còn bốn lỗi liên quan đến startWorkflow: trả về workflow ID null khi Redis sập (#3, chưa giải quyết), lỗi cú pháp SQL do race condition khi phân vùng bảng được tạo hoặc xoay vòng (#4, đã sửa ở 5.5.6), lỗi khóa trùng do cơ chế retry mới (#8, đã sửa ở 5.5.6), và lỗi "không kết nối được" gây hiểu nhầm — trong một lần chạy, 1.752 trên 25.920 lời gọi thất bại thực chất lại thành công (#6, đang điều tra). Điều này đặc biệt nguy hiểm nếu client tự động retry và tạo ra nhiều bản sao của cùng một workflow.
Khuyến nghị cho người dùng
Jepsen khuyến nghị người dùng nâng cấp lên phiên bản 5.5.6, vì bản này khắc phục cả ba lỗi an toàn nghiêm trọng. Với các workflow bị bỏ rơi hoặc bị đánh dấu hoàn thành sai, người dùng có thể tìm và khởi động lại thủ công.
Nhóm nghiên cứu cũng nhấn mạnh một bài học quan trọng: trong bất kỳ hệ thống điều phối workflow nào, người dùng cần đảm bảo các task có tính idempotent và giao hoán — không chỉ với các lần thử lại của chính nó mà còn với các task khác và với cả failure workflow.
Ví dụ: một workflow đặt vé máy bay bị timeout, Conductor thử lại nhưng cũng timeout, rồi kích hoạt failure workflow để hủy vé. Failure workflow hoàn tất, nhưng sau đó một request đặt vé bị trễ lại đến dịch vụ — và vé bị đặt lại dù workflow tưởng đã hủy xong.
Giải pháp là dùng idempotency key và logical clock ở các dịch vụ hạ nguồn để đảm bảo ngữ nghĩa giao hoán.
Góc nhìn cho người dùng Việt Nam
Với các đội phát triển tại Việt Nam đang dùng Conductor — hoặc các hệ điều phối tương tự như Temporal, Apache Airflow, Camunda — báo cáo này là lời nhắc nhở quan trọng về lựa chọn hệ lưu trữ đi kèm. Jepsen lưu ý rằng an toàn của Conductor chỉ ngang bằng an toàn của Postgres và Redis mà nó dựa vào. Redis đơn node là điểm lỗi đơn, còn Redis Cluster và Sentinel đều có thể mất ghi đã xác nhận khi mạng bị chia cắt. Ngay cả các dịch vụ managed như ElastiCache, Memorystore hay Azure Managed Redis cũng có những giới hạn cần đọc kỹ.
Nói cách khác, khi thiết kế hệ thống thanh toán, xử lý đơn hàng hay quy trình nghiệp vụ tự động trên Conductor, việc chọn đúng hệ lưu trữ và thiết kế task an toàn quan trọng không kém việc chọn công cụ điều phối.
Báo cáo đầy đủ của Jepsen được tài trợ bởi chính Orkes và thực hiện theo chính sách đạo đức của Jepsen. Như thường lệ, nhóm nghiên cứu lưu ý: họ có thể chứng minh sự tồn tại của lỗi, nhưng không thể chứng minh hệ thống không có lỗi.
Bài viết liên quan

Công nghệ
Mô hình AI hàng đầu giỏi Vật lý đến đâu? Nghiên cứu mới chỉ ra các bài kiểm tra hiện hành đang đánh giá sai
16 tháng 9, 2026

Công nghệ
Nộp đơn xin việc lẽ ra nên khó hơn. Thật đấy
25 tháng 8, 2026

Công nghệ
GM đóng cửa nhà máy lắp ráp pin Brownstown: Lý do không liên quan đến chiến lược xe điện
20 tháng 10, 2026