上下文
考虑以下情况:需要创建资源,但操作需要很长时间才能完成。
实际上,这种情况并不少见:毕竟,rest 不是在某些 crud 场景中操作几个数据库行。rest是关于任意资源的操作,资源可能需要大量的计算才能存在。
因此,您基本上有两种选择:
您将强制 api 客户端等待资源实际创建
您可以立即返回一些状态响应,并将创建推迟到以后的某个时间点
例
让我们创建一些不平凡的东西(我使用httpie工具):
1± http post https://api.service.io/stars name='death star' 2http/1.1 201 created 3location: /stars/12345
在这里,我们试图创造一颗死星,正如你所看到的,它被创造出来并被送回去。location
现在,正如你可能想象的那样,创造恒星本身并不是一件容易的事,更不用说当我们想要像死星这样装备的东西时了。这意味着我们将不得不等待一段时间才能看到这种反应。201 created
因此,我们的目标是初始化星形创建,获取确认消息,并享受一些乐趣,直到资源最终准备就绪(如果我们必须不时轮询以检查状态更新,我们就可以了)。
为什么等待并不酷
嗯,因为!
更严重的是,强制api客户端等待本身并没有错。如果在服务器端,你依赖于一些异步循环,并且可以处理疯狂的连接数量,并且如果最终的等待时间是几秒钟(对于你的目的来说是可以接受的),那么你绝对可以停止阅读这篇文章,而不会发现酷孩子已经使用了几年的方法。n
n
异步处理(做错了)
你的第一反应可能是:"如果我立即回来,但把实际的创作推迟到以后的某个时间点,那会怎么样?http 201 created
好吧,你不能那样做。如果您这样做,您将违反http / 1.1:语义和内容协议(更确切地说是rfc 7231的第6.3.2节):
rfc 7231 的 6.3.2 节
201(已创建)状态代码指示请求已得到满足,并已导致创建了一个或多个新资源。请求创建的主要资源由响应中的"位置"标头字段标识,如果未收到"位置"字段,则由有效的请求 uri 标识。
在实际创建资源时必须使用该值,而不是排队等待创建。http 201 created
异步处理(正确完成)
假设我们有一些队列,我们可以在其中放置长时间运行的作业(由某些工作进程定期执行)。
现在,我们可以返回。201 created
202 accepted
rfc 6 的 3.3.7231 节
202(已接受)状态代码指示请求已被接受进行处理,但处理尚未完成。
如您所见,这正是我们所追求的!
我们知道要返回什么状态代码,那么标头呢?简单。api 将返回已创建的排队任务的位置,而不是实际资源的位置:location
1± http post https://api.service.io/stars name='death star' 2http/1.1 202 accepted 3location: /queue/12345
:火: 专业提示:允许返回有效负载和响应,您应该利用这个机会返回一些有意义的东西(例如任务完成的eta,当前状态等)。202 accepted
实施说明
在延迟处理方面,有几个与实现相关的问题经常被问到。让我们回顾一下它们。
问题 1.如何了解资源何时最终可用?
您需要查询排队的任务(这就是 api 返回标头的原因):location
1± http get https://api.service.io/queue/12345 2http/1.1 200 ok 3 45 pending 62 mins. 7 8
:火: 专业提示:遵循 hateoas 约束,我们可以添加指向允许取消/删除排队任务的状态的链接。
问题 2.创建资源时会发生什么情况,队列任务资源如何更改?
创建资源后,api 应针对排队任务的所有后续请求使用状态代码进行响应:303 see other
1± http get https://api.service.io/queue/12345 2http/1.1 303 see other 3location: /stars/97865
问题 3.创建完成后,如何处理任务资源?
在创建资源时,其相应的任务可用,您可以向其查询状态。
创建最初所需的资源后,有两种替代方法可以处理临时任务资源:
api 客户端必须发出请求,以便服务器清除它。在此之前,服务器将使用状态进行响应。删除后,将返回以供后续请求使用。
delete
303 see other
404 not found
get /queue/12345
或者,垃圾回收可以是服务器的工作:一旦任务完成,服务器可以安全地删除它并使用后续请求进行响应。
410 gone
get /queue/12345
:火: 专业提示:服务器可以为所有新的排队任务分配一些到期日期,并且无论完成状态如何,这些任务都会过期。这样,服务器会限制任何给定任务可以运行的时间(最大值)。这种策略并不违背所宣布的目的,并且允许资源永远不会存在。202 accepted
引用
thijssen, j. rest 中的异步操作
thijssen, j. rest cookbook
以上转自:https://farazdagi.com/posts/2014-10-16-rest-long-running-jobs/
以下转自:http://www.ruanyifeng.com/blog/2018/12/async-api-design.html?utm_source=tuicool&utm_medium=referral
网站的前后端通信,往往会有异步请求,这时应该怎么设计 api?
我最近读到一篇文章,作者介绍了他的做法,设计得很精细,我觉得值得借鉴,可以当作异步 api 的标准设计。
一、同步 api
为了便于比较,先看看同步 api 的设计。下面是一个很简单的例子。
客户端发出一个请求,要求创建资源。
post https://api.service.io/stars name='death star'
服务器回应 201。
http/1.1 201 created location: /stars/12345
201 created
告诉客户端,请求成功,资源已经创建。新的资源的网址请看location
字段。
二、异步请求
如果服务器不能立即返回结果,就形成了异步操作。
客户端的请求还是一样的。
post https://api.service.io/stars name='death star'
服务器回应 202。
http/1.1 202 accepted location: /queue/12345
202 accepted
告诉客户端,请求已经接受,但还没有处理,可以去location
字段查询进展。
除了上面的头信息,服务器的回应如果有数据体,可以返回一些有效信息(比如任务完成的估计时间、当前状态等等)。
三、查询进展
过了一段时间,客户端就发出请求,查询异步处理的进展。
get https://api.service.io/queue/12345
服务器回应 200。
http/1.1 200 okpending 2 mins.
200 ok
告诉客户端,请求成功,具体情况查看数据体。数据体里给出提示,异步操作已成功或还需要等待。
四、异步操作成功
有一种特殊情况,用户查询异步操作的进展的时候,可能会希望,如果异步操作已经完成,就直接跳转到新资源。
这时,服务器回应 303。
http/1.1 303 see other location: /stars/97865
303 see other
告诉客户端,重定向到不同的资源。location
字段就是跳转的目标,也就是新资源的网址。
五、删除查询链接
一旦异步操作完成,客户端可以要求服务器删除查询链接。
delete https://api.service.io/queue/12345
服务器回应 204。
http/1.1 204 no content
204 no content
告诉客户端,删除成功。以后,客户端再访问这个查询链接,服务器回应404 not found
。
如果客户端不删除查询链接,服务器完成异步任务后,也可以自动删除。客户端再请求这个链接,服务器回应410 gone
,表示该链接永久性不再可用。
(完)
麻将胡了pg电子网站的版权属于:月萌api www.moonapi.com,转载请注明出处