Giao dịch trên các dịch vụ micros REST?


195

Giả sử chúng ta có một dịch vụ siêu nhỏ, ví REST REST và cổng API kết nối mọi thứ lại với nhau. Khi Bob đăng ký trên trang web của chúng tôi, cổng API của chúng tôi cần tạo người dùng thông qua microservice User và ví thông qua microservice Wallet.

Bây giờ đây là một vài tình huống mà mọi thứ có thể đi sai:

  • Tạo người dùng Bob không thành công: không sao, chúng tôi chỉ trả lại thông báo lỗi cho Bob. Chúng tôi đang sử dụng các giao dịch SQL để không ai thấy Bob trong hệ thống. Mọi thứ đều tốt :)

  • Người dùng Bob được tạo nhưng trước khi Ví của chúng tôi có thể được tạo, cổng API của chúng tôi gặp sự cố. Bây giờ chúng tôi có một Người dùng không có ví (dữ liệu không nhất quán).

  • Người dùng Bob được tạo và khi chúng tôi đang tạo Ví, kết nối HTTP sẽ giảm. Việc tạo ví có thể đã thành công hoặc có thể không.

Những giải pháp nào có sẵn để ngăn chặn sự không thống nhất dữ liệu này xảy ra? Có các mẫu cho phép các giao dịch trải rộng trên nhiều yêu cầu REST không? Tôi đã đọc trang Wikipedia về Cam kết hai pha dường như chạm vào vấn đề này nhưng tôi không chắc chắn cách áp dụng nó trong thực tế. Giao dịch phân tán nguyên tử này : một bài viết thiết kế RESTful cũng có vẻ thú vị mặc dù tôi chưa đọc nó.

Ngoài ra, tôi biết REST có thể không phù hợp với trường hợp sử dụng này. Có lẽ cách chính xác để xử lý tình huống này để loại bỏ hoàn toàn REST và sử dụng một giao thức giao tiếp khác như hệ thống xếp hàng tin nhắn? Hoặc tôi nên thực thi tính nhất quán trong mã ứng dụng của mình (ví dụ: bằng cách có một công việc nền phát hiện sự không nhất quán và sửa chúng hoặc bằng cách sử dụng thuộc tính "trạng thái" trên mô hình Người dùng của tôi với các giá trị "tạo", "tạo", v.v.)?



3
Nếu người dùng không có ý nghĩa nếu không có ví, tại sao phải tạo một microservice riêng cho nó? Có thể là một cái gì đó không đúng với kiến ​​trúc ở nơi đầu tiên? Tại sao bạn cần một cổng API chung, btw? Có bất kỳ lý do cụ thể cho nó?
Vladislav Rastrusny

4
@VladislavRastrusny đó là một ví dụ hư cấu, nhưng bạn có thể nghĩ về dịch vụ ví như được xử lý bởi Stripe chẳng hạn.
Olivier Lalonde

Bạn có thể sử dụng trình quản lý quy trình để theo dõi giao dịch (mẫu trình quản lý quy trình) hoặc để từng microservice biết cách kích hoạt rollback (mẫu trình quản lý saga) hoặc thực hiện một số loại cam kết hai pha ( blog.aspiresys.com/software-product-engineering / sản xuất / Bắn )
pate

@VladislavRastrusny "Nếu người dùng không có ý nghĩa nếu không có ví, tại sao phải tạo một dịch vụ siêu nhỏ riêng cho nó" - ví dụ, ngoài thực tế, Người dùng không thể tồn tại mà không có Ví mà họ không có mã chung. Vì vậy, hai nhóm sẽ phát triển và triển khai microservice User và Wallet một cách độc lập. Đó không phải là toàn bộ quan điểm của việc làm microservice ở nơi đầu tiên?
Nik

Câu trả lời:


148

Điều gì không có ý nghĩa:

  • giao dịch phân phối với các dịch vụ REST . Các dịch vụ REST theo định nghĩa là không trạng thái, vì vậy chúng không nên là người tham gia trong một ranh giới giao dịch kéo dài hơn một dịch vụ. Kịch bản trường hợp sử dụng đăng ký người dùng của bạn có ý nghĩa, nhưng thiết kế với REST microservice để tạo dữ liệu Người dùng và Ví là không tốt.

