Nhắc lại theo tôi:
Các sự kiện REST và không đồng bộ không phải là sự kiện thay thế. Chúng hoàn toàn trực giao.
Bạn có thể có một, hoặc cái kia, hoặc cả hai, hoặc không. Chúng là những công cụ hoàn toàn khác nhau cho các lĩnh vực vấn đề hoàn toàn khác nhau. Trong thực tế, giao tiếp đáp ứng yêu cầu mục đích chung hoàn toàn có khả năng không đồng bộ, hướng sự kiện và chịu lỗi .
Như một ví dụ tầm thường, giao thức AMQP gửi tin nhắn qua kết nối TCP. Trong TCP, mọi gói phải được người nhận thừa nhận . Nếu người gửi gói không nhận được ACK cho gói đó, nó sẽ tiếp tục gửi lại gói đó cho đến khi ACK'd hoặc cho đến khi lớp ứng dụng "từ bỏ" và từ bỏ kết nối. Đây rõ ràng là một mô hình phản hồi yêu cầu không chịu lỗi vì mỗi "yêu cầu gửi gói" phải có "phản hồi xác nhận gói" đi kèm và không thể trả lời kết quả trong toàn bộ kết nối bị lỗi. Tuy nhiên, AMQP, một giao thức được tiêu chuẩn hóa và được áp dụng rộng rãi cho nhắn tin chịu lỗi không đồng bộ, được truyền thông qua TCP! Đưa cái gì?
Khái niệm cốt lõi đang chơi ở đây là nhắn tin chịu lỗi kết nối lỏng lẻo có thể mở rộng được xác định bởi những tin nhắn bạn gửi chứ không phải cách bạn gửi chúng . Nói cách khác, khớp nối lỏng lẻo được xác định ở lớp ứng dụng .
Hãy xem xét hai bên giao tiếp trực tiếp với RESTful HTTP hoặc gián tiếp với nhà môi giới tin nhắn AMQP. Giả sử Bên A muốn tải hình ảnh JPEG lên Bên B, người sẽ làm sắc nét, nén hoặc nâng cao hình ảnh. Bên A không cần hình ảnh được xử lý ngay lập tức, nhưng không yêu cầu tham chiếu đến nó để sử dụng và truy xuất trong tương lai. Đây là một cách có thể đi trong REST:
- Bên A gửi
POST
tin nhắn yêu cầu HTTP đến Bên B vớiContent-Type: image/jpeg
- Bên B xử lý hình ảnh (trong một thời gian dài nếu nó lớn) trong khi Bên A chờ đợi, có thể làm những việc khác
- Bên B gửi
201 Created
thông điệp phản hồi HTTP đến Bên A với Content-Location: <url>
tiêu đề liên kết đến hình ảnh được xử lý
- Bên A xem xét công việc của mình được thực hiện vì hiện tại có tham chiếu đến hình ảnh được xử lý
- Thỉnh thoảng trong tương lai khi Bên A cần hình ảnh được xử lý, nó NHẬN nó bằng cách sử dụng liên kết từ
Content-Location
tiêu đề trước đó
Các 201 Created
mã phản hồi nói với một khách hàng không chỉ là yêu cầu của họ thành công, nó cũng tạo ra một nguồn lực mới. Trong phản hồi 201, Content-Location
tiêu đề là một liên kết đến tài nguyên đã tạo. Điều này được quy định trong RFC 7231 Phần 6.3.2 và 3.1.4.2.
Bây giờ, hãy xem cách tương tác này hoạt động qua giao thức RPC giả định trên AMQP:
- Bên A gửi cho nhà môi giới tin nhắn AMQP (gọi là Messenger) một tin nhắn có chứa hình ảnh và hướng dẫn định tuyến đến Bên B để xử lý, sau đó trả lời Bên A bằng một địa chỉ nào đó cho hình ảnh
- Bên A chờ đợi, có thể làm những việc khác
- Messenger gửi tin nhắn ban đầu của Bên A đến Bên B
- Bên B xử lý tin nhắn
- Bên B gửi cho Messenger một tin nhắn chứa địa chỉ cho hình ảnh được xử lý và hướng dẫn định tuyến tin nhắn đó đến Bên A
- Messenger gửi cho bên A tin nhắn từ bên B chứa địa chỉ hình ảnh được xử lý
- Bên A xem xét công việc của mình được thực hiện vì hiện tại có tham chiếu đến hình ảnh được xử lý
- Thỉnh thoảng trong tương lai khi Bên A cần hình ảnh, nó sẽ lấy hình ảnh bằng địa chỉ (có thể bằng cách gửi tin nhắn cho một số bên khác)
Bạn có thấy vấn đề ở đây không? Trong cả hai trường hợp, Bên A không thể có được địa chỉ hình ảnh cho đến khi Bên B xử lý hình ảnh . Tuy nhiên, bên A không cần hình ảnh ngay lập tức và, bằng mọi quyền, không thể quan tâm ít hơn nếu việc xử lý kết thúc!
Chúng ta có thể khắc phục điều này khá dễ dàng trong trường hợp AMQP bằng cách yêu cầu Bên B nói với B rằng B chấp nhận hình ảnh để xử lý, cung cấp cho A địa chỉ nơi hình ảnh sẽ ở sau khi quá trình xử lý hoàn tất. Sau đó, bên B có thể gửi tin nhắn cho A đôi khi trong tương lai cho biết quá trình xử lý ảnh đã kết thúc. AMQP nhắn tin để giải cứu!
Ngoại trừ đoán những gì: bạn có thể đạt được điều tương tự với REST . Trong ví dụ AMQP, chúng tôi đã thay đổi thông báo "đây là hình ảnh được xử lý" thành thông báo "hình ảnh đang xử lý, bạn có thể lấy nó sau". Để làm điều đó trong RESTful HTTP, chúng tôi sẽ sử dụng 202 Accepted
mã và Content-Location
một lần nữa:
- Bên A gửi
POST
tin nhắn HTTP đến Bên B vớiContent-Type: image/jpeg
- Bên B ngay lập tức gửi lại
202 Accepted
phản hồi có chứa một số loại nội dung "hoạt động không đồng bộ" mô tả việc xử lý đã kết thúc hay chưa và hình ảnh sẽ khả dụng khi xử lý xong. Cũng bao gồm là một Content-Location: <link>
tiêu đề, trong một 202 Accepted
phản hồi, là một liên kết đến tài nguyên được đại diện bởi bất kỳ cơ quan phản hồi nào. Trong trường hợp này, điều đó có nghĩa là đó là một liên kết đến hoạt động không đồng bộ của chúng tôi!
- Bên A xem xét công việc của mình được thực hiện vì hiện tại có tham chiếu đến hình ảnh được xử lý
- Thỉnh thoảng trong tương lai khi Bên A cần hình ảnh được xử lý, trước tiên, nó NHẬN tài nguyên hoạt động không đồng bộ được liên kết trong
Content-Location
tiêu đề để xác định xem việc xử lý đã kết thúc chưa. Nếu vậy, Bên A sau đó sử dụng liên kết trong chính hoạt động không đồng bộ để NHẬN hình ảnh được xử lý.
Sự khác biệt duy nhất ở đây là trong mô hình AMQP, Bên B nói với Bên A khi quá trình xử lý ảnh được thực hiện. Nhưng trong mô hình REST, Bên A kiểm tra xem việc xử lý có được thực hiện ngay trước khi nó thực sự cần hình ảnh hay không. Những cách tiếp cận này có khả năng mở rộng tương đương . Khi hệ thống trở nên lớn hơn, số lượng tin nhắn được gửi trong cả chiến lược REST không đồng bộ và chiến lược REST không đồng bộ tăng lên với độ phức tạp tiệm cận tương đương. Sự khác biệt duy nhất là máy khách đang gửi thêm một tin nhắn thay vì máy chủ.
Nhưng cách tiếp cận REST có thêm một vài mánh khóe: khám phá năng động và đàm phán giao thức . Xem xét cách cả hai tương tác REST đồng bộ hóa và không đồng bộ bắt đầu. Bên A đã gửi cùng một yêu cầu chính xác cho Bên B, với sự khác biệt duy nhất là loại thông điệp thành công cụ thể mà Bên B đã phản hồi. Điều gì xảy ra nếu Bên A muốn chọn xử lý hình ảnh là đồng bộ hay không đồng bộ? Điều gì xảy ra nếu Bên A không biết liệu Bên B thậm chí có khả năng xử lý không đồng bộ không?
Chà, HTTP thực sự đã có một giao thức chuẩn hóa cho việc này rồi! Nó được gọi là Tùy chọn HTTP, cụ thể là respond-async
tùy chọn của RFC 7240 Mục 4.1. Nếu Bên A mong muốn có phản hồi không đồng bộ, nó sẽ bao gồm một Prefer: respond-async
tiêu đề với yêu cầu POST ban đầu. Nếu Bên B quyết định tôn trọng yêu cầu này, nó sẽ gửi lại 202 Accepted
phản hồi bao gồm a Preference-Applied: respond-async
. Nếu không, Bên B chỉ đơn giản là bỏ qua các Prefer
tiêu đề và gửi lại 201 Created
như bình thường.
Điều này cho phép Bên A đàm phán với máy chủ, tự động thích ứng với bất kỳ triển khai xử lý hình ảnh nào mà nó đang nói đến. Hơn nữa, việc sử dụng các liên kết rõ ràng có nghĩa là Bên A không cần biết về bất kỳ bên nào ngoài B: không có nhà môi giới tin nhắn AMQP, không có Bên C bí ẩn nào biết cách thực sự biến địa chỉ hình ảnh thành dữ liệu hình ảnh, không có B-Async thứ hai bên nếu cả hai yêu cầu đồng bộ và không đồng bộ cần phải được thực hiện, v.v ... Nó chỉ đơn giản mô tả những gì nó cần, những gì nó sẽ tùy chọn, và sau đó phản ứng với mã trạng thái, nội dung phản hồi và liên kết. Thêm vào trongCache-Control
tiêu đề cho các hướng dẫn rõ ràng về thời điểm giữ bản sao dữ liệu cục bộ và bây giờ các máy chủ có thể thương lượng với khách hàng mà tài nguyên khách hàng có thể giữ bản sao cục bộ (hoặc thậm chí ngoại tuyến!). Đây là cách bạn xây dựng các dịch vụ siêu nhỏ chịu lỗi kết hợp lỏng lẻo trong REST.