一、ZeroMQ概述


  • ZeroMQ(又名ØMQ,MQ,或zmq)看起来像一个可嵌入的网络库,但其作用就像一个​并发框架。
  • ZeroMQ类似于标准Berkeley套接字,​其提供了各种传输工具,​如进程内、进程间、TCP和组播中进行原子消息传送的​套接字。
  • 你可以使用各种模式​实现N对N的套接字连接​,这些模式包括:​扇出、发布-订阅、任务分配、请求-应答。
  • ZeroMQ的速度足够快,因此可充当集群产品的结构。
  • ZeroMQ的​异步I/O模型​提供了可扩展的多核应用程序,用异步消息来处理任务。
  • ZeroMQ核心​由C语言编写​,支持C、C++、java等​多种编程语言的API​,并可运行在大多数操作系统上。
  • 相关链接:

二、零之禅


  • ØMQ中的Ø关乎权衡:

  • 一方面,ØMQ这个奇怪的名字使其在谷歌和Twitter等搜索引擎上降低了知名度。
  • 另一方面,ØMQ惹恼了一些丹麦人(Ø是丹麦字母表中的字母),比如“ØMG rØtfl”(把Ø替换为O后表示“天哪,笑翻了”)、“RØdgrØd med FlØde”(这是一种侮辱,意思是“愿你的邻居是格伦德尔的直系后裔”)。

  • 在程序方面:

  • 最初,ØMQ中的“零”是为了表示​“零代理”和(尽可能接近)“零延迟”​。但从那时起,它已经涵盖了不同的目标:​零管理、零成本、零浪费。
  • 简而言之,“零”是指贯穿项目的简约文化。


三、为什么要使用ZeroMQ


  • 当今的许多应用程序都包含了跨越某种网络的组件,无论这种网络是局域网还是互联网。因此,许多应用程序开发者最终都会处理某种类型的消息传递。一些开发人员使用消息队列产品,但大多数时候,他们使用TCP或UDP自己做。这些协议并不难用,但是,​从A 发送几个字节到B和以任何一种可靠的方式处理消息,这两者之间有很大的区别。
  • 让我们来看看当开始使用原始的TCP连接部件的时候,我们要面对的典型问题。任何可复用的消息层都需要解决如下所有这些问题或其中的大部分问题:

  • 我们如何处理I/O呢?​是让我们的应用程序阻塞,还是在后台处理I/O呢?这是一个关键的设计决策。阻塞式I/O 创建的架构不能很好地扩展,但后台I/O 也是非常难以正确做到的。
  • 我们如何处理动态组件(例如,暂时撤除的块)呢?​我们需要正式将组件划分为“客户端”和“服务器”,并强制该服务器不能撤除吗?那么,如果我们想将服务器连接到服务器时该怎么办呢?我们需要每隔几秒钟就尝试重新连接吗?
  • 我们如何表示在线路上的消息呢?​我们应该怎样将数据组织为帧,才能使得它很容易写入和读取,避免缓冲区溢出,既对小型消息高效,也足以处理非常大的戴着聚会礼帽的跳舞猫的视频呢?
  • 我们如何处理不能立即传递的消息呢?​特别是当我们在等待一个组件的联机回应时如何处理呢?我们需要丢弃消息,把它们放入一个数据库,或者把它们放到一个内存队列吗?
  • 我们在哪里存储消息队列呢?​如果组件从队列中读取很慢,导致我们的队列堆积,这会发生什么情况?我们的策略是什么呢?
  • 我们如何处理丢失的消息呢?​我们应该等待新的数据,要求重发,还是应该建立某种可靠性层,确保信息不会丢失呢?如果该层本身崩溃了该怎么办呢?
  • 如果我们需要使用一个不同的网络传输,比如说,用多播来取代TCP 单播,或IPv6,该怎么办呢?​我们需要重写应用程序吗?还是将传输抽象到某个层中呢?
  • 我们如何路由消息呢?​我们可以发送同样的消息到多个接收者吗?我们可以发送应答给原来的请求者吗?
  • 我们如何编写出另一种语言的API 呢?​我们应该重新实现一个线路级协议,还是重新包装一个库?如果是前者,我们怎么能保证协议栈的高效稳定呢?如果是后者,我们又怎么能保证互操作性呢?
  • 我们应该如何表示数据,以便它可以在不同的架构之间读取呢?​我们应该对数据类型强制执行特定的编码吗?究竟到什么程度,才是消息传递系统的工作,而不是更高一层的工作呢?
  • 我们应该如何处理网络错误呢?​是等待并重试,默默地忽略它们,还是终止它们呢?

  • ZeroMQ解决传统网络编程的问题:

  • 调用的socket接口较多。
  • TCP是一对一的连接。
  • 编程需要关注很多socket细节问题。
  • 不支持跨平台编程。
  • 需要自行处理分包、组包问题。
  • 流式传输时需处理粘包、半包问题。
  • 需自行处理网络异常,比如连接异常中断、重连等。
  • 服务端和客户端启动有先后。
  • 自行处理IO模型。
  • 自行实现消息的缓存。
  • 自行实现对消息的加密。