Điều gì sẽ khiến bạn đau đầu:

  • EJB với các giao dịch phân tán . Đó là một trong những điều hoạt động trên lý thuyết nhưng không thực tế. Ngay bây giờ tôi đang cố gắng để làm cho một giao dịch phân tán hoạt động cho các EJB từ xa trên các phiên bản JBoss EAP 6.3. Chúng tôi đã nói chuyện với bộ phận hỗ trợ của RedHat trong nhiều tuần và nó vẫn chưa hoạt động.
  • Giải pháp cam kết hai pha nói chung . Tôi nghĩ rằng giao thức 2PC là một thuật toán tuyệt vời (nhiều năm trước tôi đã triển khai nó trong C với RPC). Nó đòi hỏi các cơ chế phục hồi thất bại toàn diện, với các lần thử lại, kho lưu trữ trạng thái, v.v ... Tất cả sự phức tạp được ẩn trong khung giao dịch (ví dụ: JBoss Arjuna). Tuy nhiên, 2PC không phải là bằng chứng thất bại. Có những tình huống giao dịch đơn giản là không thể hoàn thành. Sau đó, bạn cần xác định và sửa lỗi không thống nhất cơ sở dữ liệu bằng tay. Nó có thể xảy ra một lần trong một triệu giao dịch nếu bạn may mắn, nhưng nó có thể xảy ra một lần trong mỗi 100 giao dịch tùy thuộc vào nền tảng và kịch bản của bạn.
  • Sagas (Bồi thường giao dịch) . Có chi phí thực hiện trong việc tạo ra các hoạt động bù và cơ chế phối hợp để kích hoạt bù vào cuối. Nhưng bồi thường cũng không phải là bằng chứng thất bại. Bạn vẫn có thể kết thúc với sự không nhất quán (= một số đau đầu).

Điều gì có lẽ là sự thay thế tốt nhất:

  • Sự thống nhất cuối cùng . Cả giao dịch phân tán giống như ACID và giao dịch bù đều không phải là bằng chứng và cả hai đều có thể dẫn đến sự không nhất quán. Sự thống nhất cuối cùng thường tốt hơn "sự không nhất quán thường xuyên". Có nhiều giải pháp thiết kế khác nhau, như:
    • Bạn có thể tạo một giải pháp mạnh mẽ hơn bằng cách sử dụng giao tiếp không đồng bộ. Trong kịch bản của bạn, khi Bob đăng ký, cổng API có thể gửi tin nhắn đến hàng đợi Người dùng mới và trả lời ngay cho người dùng nói rằng "Bạn sẽ nhận được email để xác nhận việc tạo tài khoản". Một dịch vụ tiêu dùng hàng đợi có thể xử lý tin nhắn, thực hiện các thay đổi cơ sở dữ liệu trong một giao dịch và gửi email đến Bob để thông báo cho việc tạo tài khoản.
    • Microservice User tạo bản ghi người dùng bản ghi ví trong cùng một cơ sở dữ liệu . Trong trường hợp này, cửa hàng ví trong microservice User là bản sao của cửa hàng ví chính chỉ hiển thị với microservice Wallet. Có một cơ chế đồng bộ hóa dữ liệu dựa trên kích hoạt hoặc khởi động định kỳ để gửi các thay đổi dữ liệu (ví dụ: ví mới) từ bản sao đến bản gốc và ngược lại.

Nhưng nếu bạn cần phản hồi đồng bộ thì sao?

  • Làm lại các dịch vụ siêu nhỏ . Nếu giải pháp với hàng đợi không hoạt động vì người tiêu dùng dịch vụ cần phản hồi ngay lập tức, thì tôi muốn sửa lại chức năng Người dùng và Ví để được kết hợp trong cùng một dịch vụ (hoặc ít nhất là trong cùng một VM để tránh các giao dịch phân tán ). Vâng, đó là một bước xa hơn từ microservice và gần hơn với một tảng đá nguyên khối, nhưng sẽ giúp bạn khỏi đau đầu.

