NSQ的设计目的(翻译)

NSQ的设计目的

NSQ是simplequeue(部分 simplehttp)的一个继任者,因此被设计为

  • 支持拓扑做到高可用性和消除单点故障
  • 满足更强的消息传递保证需求
  • 限制单个进程的内存使用(通过将部分消息持久化到磁盘)
  • 大大简化生产者和消费者的配置要求
  • 提供一个简单的升级路径
  • 提高效率

    简化了配置和管理

  • 一个nsqd实例被设计成同时处理多个数据流。流被称为主题(topic),一个主题含有一个或者多个通道(channel),每个channel接收topic全部消息的拷贝。实际上,channel被映射成消费topic的一个下游服务(a downstream service )。
  • topic和channels没有事先配置好。topic的创建是在第一次使用的时候,topic的创建方式有两种:(1):第一次推送到某个topic消息的时候;(2):客户端订阅到topic的channel的时候。
  • topics和channels之间全部的缓存数据都是独立的,防治一个缓慢的消费者造成其他channel的消息积压(同样应用在topic层)。
  • 一个channel可以有多个客户端连接。假设全部连接的客户端处于准备接收消息的状态,每个消息会被发送到任意的客户端,如图所示
  • 总而言之,消息是从topic通过多播的方式到channel(每个channel接收topic全部消息的拷贝),平均地从channel分发到consumers。
  • NSQ包含一个help应用程序nsqlookupd,提供了目录服务(a directory service),在那里consumers可以找到那些他们感兴趣的主题的nsqd实例的地址,然后完成订阅。在配置方面,将消费者从生产者中去耦(他们相互独立,只需要知道哪里去联系共同的实例nsqlookupd,但是从来不知道对方),减少维护的复杂性。
  • 在较低的层面,每一个nsqd有一个到nsqlookupd的TCP长连接,用于定期的向nsqlookupd推送自己的状态信息。这些数据会被nsqlookupd用于觉得哪个nsqd会被分配给consumers。对于consumers而言,an HTTP /lookup endpoint is exposed for polling.
  • 为了介绍一个新的不同的消费者,简单地开启使用nsqlookupd 实例地址配置好的NSQ 客户端, 然后没有其他配置信息的改变需要添加到新的consumers或者新的publishers,大大的减少开销和复杂度。
  • Note:在未来的版本中, nsqlookupd使用的用于返回的地址(nsqd的地址)会基于深度、客户端的连接数或者其他的一些智能算法。当前的实现是非常简单的。根本上,目标是确保全部的producers are being read from such that depth stays near zero.
  • 需要说明的是nsqd和nsqlookupd被设计成独立工作的,没有兄弟姐妹之间的沟通和协调(上面的TCP 长连接是什么?)
  • 我们同样认为有方法去查看,检查和集群管理是非常重要的,所以我开发了nsqadmin来完成这些事情。它提供了Web界面去浏览topics/channels/consumers的层次结构,为每一层检查深度和其他关键统计数据。此外,还支持其他的一些管理命令,例如移除和清空管道(which is a useful tool when messages in a channel can be safely thrown away in order to bring depth back to 0)

    简单的升级路径

  • 这之前使我们最高的优先级之一, 我们的产品系统需要处理大量的流量,全部建立在我们现有的消息工具之上,所以我们需要一个方法去缓慢而有条理地升级基础设施的某些部分,而尽量不带了影响。
  • 第一,在消息产品方面我们使用nsqd去匹配simplequeue(nsq的前身),特别的,nsqd暴露http的/put接口,就跟simplequeue一样,用于POST二进制数据(with the one caveat that the endpoint takes an additional query parameter specifying the “topic”),服务从start publishing到nsqd只需要改少量的代码。
  • 其次,我们用Python和Go建立库去匹配我们现有库的功能和使用方法,这缓解了消息消费者方面的转变通过限制引导的代码更改,全部业务逻辑保持一样。
  • 最后,我们建立工具将新老的组件“粘合”在一起工作,他们都可以使用,在包的examples目录下面
    • nsq_pubsub - expose a pubsub like HTTP interface to topics in an NSQ cluster
    • nsq_to_file - durably write all messages for a given topic to a file
    • nsq_to_http - perform HTTP requests for all messages in a topic to (multiple) endpoints

