2012-11-09 22 views
7

Trong một SOA RESTful, giả sử tôi đưa ra yêu cầu POST qua AJAX nhưng tôi không nhận được phản hồi trước khi yêu cầu hết thời gian. Hơn nữa giả sử việc gửi lại yêu cầu sẽ có hại. POST không phải là idempotent. Ví dụ: có thể tôi đăng một khoản tiền chuyển khoản ngân hàng. Nếu tôi không nhận được phản hồi, tôi không biết liệu máy chủ có xử lý yêu cầu hay không.Cách xử lý các yêu cầu POST đã hết thời gian

Cách tốt nhất để giải quyết vấn đề này là gì, giả sử tôi có quyền kiểm soát phía máy khách và bên dịch vụ?

Suy nghĩ ban đầu của tôi là bao gồm một nonce (ví dụ: id giả; một số loại định danh duy nhất) với mỗi yêu cầu POST; ví dụ. có lẽ là một giá trị trong tiêu đề If-None-Match. Với cách tiếp cận này, phía máy khách có thể lập trình lại một yêu cầu được hẹn giờ với cùng một id giả và máy chủ có thể từ chối nó nếu nó chứa một giá trị lặp lại.

+1

nếu bạn không nhận được phản hồi sau một thời gian chờ nhất định, chỉ cần giả sử nó không thành công và yêu cầu khách hàng thử lại hoặc hủy. rõ ràng là mã trên máy chủ nên kiểm tra cùng một id. – alfred

+0

Để rõ ràng, id giả này không có nghĩa là * id tài nguyên * - Tôi không trực tiếp giải quyết tài nguyên. Tôi đang sử dụng POST như dự định; cụ thể là, BẬT cho trình xử lý tài nguyên (ví dụ:/Chuyển, không phải/Chuyển khoản/). Nếu không, tôi sẽ không làm một POST ở nơi đầu tiên. – johnr

+0

Đây là một câu hỏi tương tự như "[Tránh các POST trùng lặp với REST] (http://stackoverflow.com/q/15159274/1347968)". – siegi

Trả lời

4

Có một số cách tôi đã nghe nói về để cố gắng giải quyết này

  1. Lấy trạng thái hiện tại.

    Thiết kế dịch vụ sao cho nếu POST không thành công, khách hàng có thể phát hành GET trên cùng một tài nguyên và dựa trên dữ liệu được trả lại, họ có thể xác định xem POST có thành công không.

    Vấn đề với cách tiếp cận này là trong trường hợp POST tạo mục mới trong bộ sưu tập, có thể khó để khách hàng xác định xem bài đăng có thành công hay không (nghĩa là bài đăng của tôi đã thêm mục đó hoặc đã làm người khác không?)

  2. If-Match

    Sử dụng If-Match tiêu đề để ngăn chặn sự POST từ được lặp đi lặp lại. ví dụ: nếu POST đang thêm một mục vào bộ sưu tập và bộ sưu tập hiện có ETag của 737060cd8c284d8af7ad3082f209582d. Nếu If-Match của 737060cd8c284d8af7ad3082f209582d được sử dụng trên POST, thì POST sẽ chỉ thành công nếu bộ sưu tập của ETag vẫn là 737060cd8c284d8af7ad3082f209582d, sẽ thêm mục này và dẫn đến một bộ sưu tập mới ETag. Việc lặp lại POST ở giai đoạn này sẽ chỉ trả lại 412 Precondition Failed.

    Vấn đề với cách tiếp cận này là khi bạn nhận được 412 Precondition Failed, bạn không thể chắc chắn nếu POST của bạn đã sửa đổi bộ sưu tập hay của người khác.

  3. POST thì PUT

    Thiết kế dịch vụ của bạn sẽ không bao giờ tồn tại dữ liệu từ một POST. Thay vào đó, POST tạo tài nguyên tạm thời với nội dung POST, trong trạng thái "Đang chờ xử lý". Tài nguyên tạm thời này sau đó được "cam kết" với một PUT. Với cách tiếp cận này, bạn không quan tâm liệu thời gian POST của bạn đã hết, chỉ cần yêu cầu POST một lần nữa và lần này bạn hy vọng sẽ nhận được tài nguyên tạm thời của bạn. Nếu PUT để cam kết thời gian của tài nguyên, bạn cũng không quan tâm, vì PUT là idempotent.

    Nhược điểm thực sự duy nhất của phương pháp này là công việc phụ cần thiết để quản lý tài nguyên tạm thời và nỗ lực bổ sung cần thiết trong ứng dụng khách.

    Cập nhật

  4. nonce

    Việc sử dụng một nonce (a.k.ID thông báo, ID giao dịch, ID yêu cầu, ID tương quan) trong yêu cầu là cách tiếp cận chung để giải quyết vấn đề này; tuy nhiên nó có thể có vấn đề về khả năng mở rộng. Nếu bạn cam kết từ chối tất cả các POST sử dụng nonce trước đó, thì bạn cần phải quét các bản ghi POST hiện có để xác định xem nonce đã được sử dụng chưa. Không phải là một vấn đề khi bạn chỉ có vài nghìn BÀI ĐĂNG, nhưng nó có thể trở thành vấn đề khi bạn có hàng triệu (đặc biệt nếu bạn không lưu trữ các nonces theo cách nhanh chóng truy vấn). Bạn có thể giảm thiểu điều này bằng cách giảm cam kết từ chối tất cả các POST sử dụng nonce trước đó trong một khoảng thời gian nhất định (ví dụ: 24 giờ trước), nhưng nếu POST đầu tiên hết giờ và khách hàng bị ngắt kết nối trong khung thời gian đó, thì họ quay trở lại vị trí cũ, nơi họ không biết liệu POST đầu tiên có thành công hay không và không có cách nào để xác định xem họ có nên lặp lại hay không.

+1

Còn cách tôi đề xuất thì sao? Bạn có nghĩ rằng nó là khả thi? – johnr

+0

@johnr Tôi đã cập nhật câu trả lời của mình để bao gồm nonces –

+1

+1. Cá nhân tôi thích lựa chọn thứ ba; tạo tài nguyên đầu tiên và sau đó sử dụng PUT :) –

Các vấn đề liên quan