购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

队列

队列是实现发布/订阅模式的另一种方式。在上一节讨论的发布/订阅模式中,主题的每个订阅者都能接收主题内的所有消息。在队列模型中,只有一个订阅者可以接收被发送到主题的每一条消息。队列模型解决的是一种特定的发布/订阅问题,即队列内的每一条消息都代表一个需要完成的任务,而订阅者负责执行该任务。以聚会的邀请过程为例(如图 2-3 所示),队列中的消息可以被看作一份任何人都能接收到的邀请(左图),事件流中的消息可以被看作一份给特定人的邀请(右图)。

图2-3 左边是普通的聚会邀请,右边是给某个特定的人(凯尔西)的邀请

队列模型比事件流模型更为直接,适用的场景范围也更广泛。在这类场景中,客户端接收一个任务并将任务发送到消息系统,然后由下游的一个消费者完成该任务。电子邮件、取消订阅、删除记录、事件编排及创建索引都属于这类范畴的应用案例。

有些消息系统专门用于支持队列模型,这类消息系统被称为工作队列。工作队列旨在管理程序线程的工作负载。工作队列主要有三个作用:1)追踪所有需要完成的任务(一个队列);2)让合适的程序执行任务;3)汇报任务的完成(或未完成)情况。Beanstalkd是一个应用广泛的工作队列型消息系统,其设计非常简洁且不需要用户做额外的配置。通过以下示例我们可以更深入地理解Beanstalkd和队列模型。

Beanstalkd 将工作任务组织为名叫“tube”的逻辑列表。你可以把一个 tube 想象成一个队列,一个集合了待完成任务的有序列表。每个 tube 都有名字,tube 内部会存储job。由于 Beanstalkd 是一个工作队列,因此大部分的语言和概念都与工作任务相关。Beanstalkd中有生产者(也称作发布者),即要求完成任务的程序客户端;同时也有订阅者,即从队列中获取并完成任务的程序客户端。以下示例展示的是一个简单的 Beanstalkd 客户端向“worka”tube发送一个新的job:

现在我们已经发布了一个任务,可以连接到同一个“worka”tube并完成该任务:

在这个模型中,Beanstalkd 服务器负责追踪哪个 job 应该属于哪个 tube,系统中大部分复杂工作由消费者负责,包括:

·获取任务

·将任务标记为已完成

·任务失败时将其重新提交

·维持和Beanstalkd之间的连接

在Beanstalkd中,一个任务由一个工作者(订阅者)完成。 当我们仔细思考工作队列的用途时,会发现任务和消费者(工作者)之间的一对一关系是合理的。然而,该队列模型也有一些隐含的副作用。我们会更深入地探讨这些副作用,以理解队列和事件流的差异。第一,在队列模型里(特别是Beanstalkd API中),我们认为,任务完成后就不需要在系统中继续保留该任务。实际上,当 Beanstalkd 中的任务已完成时,工作者应该显式地把该任务删除。第二,队列没有维护任务间的顺序。这意味着并不能保证工作者会以一定或相同的顺序处理 Beanstalkd 中的任务。对某些应用程序来说,它们需要多个订阅者处理同一个任务;此外,如果能够知道任务到达队列的顺序也会对它们有所帮助。 U7eFozvqi/P+LMz0Gt6u4UKR3XyNARmDJYD7Jb/0t7t3pkSERX32E+wcSU15bEdB

点击中间区域
呼出菜单
上一章
目录
下一章
×