1 ØMQ(ZeroMQ)简介
zeromq是一个快速的通讯库。 轻量级的消息队列
ZeroMQ(ØMQ/ZMQ)网络库的由来:“它提供一些跨多种传输协议(如进程内通讯、IPC、TCP和广播)的套接字供你使用。你可使用多种方式实现N对N的套接字连接,譬如:扇出、发布订阅、任务分发以及请求响应。”
建立在 socket 之上的 light-weight message queue。不再需要自己管理 tcp 分包。简单、实用。来自 iMatix 的一个库,iMatix 主要面向金融行业。(业务逻辑决定设计)
1.1 优点
c++的消息中间件zeromq
史上最强大的消息中间件,30us内完成消息传递,兼容多平台,多语言,很好
熟悉消息队列技术如rabbitmq,zeromq
高吞吐,低延时,超乎你的想象
支持多语言,支持windowns,linux和各种平台
它是个可伸缩层,分散在分布式系统间。因此,它可支持任意大的应用程序。ØMQ不是简单的点对点交互,相反,它定义了分布式系统的全局拓扑。ØMQ应用程序没有锁,可并行运行。此外,它可在多个线程、内核和主机盒之间弹性伸缩。
1.2 Zmq特点
1) ZeroMQ交互是面向消息的。它将人们每天为应用程序周而复始地进行的例行消息处理封装起来。这意味着如果当客户端套接字发送一条150KB大小的消息时,服务端套接字无需显式处理任何缓存(buffer)或组帧,即能接接收到一条完整而相同的消息。
2) ZeroMQ套接字与传输协议无关:对于任何协议,只有单一且统一的发送消息和接收消息API。缺省情况下支持进程内通讯、IPC、广播和TCP。此外,协议间切换非常简单,仅需更改连接字符串的前缀即可。
3) ZeroMQ套接字能感知路由和网络拓扑。因为我们不再需要显示地管理点对点的连接状态——在上面我们已经看到,所有这些都已经由ZeroMQ库封装好——所以单个ZeroMQ套接字
可以绑定两个独立的端口并监听他们的入站请求消息;也可使用一个API调用向两个独立的套接字发送数据。
4) 缺省情况下,ZeroMQ中所有的交互都是异步的。这种异步处理模型使得ZeroMQ能够将建立连接、销毁连接、重新连接的过程封装起来,同时又能实现消息传输延迟的最小化:非阻塞的含义是,应用中一般的消息处理都是并行进行的,如消息的发送、传输以及(在发送端或接收端)排队。当然,你也可以控制ZeroMQ的排队行为,只需要设定内存范围即可,甚至你还可以为每个套接字设定交换区域。所以,如果需要的话,你完全可以模拟阻塞式API,但是异步I/O是缺省的行为。
无需多说,ZeroMQ是一个雄心满满项目,该简介对于完整的特性集而言只能略见一斑。ZeroMQ的明确目标是成为标准网络协议栈的一部分,之后进入Linux内核,现在还未看到它们的成功。但是,它无疑是极具前景的、并且是人们更加需要的传统BSD套接字之上的一层封装。 ZeroMQ让编写高性能网络应用程序极为简单和有趣。
1.3 对比
经过比较选型,从多语言的支持的角度,最后筛选得到RabbitMQ和ZeroMQ两个选择。
RabbitMQ是采用Erlang开发的,支持完善的AMQP协议;ZeroMQ使用C语言开发,重点在于效率;两者均有多语言支持,其中ZeroMQ支持得较多。
比较看, RabbitMQ支持的AMQP协议,较为完整和复杂;而ZeroMQ的接口极为简单。速度上,还未对亲自对两者做压力测试。从网上的资料看,RabbitMQ较慢,几十个并发以内,延时为几十毫秒,但当客户端达到1000个并发的时候,速
度就无法容忍了(参考);ZeroMQ上则据称可以达到13毫米延时和高达每秒4.1兆次传递(参考, 国内需要才能访问)。如果队列较多的话,RabbitMQ很容易把内存耗尽,而ZeroMQ则把队列内容保存在发送端。
?MQ is already very fast. We're getting 13.4 microseconds end-to-end latencies and up to 4.1 million messages a second today. (1G的网卡,8核AMD Opteron)
zeromq的PUB/SUB网络模型
2 zeromq解决了什么问题
最开始,考虑的问题是,zeromq进程间通信和线程间通信的区别libevent,ACE这样定位的项目有什么区别没有?
1) libevent封装了对网络I/O,信号,定时器等的处理,可以基于它之上做网络层的开发.
2) ACE封装了不同平台下的系统调用,也提供好几种网络编程的模型.
然而,zeromq不是libevent,也不是ACE,因为它的主要特性是:面向消息进行通信.所以,它提供的是比libevent,ACE处在网络通信中更高一层的组件.使用它,程序员不再需要上面提到的libevent,ACE之类的库需要关心的东西,程序员如果要使用zeromq,只需要做如下的事情:
1) 告知所使用的patten,比如request-reply,pub-sub,push-pull(下面会详细解释这个pattern).
2) 告知是用于机器之间,还是进程之间,线程之间的通信.
然后,将所需要发送的数据封装到zeromq自带的msg结构体中发送出去,使用者自己关心如何序列化/反序列化这些数据,然后如何处理这些数据就是使用者的事情了.
这样看上来,使用者要关注的事情了一层,大部分的精力都可以放在业务逻辑之上了.简而言之,它让使用者的精力放在了通信模式和业务逻辑上,而不是更下面一层的网络层上.
下面解释一下zeromq常用的几种网络pattern:
1) request-reply
就是一般的C/S架构中,clientserver之间一问一答的通信模式,比如最经典的echo服务.需要注意的是,client发送一个request,server必须有一个回应.
这个pattern并不是什么亮点,下面亮点来了.
2) publish-subscribe
server端作为publish,而任何连接到服务端的client都会成为subscribe.也就是说,server端会把当前的所有需要publish出去的消息全部发送到当前连接上去的client.
3) push-pull
server端作为push,client端作为pull.如果有多个client端同时连接到这个server,则服务器会在内部做一个负载均衡,采用平均分配的算法,将所有的消息均衡发布到client端上.
看上去,很稀松平常?接下来亮点真的来了.
2),3)两种模式中,无论是server端还是client端在启动时 都是不知道client实际数量的,这就意味着,一个使用zeromq搭建的服务,可以进行热更新”.
考虑如下一种场景.一个server端做为一组服务器集最上层的一个proxy,起到负载均衡的作用,将请求按照它下面对应服务器集依次派发到不同的 client端进行处理.某个时刻可能处理
的机器只有2,而随着负载越来越大,可能需要3台机器了,这个时候如果使用zeromqpush-pull 搭建的proxy,则可以不用对之前搭建的server,client端进行停机,只需要新启动一个client连接上去,proxy层就会自动根据当前的机器分配平均派发任务了.cool.
实际上,这些模式并不是什么新东西,只不过zeromq为使用者做了一个封装,而不是像libevent,ACE等还局限在网络层部分的封装,它关注的是通信层,通信模式等.
个人感觉,zeromq部分解决 erlang所要解决的问题:在多台机器中通信,派发任务等,是分布式通信的利器,但是局限于语言的限制,它没有办法做的跟erlang一样的完善(erlang已经可以算的上一个简易微型的OS),但是许多的时候,似乎只使用这一部分功能也就足够了.
zeromq的代码量,截至到我目前阅读的2.0.10-stable版本,也只有不到2W行代码.提供出去的API也极为简单,但是内部的实现比较”,zeromq是我阅读过的项目中少数的非常需要依赖调试工具跟进代码才能看懂代码流程的项目,同时代码中类的继承层次也比较多,阅读起来并不像它提供的API那样简单直白.后续会对其中的一些难点做一些分析.
3 ZeroMQ 的模式
在需要并行化处理数据的时候,采用消息队列通讯的方式来协作,比采用共享状态的方式要好的多。Erlang Go 都使用这一手段来让并行任务之间协同工作。
最近读完了 ZeroMQ Guide。写的很不错。前几年一直有做类似的工作,但是自己总结的不好。而 ZeroMQ 把消息通讯方面的模式总结的很不错。
ZeroMQ 并不是一个对 socket 的封装,不能用它去实现已有的网络协议。它有自己的模式,不同于更底层的点对点通讯模式。它有比 tcp 协议更高一级的协议。(当然 ZeroMQ 不一定基于 TCP 协议,它也可以用于进程间和进程内通讯。)它改变了通讯都基于一对一的连接这个假设。
ZeroMQ 把通讯的需求看成四类。其中一类是一对一结对通讯,用来支持传统的 TCP socket 模型,但并不推荐使用。常用的通讯模式只有三类。
1. 请求回应模型。由请求端发起请求,并等待回应端回应请求。从请求端来看,一定是一对对收发配对的;反之,在回应端一定是发收对。请求端和回应端都可以是 1:N 的模型。通常把 1 认为是 server N 认为是 Client ZeroMQ 可以很好的支持路由功能(实现路由功能
的组件叫作 Device),把 1:N 扩展为 N:M (只需要加入若干路由节点)。从这个模型看,更底层的端点地址是对上层隐藏的。每个请求都隐含有回应地址,而应用则不关心它。
2. 发布订阅模型。这个模型里,发布端是单向只发送数据的,且不关心是否把全部的信息都发送给订阅端。如果发布端开始发布信息的时候,订阅端尚未连接上来,这些信息直接丢弃。不过一旦订阅端连接上来,中间会保证没有信息丢失。同样,订阅端则只负责接收,而不能反馈。如果发布端和订阅端需要交互(比如要确认订阅者是否已经连接上),则使用额外的 socket 采用请求回应模型满足这个需求。
3. 管道模型。这个模型里,管道是单向的,从 PUSH 端单向的向 PULL 端单向的推送数据流。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。