4
Sự nhất quán cuối cùng đã làm việc cho tôi. Trong trường hợp này, hàng đợi "Người dùng mới" phải sẵn sàng cao và có khả năng phục hồi.
Ram Bavireddi

@RamBavireddi làm Kafka hoặc RabbitMQ hỗ trợ hàng đợi kiên cường?
v.oddou

@ v.oddou Vâng, họ làm.
Ram Bavariaireddi

2
@PauloMerson Tôi không chắc chắn về cách bạn khác biệt Bồi thường giao dịch với tính nhất quán cuối cùng. Điều gì sẽ xảy ra nếu, trong tính nhất quán cuối cùng của bạn, việc tạo ví không thành công?
balsick

2
@balsick Một trong những thách thức của cài đặt tính nhất quán cuối cùng là tăng độ phức tạp trong thiết kế. Kiểm tra tính nhất quán và các sự kiện sửa chữa thường được yêu cầu. Thiết kế của giải pháp khác nhau. Trong câu trả lời, tôi đề xuất tình huống trong đó bản ghi Wallet được tạo trong cơ sở dữ liệu khi xử lý tin nhắn được gửi qua một nhà môi giới tin nhắn. Trong trường hợp này, chúng tôi có thể đặt Kênh Thư chết, nghĩa là, nếu xử lý tin nhắn đó phát sinh lỗi, chúng tôi có thể gửi tin nhắn đến hàng đợi thư chết và thông báo cho nhóm chịu trách nhiệm về "Ví".
Paulo Merson

66

Đây là một câu hỏi kinh điển tôi đã được hỏi trong một cuộc phỏng vấn gần đây Làm thế nào để gọi nhiều dịch vụ web và vẫn bảo tồn một số loại xử lý lỗi ở giữa nhiệm vụ. Ngày nay, trong điện toán hiệu năng cao, chúng tôi tránh hai lần cam kết. Tôi đã đọc một bài báo cách đây nhiều năm về cái được gọi là "mô hình Starbuck" cho các giao dịch: Nghĩ về quá trình đặt hàng, thanh toán, chuẩn bị và nhận cà phê bạn đặt hàng tại Starbuck ... Tôi mô tả quá mức mọi thứ nhưng mô hình cam kết hai giai đoạn sẽ đề nghị rằng toàn bộ quá trình sẽ là một giao dịch gói duy nhất cho tất cả các bước liên quan cho đến khi bạn nhận được cà phê của mình. Tuy nhiên, với mô hình này, tất cả nhân viên sẽ chờ đợi và ngừng làm việc cho đến khi bạn nhận được cà phê của mình. Bạn thấy bức tranh?

Thay vào đó, "mô hình Starbuck" có năng suất cao hơn bằng cách làm theo mô hình "nỗ lực tốt nhất" và bù đắp cho các lỗi trong quy trình. Đầu tiên, họ chắc chắn rằng bạn trả tiền! Sau đó, có hàng đợi tin nhắn với đơn đặt hàng của bạn được gắn vào cốc. Nếu có sự cố xảy ra trong quy trình, như bạn không nhận được cà phê của mình, đó không phải là những gì bạn đã đặt hàng, v.v., chúng tôi tham gia vào quy trình bồi thường và chúng tôi đảm bảo bạn có được những gì bạn muốn hoặc hoàn lại tiền cho bạn, Đây là mô hình hiệu quả nhất để tăng năng suất.

Đôi khi, starbuck đang lãng phí một ly cà phê nhưng quá trình tổng thể là hiệu quả. Có những thủ thuật khác để suy nghĩ khi bạn xây dựng các dịch vụ web của mình như thiết kế chúng theo cách mà chúng có thể được gọi bất kỳ số lần nào và vẫn cung cấp kết quả cuối cùng. Vì vậy, đề nghị của tôi là:

  • Đừng quá ổn khi xác định các dịch vụ web của bạn (Tôi không tin về sự cường điệu của dịch vụ vi mô xảy ra trong những ngày này: quá nhiều rủi ro khi đi quá xa);

  • Async tăng hiệu suất vì vậy thích không đồng bộ, gửi thông báo qua email bất cứ khi nào có thể.

  • Xây dựng các dịch vụ thông minh hơn để làm cho chúng "có thể nhớ lại" bất kỳ số lần nào, xử lý bằng uid hoặc taskid sẽ theo thứ tự từ dưới lên trên cho đến khi kết thúc, xác thực các quy tắc kinh doanh trong mỗi bước;

  • Sử dụng hàng đợi tin nhắn (JMS hoặc các loại khác) và chuyển hướng đến bộ xử lý xử lý lỗi sẽ áp dụng các hoạt động cho "rollback" bằng cách áp dụng các hoạt động ngược lại, bằng cách đó, làm việc với thứ tự async sẽ yêu cầu một số loại hàng đợi để xác thực trạng thái hiện tại của quy trình, vì vậy hãy xem xét điều đó;

  • Trong phương sách cuối cùng, (vì nó có thể không xảy ra thường xuyên), hãy đặt nó vào hàng đợi để xử lý lỗi thủ công.

