任务队列和异步接口的正确打开方式
什么是异步接口?
Asynchronous Operations
Certain types of operations might require processing of the request in an asynchronous manner (e.g. validating a bank account, processing an image, etc.) in order to avoid long delays on the client side and prevent long-standing open client connections waiting for the operations to complete. For such use cases, APIs MUST employ the following pattern:
For POST
requests:
- Return the
202 Accepted
HTTP response code. In the response body, include one or more URIs as hypermedia links, which could include:
The final URI of the resource where it will be available in future if the ID and path are already known. Clients can then make an HTTP
GET
request to that URI in order to obtain the completed resource. Until the resource is ready, the final URI SHOULD return the HTTP status code404 Not Found
.{ "rel": "self", "href": "/v1/namespace/resources/{resource_id}", "method": "GET" }
A temporary request queue URI where the status of the operation may be obtained via some temporary identifier. Clients SHOULD make an HTTP
GET
request to obtain the status of the operation which MAY include such information as completion state, ETA, and final URI once it is completed.{ "rel": "self", "href": "/v1/queue/requests/{request_id}, "method": "GET" }"
For PUT
/PATCH
/DELETE
/GET
requests:
Like POST
, you can support PUT/PATCH
/DELETE
/GET
to be asynchronous. The behaviour would be as follows:
- Return the
202 Accepted
HTTP response code. In the response body, include one or more URIs as hypermedia links, which could include:
A temporary request queue URI where the status of the operation may be obtained via some temporary identifier. Clients SHOULD make an HTTP
GET
request to obtain the status of the operation which MAY include such information as completion state, ETA, and final URI once it is completed.{ "rel": "self", "href": "/v1/queue/requests/{request_id}, "method": "GET" }"
APIs that support both synchronous and asynchronous processing for an URI:
APIs that support both synchronous and asynchronous operations for a particular URI and an HTTP method combination, MUST recognize the Prefer
header and exhibit following behavior:
- If the request contains a
Prefer=respond-async
header, the service MUST switch the processing to asynchronous mode. - If the request doesn’t contain a
Prefer=respond-async
header, the service MUST process the request synchronously.
It is desirable that all APIs that implement asynchronous processing, also support webhooks as a mechanism of pushing the processing status to the client.
资料引自:paypal/API Design Patterns And Use Cases:asynchronous-operations
用人话来说
简单来说就是请求过来,直接返回对应的resourceId/request_id,然后可以通过resourceId/request_id查询处理结果
处理过程可能是队列,也可能直接是异步操作
如果还没完成处理,返回404,如果处理完成,正常返回对应数据
好像也没什么讲了….
全文结束吧.
样例代码部分啦
实现逻辑
创建任务,生成”request-id”存储到对应redis zset队列中
同时往redis channel发出任务消息, 后台任务处理服务自行处理此消息(生产者-消费者模式)
任务处理服务处理完消息之后,将处理结果写入redis,request-id为key,结果为value,然后从从redis zset从移除对应的”request-id”
获取request-id处理结果时:如果request-id能查询到对应的任务处理结果,直接返回处理完的数据; 如果request-id还在sortset队列则直接返回404 + 对应的位置n,表示还在处理中,前面还有n个请求;
时序图大概长这样:
喜闻乐见代码时间
RequestService.cs
1 | // RequestService.cs |
1 |
|
1 |
|