Xử lý lỗi trong hệ thống phân tán


8

Đây là chuỗi chung của hai thành phần phân tán trong ứng dụng Java của chúng tôi:

1  A sends request to B
2      B starts some job J in parallel thread
3      B returns response to A
4  A accepts response
5      Job finishes after some time
6      Job sends information to A
7  A receives response from a Job and updates

Đây là kịch bản lý tưởng, giả sử mọi thứ hoạt động. Tất nhiên, cuộc sống thực sự đầy những thất bại. Ví dụ, một trong những trường hợp xấu nhất có thể là nếu #6thất bại đơn giản chỉ vì mạng: công việc đã được thực thi chính xác, nhưng Akhông biết gì về nó.

Tôi đang tìm kiếm một cách tiếp cận nhẹ về cách quản lý lỗi trong hệ thống này. Lưu ý rằng chúng tôi có rất nhiều thành phần, vì vậy việc phân cụm tất cả chúng chỉ vì xử lý lỗi không có ý nghĩa. Tiếp theo, tôi đã bỏ việc sử dụng bất kỳ bộ nhớ / repo phân tán nào sẽ được cài đặt lại trên mỗi thành phần vì cùng một lý do.

Suy nghĩ của tôi đang đi theo hướng có một trạng thái tuyệt đối trên B và không bao giờ có trạng thái tồn tại trên a A. Điều này có nghĩa như sau:

  • trước khi #1chúng tôi đánh dấu Arằng đơn vị công việc tức là thay đổi sắp bắt đầu
  • chỉ Bcó thể bỏ đánh dấu trạng thái này.
  • Acó thể lấy thông tin về Bbất cứ lúc nào, để cập nhật trạng thái.
  • không có thay đổi mới trên cùng một đơn vị có thể được gọi trên A.

bạn nghĩ sao? Có cách nào nhẹ để khắc phục lỗi trong hệ thống loại này không?


Đây là một câu hỏi cũ. Bạn đã tìm thấy một giải pháp tốt? ... Nếu vậy, bạn có thể chia sẻ nó?
Svidgen

Câu trả lời:


2

Đăng nhập vào một bản ghi liên tục trên A là đủ. Điều này đối phó với khởi động lại và phân vùng mạng để đạt được sự thống nhất cuối cùng, hoặc để phá vỡ tín hiệu ngăn chặn sự hội tụ như vậy. Với cam kết nhóm được khấu hao , có thể mất ít hơn một lần ghi để duy trì một mục nhật ký.

Bạn đề nghị làm cho B chịu trách nhiệm cho việc bỏ đánh dấu trạng thái. Tôi không đồng ý. Chỉ A nhận thức được công việc mới và chỉ A phải chịu trách nhiệm theo dõi nó và báo cáo các lỗi như thời gian chờ. B gửi (các) tin nhắn không cần thiết đến A và A cập nhật trạng thái, truy vấn lại theo các khoảng thời gian khi cần thiết.

Ở bước 0, A nhận ra một yêu cầu mới và ghi lại nó. Điều đó cấu thành nghĩa vụ A phải thực hiện sau một thời hạn - A sẽ liên tục thực hiện và lặp lại các bước tiếp theo cho đến khi A biết rằng việc xử lý yêu cầu đã hoàn tất.

Một số yêu cầu sẽ dài hơn những yêu cầu khác. Ước tính thời gian xử lý sẽ có sẵn trên A và trên B, có lẽ được sửa đổi khi quá trình xử lý tiếp tục. Những ước tính như vậy có thể được đưa trở lại A vì vậy nó sẽ hiếm khi tạo ra thời gian chờ dương tính giả. Hãy nghĩ về nó như một thông điệp sống còn nói rằng "vẫn hoạt động, vẫn hoạt động".


1

Áp dụng một kéo thay vì chiến lược đẩy. Làm cho mỗi phần kéo thay đổi từ những người khác và cập nhật hồ sơ riêng của mình.

  • A ghi nhật ký những việc B nên làm với hàng đợi
  • B kéo từ hàng đợi của A và thực hiện công việc
  • B ghi lại những thứ nó đã thực hiện vào hàng đợi
  • A kéo từ hàng đợi của B để biết kết quả công việc là gì

(Tôi đang sử dụng hàng đợi từ, nhưng bạn có thể thay thế nhật ký hoặc chủ đề.)

Bạn có thể nướng hàng đợi vào các dịch vụ hoặc bạn có thể có một nhà môi giới tin nhắn riêng. Việc triển khai được đưa vào một dịch vụ có thể đơn giản như GET /jobrequests?from=<timestamp>(với B theo dõi dấu thời gian của yêu cầu công việc được xử lý mới nhất).

Một phần khó khăn của một kiến ​​trúc như vậy là quyết định ít nhất một lần so với ít nhất một lần ngữ nghĩa. Cụ thể: nếu B kéo một mục từ hàng đợi và sau đó gặp sự cố trong khi thực hiện nó, điều gì sẽ xảy ra? Có hai khả năng và phù hợp nhất tùy thuộc vào trường hợp sử dụng của bạn:

  • Ít nhất một lần: B chỉ cam kết điểm nào trong hàng đợi mà nó đã nhận được sau khi hoàn thành một hành động, có nguy cơ thực hiện hành động hai lần. Nếu bạn thiết kế các hành động trở nên bình thường, bạn có thể đạt được hành vi chính xác một lần bằng cách sử dụng phương pháp này. (Tôi sử dụng kafka cho kịch bản này.)
  • Nhiều nhất một lần: B chỉ tiêu thụ mỗi mục hàng một lần. Nếu nó gặp sự cố trong khi thực thi nó, thì mục đó sẽ không bao giờ được thực thi.

Lợi ích của phương pháp này:

  • Các dịch vụ tiêu thụ hàng đợi không cần phải xuất hiện để đẩy hàng đợi xảy ra. Điều này có nghĩa là bạn có thể tự do khởi động lại B trong khi A đang làm việc hoặc khởi động lại A trong khi B đang làm việc. Lưu trữ dự phòng các dịch vụ nền chỉ cần thiết để đảm bảo thời gian đáp ứng tổng thể, không hoạt động đáng tin cậy.
  • Tốc độ kéo của các mục hàng có thể được kiểm soát bởi người tiêu dùng, cho phép bạn tạm thời đệm các đỉnh tải trong hàng đợi.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.