Hãy quay trở lại với vấn đề ban đầu đã được đăng. Tạo một tài khoản và tạo ví và đảm bảo mọi thứ đã được thực hiện.

Giả sử một dịch vụ web được gọi để điều phối toàn bộ hoạt động.

Mã giả của dịch vụ web sẽ như thế này:

  1. Gọi microservice tạo tài khoản, truyền cho nó một số thông tin và một số tác vụ duy nhất 1.1 Dịch vụ micros micros tạo tài khoản trước tiên sẽ kiểm tra xem tài khoản đó đã được tạo chưa. Một id nhiệm vụ được liên kết với hồ sơ của tài khoản. Microservice phát hiện ra rằng tài khoản không tồn tại nên nó tạo ra nó và lưu trữ id nhiệm vụ. LƯU Ý: dịch vụ này có thể được gọi 2000 lần, nó sẽ luôn thực hiện cùng một kết quả. Dịch vụ trả lời với "biên nhận chứa thông tin tối thiểu để thực hiện thao tác hoàn tác nếu được yêu cầu".

  2. Tạo Ví gọi, cung cấp cho nó ID tài khoản và id tác vụ. Giả sử một điều kiện không hợp lệ và việc tạo ví không thể được thực hiện. Cuộc gọi trở lại với một lỗi nhưng không có gì được tạo ra.

  3. Dàn nhạc được thông báo về lỗi. Nó biết rằng nó cần phải hủy bỏ việc tạo Tài khoản nhưng nó sẽ không tự làm được. Nó sẽ yêu cầu dịch vụ ví thực hiện bằng cách chuyển "biên nhận hoàn tác tối thiểu" nhận được ở cuối bước 1.

  4. Dịch vụ Tài khoản đọc biên lai hoàn tác và biết cách hoàn tác thao tác; biên lai hoàn tác thậm chí có thể bao gồm thông tin về một dịch vụ siêu nhỏ khác mà nó có thể tự gọi mình để thực hiện một phần công việc. Trong tình huống này, biên lai hoàn tác có thể chứa ID tài khoản và có thể một số thông tin bổ sung cần thiết để thực hiện thao tác ngược lại. Trong trường hợp của chúng tôi, để đơn giản hóa mọi thứ, giả sử chỉ cần xóa tài khoản bằng id tài khoản.

  5. Bây giờ, giả sử dịch vụ web không bao giờ nhận được thành công hay thất bại (trong trường hợp này) rằng việc hoàn tác tạo tài khoản đã được thực hiện. Nó chỉ đơn giản sẽ gọi lại dịch vụ hoàn tác của Tài khoản. Và dịch vụ này nên không bao giờ thất bại vì mục tiêu của nó là tài khoản không còn tồn tại. Vì vậy, nó kiểm tra nếu nó tồn tại và thấy không có gì có thể được thực hiện để hoàn tác nó. Vì vậy, nó trả về rằng hoạt động là một thành công.

  6. Dịch vụ web trả về cho người dùng rằng tài khoản không thể được tạo.