消除单点故障

  • NSQ被设计成分布式的使用场合,nsq的客户端通过TCP连接到提供特定topic的全部实例,没有中间人,没有信息代理也没有单点故障。
  • 这个拓扑结构消除了对链单、聚合、提要的需求,作为替换你直接从producers消费消息。从技术上说,它不在乎哪个客户端连接到哪个NSQ,只要有足够的客户端连接到全部的生产者去满足足够量的消息,你保证所有最终将被处理。
  • 对于nsqlookupd,高的可用性是通过运行多个实例完成的,他们之间不直接交流,数据被认为是最终一致的。Consumers 拉取他们之前全部配置好的nsqlookupd实例,分析全部的响应。过期,无法访问,或者错误的节点立刻停止。

    保证消息交付

  • NSQ保证消息送达一次,多次的信息到达是可能的。Consumers应该预料到这一点同时应该删除或者执行idempotent操作。
  • 这个担保是作为协议的一部分被强制实施的,然后按下面的过程工作(假设客户端已经连接同时订阅了topic)
    1:客户端表明自己可以做好接收消息的准备了。
    2:NSQ发送消息,同时存储到本地(当超时或者 re-queue的事件发生)。
    3:客户端发生FIN (finish) or REQ (re-queue)分别表明成功还是失败。如果客户端没有回复NSQ,在等待事先配置好的超时时间之后,会进行re-queue操作。
    
  • 上面的措施保障只有一种情况下会导致消息丢失,那就是nsqd进程没有关闭干净(crash?),在这个案例中,全部的消息在内存中(或者那些没有刷新到磁盘的消息)都会丢失。
  • 如果保障消息不丢失是最重要的,上面的情况也可以被解决。一个解决方法是在不同的机器上面部署冗余的nsqd,介绍相同数据的拷贝,因为你发送的consumers的消息是幂等的,在这些消息上面做两次操作没有下游的影响同时允许系统确保任何单个节点故障不丢失信息。
  • NSQ提供了一些构建模块支持不同的产品使用案例和可配置程度的耐久性。

    限制内存使用

  • NSQ提供了–mem-queue-size配置选项,决定内存中最多有多少消息。如果队列的深度超过了临界值,消息会被写到磁盘。
  • 此外,精明的观察者可能已经确定,这是一个方便的方式通过该值设置为低的东西(如1甚至是0)来获得交付更高的保证。在磁盘备份的队列可在发生不洁重新启动(虽然消息可能被传递两次)。
  • 另外,有关的消息传送的保证,清洁的停机(通过发送nsqd过程TERM信号)安全持久化当前在存储器中的消息。
  • 请注意,如果topic/channel的名称结尾带有字符串#ephemeral是不会被缓存到磁盘,当到达队列最大值是这种消息会被丢弃。这使得消费者不需要的信息保证订阅一个频道。这些短暂的渠道也将它的最后一个客户端断开连接后消失。为一个短暂的主题,这意味着至少有一个信道已经创建,消费,和删除(通常是短暂的信道)。

    效率

  • NSQ的目的使用沟通通过类似“memcached-like”命令协议带有简单前缀的响应。所有的消息数据被保持在元数据中,如尝试次数,时间戳等等,元数据这消除数据的拷贝来回从服务器到客户端,先前工具链的固有性质,当重新排队的消息。这也简化了客户端,因为他们不再需要负责维护消息状态。
  • 而且,通过还原配置的复杂性,建立和开发时间大大减少(特别是在有> 1消费者一个话题的情况下)。
  • 对于数据协议中,我们做了一个关键的设计决定,即通过推送数据到客户端,而不是等待它拉。这一概念,我们称之为RDY的状态,实质上是客户端的流量控制的一种形式。
  • 当客户端连接到nsqd并订阅它被放置在一个信道的RDY为0这种状态意味着没有信息将被发送到客户端。当客户端已准备好接收邮件发送了更新其命令RDY状态,一些#它准备来处理,说100在没有任何额外的命 ​​令,100邮件将被传递到客户端,因为它们是用(每次递减服务器端RDY计数为该客户端)。
  • 客户机库被设计成发送一个命令来更新RDY当它到达计数〜所述可配置的25%最大-飞行中设置(和正确地考虑来连接到多个nsqd 实例,适当地划分)。
  • 这是一个显著性能旋钮一些下游系统能够更容易地批量过程的消息和从较高大大受益最大-飞行。
  • 值得注意的是,因为它既是缓冲和推基于与满足需求流(信道)的独立副本的能力,我们已经产生的行为就像一个守护进程simplequeue 和PubSub的 结合。这对简化我们的系统的拓扑而言强大,我们将有传统上保持以上讨论的较旧的工具链。

    参考资料

  • DESIGN
文章目录
  1. 1. NSQ的设计目的
  2. 2. 简化了配置和管理
  3. 3. 简单的升级路径
  4. 4. 消除单点故障
  5. 5. 保证消息交付
  6. 6. 限制内存使用
  7. 7. 效率
  8. 8. 参考资料
,