构建可复用的消息传递系统是十分困难的

  • 但是,我们如何才能做一个可复用的消息传递层呢?​为什么有那么多的项目都需要这项技术,人们都还在通过在他们的代码中驱动TCP套接字费力地做它,并重复解决一长串清单中的问题呢?(见下图)。

一文带你入门了解“零之禅“消息队列ZeroMQ_ZeroMQ简介


  • 实证明,构建可复用的消息传递系统是非常困难的,​这就是为什么很少有自由和开放源码(FOSS)项目尝试做这项工作的原因,它也是商业通信产品复杂、昂贵、灵活性差,而且脆弱的原因。2006 年,​iMatix 设计了高级消息队列协议,或AMQP​(​​http://www.amqp.org/​​​),开始给FOSS 开发者提供也许是首个可复用的消息传递系统方法。AMQP 工作得比许多其他设计更好,但仍然相对复杂、昂贵,而且脆弱(​​http://www.imatix.com/articles:whats-wrong-with-amqp​​)。学会如何使用它需要几个星期,而要用它来建立在事情变得很麻烦时也不会崩溃的稳定架构则需要几个月。
  • 大多数消息传递项目(如AMQP)都在尝试以可重用的方式解决上面这个冗长的清单上的问题,​它们通过发明一种负责寻址、路由和排队的新概念——代理​,来做到这一点。这将导致一个客户端/服务器协议或一些未在文档中记录的协议之上的一组API,它允许应用程序与这个代理交流。在降低大型网络的复杂性方面,代理是一个很好的东西。但把以代理为基础的消息传递添加到像ZooKeeper 这样的产品会使情况变得更糟,而不是更好。这将意味着增加一台额外的大电脑和一个新的单点故障。代理迅速成为一个瓶颈和一个要管理的新风险。如果软件支持的话,我们可以添加第二个、第三个和第四个代理,并提出一些故障切换方案。人们这么做了。然而,它产生了更多的变动部件,变得更复杂,有更多的东西会被破坏。
  • 此外,以代理为中心的设置都需要自己的运营团队。​你真的需要日夜注意代理,并在它们开始“行为不端”时,用棍子敲打它们。你需要电脑,你需要备份的电脑,你需要人来管理那些电脑。只有那些由多个团队在数年内建成的,带有许多变动部件的大型应用程序,才值得这样做
  • 因此,中小型应用程序开发人员陷入了困境。他们要么避免网络编程,制作不可扩展的单一应用程序,要么跳进网络编程,制作脆弱、复杂、很难维护的应用程序​。他们还可以把赌注压在消息传递产品上,并最终获得依赖于昂贵且易破坏的技术的可扩展的应用程序。目前还没有非常好的选择,这也许可以解释为什么消息传递主要还停留在上个世纪,并激起强烈的情绪——对用户是消极的,而对那些销售技术支持和许可的厂商则是欢乐的、喜悦(如下图所示)。

一文带你入门了解“零之禅“消息队列ZeroMQ_为什么要使用ZeroMQ_02



ZeroMQ的优点


  • 我们需要的是做消息传递工作的东西,但需要它以下面这种简单和廉价的方式完成工作:

  • 它可以在任何应用程序中以接近零的消耗开展工作。
  • 它应该是不需要任何其他依赖就可以链接的库。
  • 无须额外的变动部件,所以没有额外的风险。
  • 它应该能运行在任何操作系统上,并能用任何编程语言开展工作。

  • 而这就是ZeroMQ :​一个高效的可嵌入库,它解决了大部分应用程序需要解决的问题,​变得在网络上有良好的可伸缩性,而没有多少成本。
  • 具体做法:

  • 它在后台线程异步处理I/O,​这些线程使用​无锁数据结构​与应用程序进行通信,所以并发ZeroMQ应用程序不需要锁、信号量、或者其他等待状态。
  • 组件可以动态地来去自如,而ZeroMQ会自动重新连接​,这意味着你可以以任何顺序启动组件,你可以创建“面向服务的架构”(SOA),其中的服务可以在任何时间加入和离开网络。
  • 它根据需要自动对消息排队​。为此,它会智能地在对消息排队之前,将消息尽可能地推进到接收者。它有一个处理过满队列(称为“高水位标志”)的方法。当队列满时,ZeroMQ会自动阻止发件人,或丢弃消息,这取决于你正在做的是哪种消息传递(即所谓的“模式”)。
  • 它可以让你的应用程序通过任意传输协议来互相交流,​这些协议可以是:TCP、多播、进程内、进程间。你不需要更改代码以使用不同的传输工具。
  • 它使用依赖于消息传递模式的不同策略​,安全地处理速度慢/阻塞的读取者。
  • 它可以让你采用多种模式,​如请求-应答和发布-订阅来将消息路由。这些模式是指你如何创建拓扑结构和网络结构。
  • 它可以让你创建代理(proxy)来排队、转发,或通过一个调用来捕获消息​。代理可以降低网络互联的复杂性。
  • 它使用在线路上的简单组帧原封不动地传递整个消息。​如果你写了一个10KB 的消息,那么你将收到一个10KB 的消息。
  • 它不对消息强加任何格式​。它们是零字节到千兆字节的二进制大对象。当你想表示你的数据时,可以选择其上的其他一些产品,如谷歌的协议缓冲区、XDR 等。
  • 它能智能地处理网络错误​。有时候它会重试,有时它会告诉你某个操作失败。
  • 它可以减少你的能源消耗​。少花CPU多办事意味着使用电脑更少的能源,你可以让你的旧电脑使用更长的时间。



  • 实际上,ZeroMQ做的比这更多​。它对你如何开发网络功能的应用程序有颠覆性的影响:

  • 从表面上看,​这是一个在其上做zmq_msg_recv()和zmq_msg_send()的套接字风格的API。
  • 但该消息处理循环迅速成为中心循环,​而你的应用程序很快就会分解成一组消息处理任务。它是优雅和自然的。
  • 而且,它可扩展:​每个任务对应一个节点,节点通过任意传输方式互相交谈。在一个进程中的两个节点(节点是一个线程),在一台电脑中的两个节点(节点是一个进程),或一个网络上的两台电脑(节点是一台电脑),所有的处理方式都是相同的,不需要更改应用程序代码。

四、ZeroMQ模型


REQ/REP请求响应模型

  • 演示案例可以参阅:

一文带你入门了解“零之禅“消息队列ZeroMQ_为什么要使用ZeroMQ_03



PUB/SUB发布订阅模型

  • 演示案例可以参阅:

一文带你入门了解“零之禅“消息队列ZeroMQ_ZeroMQ简介_04



PUSH/PULL推拉模型

  • 演示案例可以参阅:

一文带你入门了解“零之禅“消息队列ZeroMQ_ZeroMQ简介_05



Router/Dealer模型

一文带你入门了解“零之禅“消息队列ZeroMQ_ZeroMQ简介_06


五、可供选择的消息队列的对比

一文带你入门了解“零之禅“消息队列ZeroMQ_消息队列ZeroMQ_07

六、ZeroMQ架构背后的历史

一文带你入门了解“零之禅“消息队列ZeroMQ_应用程序_08

七、ZeroMQ吞吐量和延时性

一文带你入门了解“零之禅“消息队列ZeroMQ_消息队列ZeroMQ_09


  • 我是小董,V公众点击"笔记白嫖"解锁更多【ZeroMQ】资料内容。

一文带你入门了解“零之禅“消息队列ZeroMQ_ZeroMQ简介_10