Đây là một ví dụ đồng bộ. Chúng tôi có thể quản lý nó theo một cách khác và đưa vụ việc vào hàng đợi tin nhắn được nhắm mục tiêu đến bàn trợ giúp nếu chúng tôi không muốn hệ thống khắc phục hoàn toàn lỗi ". Tôi đã thấy điều này được thực hiện trong một công ty không đủ móc có thể được cung cấp cho hệ thống đầu cuối để khắc phục tình huống. Bàn trợ giúp nhận được tin nhắn có chứa những gì được thực hiện thành công và có đủ thông tin để sửa những thứ giống như nhận được hoàn tác của chúng tôi theo cách hoàn toàn tự động.

Tôi đã thực hiện tìm kiếm và trang web microsoft có mô tả mẫu cho phương pháp này. Nó được gọi là mẫu giao dịch bù:

Bồi thường mô hình giao dịch


2
Bạn có nghĩ rằng bạn có thể mở rộng câu trả lời này để cung cấp lời khuyên cụ thể hơn cho OP. Khi nó đứng, câu trả lời này là hơi mơ hồ và khó hiểu. Mặc dù tôi hiểu cách phục vụ cà phê tại Starbucks, nhưng tôi không rõ các khía cạnh của hệ thống này nên được mô phỏng trong các dịch vụ REST.
JWG

Tôi đã thêm một ví dụ liên quan đến trường hợp ban đầu được cung cấp trong bài viết gốc.
dùng8098437

2
Chỉ cần thêm một liên kết đến mẫu giao dịch bù như mô tả của Microsoft.
dùng8098437

3
Đối với tôi, đây là câu trả lời tốt nhất. Rất đơn giản
Oscar Nevarez

1
Lưu ý rằng các giao dịch bù có thể hoàn toàn không thể thực hiện được trong một số trường hợp phức tạp (như được tô sáng rực rỡ trong tài liệu microsoft). Trong ví dụ này, hãy tưởng tượng trước khi việc tạo ví có thể thất bại, ai đó có thể đọc chi tiết về tài khoản được liên kết bằng cách thực hiện cuộc gọi GET trên dịch vụ Tài khoản, lý tưởng không nên tồn tại ở nơi đầu tiên vì việc tạo tài khoản đã thất bại. Điều này có thể dẫn đến sự không nhất quán dữ liệu. Vấn đề cô lập này nổi tiếng trong mẫu SAGAS.
Anmol Singh Jaggi

32

Tất cả các hệ thống phân tán có vấn đề với tính nhất quán giao dịch. Cách tốt nhất để làm điều này giống như bạn đã nói, có một cam kết hai pha. Có ví và người dùng được tạo trong trạng thái chờ xử lý. Sau khi được tạo, hãy thực hiện một cuộc gọi riêng để kích hoạt người dùng.

Cuộc gọi cuối cùng này sẽ được lặp lại một cách an toàn (trong trường hợp kết nối của bạn bị rớt).

Điều này sẽ đòi hỏi rằng cuộc gọi cuối cùng biết về cả hai bảng (để nó có thể được thực hiện trong một giao dịch JDBC).

Ngoài ra, bạn có thể muốn nghĩ về lý do tại sao bạn rất lo lắng về người dùng mà không có ví. Bạn có tin rằng điều này sẽ gây ra một vấn đề? Nếu vậy, có thể có những cuộc gọi nghỉ ngơi riêng biệt là một ý tưởng tồi. Nếu người dùng không nên tồn tại mà không có ví, thì có lẽ bạn nên thêm ví cho người dùng (trong cuộc gọi POST ban đầu để tạo người dùng).


Cám ơn vì sự gợi ý. Các dịch vụ Người dùng / Ví là hư cấu, chỉ để minh họa điểm. Nhưng tôi đồng ý rằng tôi nên thiết kế hệ thống để tránh sự cần thiết phải giao dịch càng nhiều càng tốt.
Olivier Lalonde

7
Tôi đồng ý với quan điểm thứ hai. Dường như, những gì microservice của bạn, người tạo ra người dùng, cũng nên tạo ví, bởi vì hoạt động này đại diện cho đơn vị công việc nguyên tử. Ngoài ra, bạn có thể đọc trang eipipes.com/docs/IEEE_Software_Design_2PC.pdf
Sattar Imamov

