通过REST API进行长轮询
假设您正在为服务器“房间”设计一个基于HTTP的REST API,订阅客户希望监视发生在房间的公共事件(例如,新参与者加入房间,另一个人离开房间,等等......)请求长时间轮询。
从服务器端的角度实现这一点的最佳方式是什么,以便客户端不会错过连续轮询之间的任何事件? 例如,服务器是否应该在队列中存在需要存在的事件队列,直到所有用户都拥有它们?
是否有任何教程,例子,互联网上关于设计这样一个API的一些理论以及从服务器角度应该考虑的所有事情?
非常简短的答案 - 为什么不使用EventStore?
简短的回答 - 为什么不直接使用Event Store作为参考实现,并调整他们的解决方案以符合实施约束?
从服务器端的角度实现这一点的最佳方式是什么,以便客户端不会错过连续轮询之间的任何事件? 例如,服务器是否应该在队列中存在需要存在的事件队列,直到所有用户都拥有它们?
REST本身提供了一些指导。 应用程序状态不应该存储在服务器上; 客户端发送的消息应该包含服务器需要满足请求的任何客户端状态(如事件流中的当前位置)。 请求中标识的资源是抽象的 - 所以客户端可以发送消息给,例如“事件7之后发生的事件”,即使下一个事件还不存在,这也是有意义的。 应该遵守统一的接口,以允许通过服务器控制之外的缓存等进行扩展。 资源状态的表示应该是超媒体,其中的控件允许客户端在消耗当前可用消息之后前进。
HTTP会引入更多的细节。 由于在服务器上没有跟踪客户端状态,因此从队列中读取是安全操作。 因此,应该使用安全的HTTP方法之一(准确地说是GET)进行读取。 由于GET实际上并不支持请求中的内容正文,因此服务器需要的信息应全部打包到请求的标题中。
换句话说,URI用于指定客户端在事件流中的当前位置。
Atom Syndication为事件处理提供了一个很好的超媒体格式 - 事件流映射到一个提要,事件映射到条目。
就其本身而言,这些作品为您提供了一个符合REST架构限制的事件处理器的良好开端。 你只需要长时间轮询就可以了。
为了大致了解您可以如何自行实施长时间轮询,您可以查看Michael Barker(LMAX Disruptor的维护人员)编写的票务演示。
Michael演示中的基本情节是,单个编写器线程正在跟踪(a)当前正在等待更新的所有客户端以及(b)本地事件缓存。 该线程读取一批事件,确定需要通知哪些请求,然后依次响应每个请求,然后继续处理下一批事件。
我倾向于将事件的本地缓存视为环形缓冲区(如破坏程序本身,但是对写入程序线程是私有的)。 作者线程知道(从HTTP请求中的信息)每个客户端在事件流中的位置。 将该位置与环形缓冲区中的当前指针进行比较,每个未决请求可以被分类
远过去客户正在寻找的位置已经从缓存中被逐出。 将客户端重定向到流中该位置的“冷”持久副本,它可以跟随超媒体控件追赶现在。
最近的过去客户端正在寻找的位置目前在缓存中可用,因此立即使用可用的事件生成对客户端的响应,并分发该响应。
不久的将来客户正在寻找的位置在缓存中不可用,但作者预计在SLA到期之前能够满足该请求。 因此,我们将客户停放在更多事件到达之前。
遥远的未来客户寻求的位置在缓存中不可用,并且我们预计我们不会在规定的时间内满足要求。 所以我们现在就回应,让客户决定要做什么。
(如果您的轮询客户端足够多,您需要开始扩展长轮询服务器,那么您需要考虑这些服务器不同步的情况,并且客户端从快速服务器转向一个已经落后的服务器。你需要有适当的仪器,让你跟踪这种情况发生的频率,以便你可以应用适当的补救措施)。
还有一些边缘案例需要考虑 - 如果有大量批次进入,那么在您有机会发送它们之前,您可能需要驱逐您的客户正在等待的事件。
很简单,让客户端传递它们收到的最后一条消息的时间戳(或标识或索引)。
请求GET /rooms/5/messages
将返回服务器知道的所有消息,例如
[
{
"message": "hello",
"timestamp": "2016-07-18T18:44:34Z"
},
{
"message": "world",
"timestamp": "2016-07-18T18:47:16Z"
}
]
然后,客户端使用GET /rooms/5/messages?since=2016-07-18T18:47:16Z
长时间轮询服务器GET /rooms/5/messages?since=2016-07-18T18:47:16Z
它返回自那时以来的所有消息(如果有的话)或者直到房间有新的消息信息。
发送所有事件的参考号码。 Cleint将通过最近收到的事件的参考号码进行通话。 如果没有事件可用,您将阻止长时间轮询请求,并且一旦事件再次以新的参考号码可用,就会响应。 在事件已经可用的情况下,它将返回在请求引用号事件之后生成的所有事件。
链接地址: http://www.djcxy.com/p/35211.html上一篇: side responses to long polling via REST API
下一篇: Jenkins login issue