2
Đây thực sự là một ý tưởng tuyệt vời . Hoàn tác là một đau đầu. Nhưng tạo ra một cái gì đó trong trạng thái chờ xử lý ít xâm lấn hơn nhiều. Bất kỳ kiểm tra đã được thực hiện, nhưng chưa có gì dứt khoát được tạo ra. Bây giờ chúng ta chỉ cần kích hoạt các thành phần được tạo. Chúng tôi thậm chí có thể làm điều đó không giao dịch.
Timo

10

IMHO một trong những khía cạnh quan trọng của kiến ​​trúc microservice là giao dịch được giới hạn trong từng dịch vụ micros micros (Nguyên tắc trách nhiệm duy nhất).

Trong ví dụ hiện tại, việc tạo Người dùng sẽ là một giao dịch riêng. Tạo người dùng sẽ đẩy một sự kiện USER_CREATED vào hàng đợi sự kiện. Dịch vụ ví sẽ đăng ký sự kiện USER_CREATED và thực hiện tạo Ví.


1
Giả sử chúng tôi muốn tránh bất kỳ và tất cả 2PC và giả sử rằng Dịch vụ người dùng ghi vào cơ sở dữ liệu, thì chúng tôi không thể đẩy tin nhắn vào hàng đợi sự kiện của Người dùng để giao dịch, điều đó có nghĩa là nó có thể không bao giờ thực hiện được dịch vụ Ví.
Roman Kharkovski

@RomanKharkovski Một điểm quan trọng thực sự. Một cách để giải quyết vấn đề có thể là bắt đầu giao dịch, lưu Người dùng, xuất bản sự kiện (không phải là một phần của giao dịch) và sau đó cam kết giao dịch. (Trường hợp xấu nhất, rất khó xảy ra, cam kết thất bại và những người phản hồi sự kiện sẽ không thể tìm thấy người dùng.)
Timo

1
Sau đó lưu trữ sự kiện vào cơ sở dữ liệu cũng như thực thể. Có một công việc theo lịch trình để xử lý các sự kiện được lưu trữ và gửi chúng cho nhà môi giới tin nhắn. stackoverflow.com/a/52216427/4587961
Yan Khonski

7

Nếu ví của tôi chỉ là một loạt các bản ghi trong cùng một cơ sở dữ liệu sql với người dùng thì có lẽ tôi sẽ đặt mã tạo người dùng và ví trong cùng một dịch vụ và xử lý việc sử dụng các phương tiện giao dịch cơ sở dữ liệu thông thường.

Có vẻ như tôi đang hỏi về những gì xảy ra khi mã tạo ví yêu cầu bạn chạm vào một hệ thống hoặc hệ thống khác? Id nói rằng tất cả phụ thuộc vào mức độ phức tạp và rủi ro của quá trình tạo.

Nếu đó chỉ là vấn đề chạm vào kho dữ liệu đáng tin cậy khác (giả sử không thể tham gia vào các giao dịch sql của bạn), thì tùy thuộc vào các tham số hệ thống tổng thể, tôi có thể sẵn sàng mạo hiểm với cơ hội nhỏ mà việc ghi thứ hai sẽ không xảy ra. Tôi có thể không làm gì, nhưng đưa ra một ngoại lệ và xử lý dữ liệu không nhất quán thông qua một giao dịch bù hoặc thậm chí một số phương pháp đặc biệt. Như tôi luôn nói với các nhà phát triển của mình: "nếu loại điều này xảy ra trong ứng dụng, nó sẽ không được chú ý".

Khi sự phức tạp và rủi ro của việc tạo ví tăng lên, bạn phải thực hiện các bước để cải thiện các rủi ro liên quan. Giả sử một số bước yêu cầu gọi nhiều apis đối tác.

Tại thời điểm này, bạn có thể giới thiệu một hàng đợi tin nhắn cùng với khái niệm người dùng và / hoặc ví được xây dựng một phần.

Một chiến lược đơn giản và hiệu quả để đảm bảo các thực thể của bạn cuối cùng được xây dựng đúng là thử lại các công việc cho đến khi chúng thành công, nhưng phần lớn phụ thuộc vào các trường hợp sử dụng cho ứng dụng của bạn.

Tôi cũng sẽ suy nghĩ lâu dài về lý do tại sao tôi có một bước dễ bị thất bại trong quy trình cung cấp của mình.


4

Một giải pháp đơn giản là bạn tạo người dùng bằng Dịch vụ người dùng và sử dụng xe buýt nhắn tin nơi dịch vụ người dùng phát ra các sự kiện của nó và đăng ký Dịch vụ ví trên xe buýt nhắn tin, lắng nghe sự kiện do người dùng tạo và tạo Ví cho người dùng. Trong lúc này, nếu người dùng vào UI UI để xem Ví của anh ta, hãy kiểm tra xem người dùng vừa được tạo chưa và cho thấy quá trình tạo ví của bạn đang diễn ra, vui lòng kiểm tra sau


3

Những giải pháp nào có sẵn để ngăn chặn sự không thống nhất dữ liệu này xảy ra?

Theo truyền thống, các nhà quản lý giao dịch phân tán được sử dụng. Vài năm trước trong thế giới Java EE, bạn có thể đã tạo các dịch vụ này dưới dạng EJB được triển khai đến các nút khác nhau và cổng API của bạn sẽ thực hiện các cuộc gọi từ xa đến các EJB đó. Máy chủ ứng dụng (nếu được cấu hình đúng) sẽ tự động đảm bảo, sử dụng cam kết hai pha, giao dịch được cam kết hoặc được khôi phục trên mỗi nút, do đó tính nhất quán được đảm bảo. Nhưng điều đó đòi hỏi tất cả các dịch vụ phải được triển khai trên cùng một loại máy chủ ứng dụng (để chúng tương thích) và trong thực tế chỉ hoạt động với các dịch vụ được triển khai bởi một công ty.

Có các mẫu cho phép các giao dịch trải rộng trên nhiều yêu cầu REST không?

Đối với SOAP (ok, không phải REST), có đặc tả WS-AT nhưng không có dịch vụ nào tôi từng tích hợp có hỗ trợ điều đó. Đối với REST, JBoss có một cái gì đó trong đường ống . Mặt khác, "mẫu" là tìm một sản phẩm mà bạn có thể cắm vào kiến ​​trúc của mình hoặc xây dựng giải pháp của riêng bạn (không được đề xuất).

Tôi đã xuất bản một sản phẩm như vậy cho Java EE: https://github.com/maxant/genericconnector

Theo tài liệu mà bạn tham khảo, đó cũng là mẫu Thử-Hủy / Xác nhận và Sản phẩm được liên kết từ Atomikos.

Động cơ BPEL xử lý tính nhất quán giữa các dịch vụ được triển khai từ xa bằng cách sử dụng bù.

Ngoài ra, tôi biết REST có thể không phù hợp với trường hợp sử dụng này. Có lẽ cách chính xác để xử lý tình huống này để loại bỏ hoàn toàn REST và sử dụng một giao thức giao tiếp khác như hệ thống xếp hàng tin nhắn?

Có nhiều cách "ràng buộc" các tài nguyên phi giao dịch vào một giao dịch:

  • Như bạn đề xuất, bạn có thể sử dụng hàng đợi tin nhắn giao dịch, nhưng nó sẽ không đồng bộ, vì vậy nếu bạn phụ thuộc vào phản hồi thì nó trở nên lộn xộn.
  • Bạn có thể viết thực tế rằng bạn cần gọi các dịch vụ phía sau vào cơ sở dữ liệu của mình và sau đó gọi các dịch vụ phía sau bằng cách sử dụng một lô. Một lần nữa, async, vì vậy có thể nhận được lộn xộn.
  • Bạn có thể sử dụng một công cụ xử lý nghiệp vụ làm cổng API để sắp xếp các dịch vụ siêu nhỏ phía sau.
  • Bạn có thể sử dụng EJB từ xa, như đã đề cập khi bắt đầu, vì điều đó hỗ trợ các giao dịch phân tán ra khỏi hộp.

Hoặc tôi nên thực thi tính nhất quán trong mã ứng dụng của mình (ví dụ: bằng cách có một công việc nền phát hiện sự không nhất quán và sửa chúng hoặc bằng cách sử dụng thuộc tính "trạng thái" trên mô hình Người dùng của tôi với các giá trị "tạo", "tạo", v.v.)?

Chơi quỷ ủng hộ: tại sao xây dựng một cái gì đó như thế, khi có những sản phẩm làm điều đó cho bạn (xem ở trên), và có thể làm điều đó tốt hơn bạn có thể, bởi vì chúng đã được thử và thử nghiệm?


2

Cá nhân tôi thích ý tưởng về Dịch vụ vi mô, các mô-đun được xác định bởi các trường hợp sử dụng, nhưng như câu hỏi của bạn đề cập, chúng có vấn đề thích ứng cho các doanh nghiệp cổ điển như ngân hàng, bảo hiểm, viễn thông, v.v ...

Các giao dịch phân tán, như nhiều người đề cập, không phải là một lựa chọn tốt, mọi người bây giờ sẽ sử dụng nhiều hơn cho các hệ thống nhất quán nhưng tôi không chắc chắn điều này sẽ làm việc cho các ngân hàng, bảo hiểm, v.v ....

Tôi đã viết một blog về giải pháp đề xuất của tôi, có thể điều này có thể giúp bạn ....

https://mehmetsalgar.wordpress.com/2016/11/05/micro-service-fan-out-transaction-probols-and-solutions-with-spring-bootjboss-and-netflix-eureka/


0

Sự nhất quán cuối cùng là chìa khóa ở đây.

  • Một trong những dịch vụ được chọn để trở thành người xử lý chính của sự kiện.
  • Dịch vụ này sẽ xử lý sự kiện ban đầu với một cam kết duy nhất.
  • Trình xử lý chính sẽ chịu trách nhiệm truyền đạt không đồng bộ các hiệu ứng phụ đến các dịch vụ khác.
  • Trình xử lý chính sẽ thực hiện việc sắp xếp các cuộc gọi dịch vụ khác.

Chỉ huy phụ trách giao dịch phân tán và nắm quyền kiểm soát. Nó biết lệnh được thực thi và sẽ phối hợp thực hiện chúng. Trong hầu hết các kịch bản sẽ chỉ có hai hướng dẫn, nhưng nó có thể xử lý nhiều hướng dẫn.

Chỉ huy có trách nhiệm đảm bảo thực hiện tất cả các hướng dẫn, và điều đó có nghĩa là nghỉ hưu. Khi người chỉ huy cố gắng thực hiện cập nhật từ xa và không nhận được phản hồi, nó sẽ không thử lại. Bằng cách này, hệ thống có thể được cấu hình để ít bị lỗi hơn và nó tự phục hồi.

Khi chúng ta thử lại, chúng ta có sự bình tĩnh. Idempotence là tài sản của việc có thể làm điều gì đó gấp đôi sao cho kết quả cuối cùng giống như khi nó được thực hiện một lần duy nhất. Chúng tôi cần sự ổn định tại dịch vụ từ xa hoặc nguồn dữ liệu để trong trường hợp nhận được lệnh nhiều lần, nó chỉ xử lý một lần.

Tính nhất quán cuối cùng Điều này giải quyết hầu hết các thách thức giao dịch phân tán, tuy nhiên chúng ta cần xem xét một vài điểm ở đây. Mỗi giao dịch thất bại sẽ được theo sau bởi một lần thử lại, số lần thử lại tùy thuộc vào bối cảnh.

Tính nhất quán là cuối cùng, trong khi hệ thống không ở trạng thái nhất quán trong quá trình thử lại, ví dụ: nếu khách hàng đã đặt mua một cuốn sách và thực hiện thanh toán và sau đó cập nhật số lượng chứng khoán. Nếu các hoạt động cập nhật chứng khoán thất bại và giả sử rằng đó là cổ phiếu cuối cùng có sẵn, cuốn sách sẽ vẫn có sẵn cho đến khi hoạt động thử lại để cập nhật chứng khoán đã thành công. Sau khi thử lại thành công, hệ thống của bạn sẽ nhất quán.


-2

Tại sao không sử dụng nền tảng Quản lý API (APIM) hỗ trợ lập trình / lập trình? Vì vậy, bạn sẽ có thể xây dựng dịch vụ tổng hợp trong APIM mà không làm phiền các dịch vụ vi mô. Tôi đã thiết kế bằng APIGEE cho mục đích này.

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.