ZeroMQ是轻量的消息中间件,与其它常见的消息服务,如ActiveMQ、 MQTT等显著不同 的是,
- 它不需要安装服务器,通常只需要使用者安装libmq库并引入相应程序语言的封装库就可以使用。
- 另一个显著区别是,ZeroMQ不明确要求通信双方的哪一方作为服务端,例如 在一个PUB/SUB通信组合中,SUB既可作为服务端也可作为客户端存在。
- 在ZeroMQ的客户端可以先于服务端启动,这在其它消息服务中间件中是不允许的。
- 用户可组合ZeroMQ的消息模式(即DEALER/ROUTER,PUB/SUB,REQ/REP等等), 定制其它消息中间件难以实现的业务逻辑
本文简单介绍ZeroMQ的特性及一些常见使用模式。
关于ZeroMQ的数据包
ZeroMQ的使用定长数据包,即[data-len][data][data]...
的形式传输数据。 用户通常需要在此基础上自定义序列化协议(如纯字符串、JSON、ProtoBuf等)。
ZeroMQ支持的底层传输协议类型
在创建socket时需要指定协议类型,支持的类型为:
- 单播:
- inproc: 多用于应用内进程间的一对一通信;
- ipc:可用于同一服务器上不同应用间通信
- tcp:基于TCP的通信方式
- 多播:epgm, pgm
ZeroMQ 的消息类型组合
ZeroMQ的服务端通过bind绑定地址创建Socket,客户端通过connect地址建立连 接。服务端与客户端的消息类型必须匹配。下面介绍ZeroMQ支持的有效消息类型 配对组合。
再次提醒,在下面的组合中,服务端/客户端可以使用两种类型中的任何一种。
广播/订阅组合
一条消息同时被所有订阅者获取:
PUB - SUB
请求应答组合
一个请求对应一个应答,注意可以有多个请求/应答者。一个请求会随机发送给一个接收者:
REQ - REP
在请求-应答模式中,通常使用请求-收到应答-请求-收到应答-...
这样循环的方式通信,某一方出现异常时,有可能造成阻塞。
可作中间件(broker)的组合
这些组合通常用来构件更为复杂的通信模式
REQ - ROUTER
DEALER - REP
DEALER - ROUTER
DEALER - DEALER
ROUTER - ROUTER
DEALER,ROUTER
会在收到的消息中加入连接ID,用于识别连接。
DEALER-ROUTER
可用于异步请求-应答场景,替代REQ - REP
组合,避免出现阻塞。
XPUB/XSUB:原始消息转发
用于代理转发消息:
XPUB - XSUB
推送模式
与PUB/SUB类似都只支持单向消息,不同的是一条消息PUSH/PULL只对应一个接收者:
PUSH - PULL
一对一通信组合
PAIR主要用于同一应用内线程间数据交换:
PAIR - PAIR
使用 multicast 自定义协议
由于 ZeroMQ仅使用定长数据包,自身并不带复杂的通信协议。除了可使用自定义二进制协议外,我们还可以 利用ZeroMQ提供的multicast定义协议。
Multicast的使用很简单,在发送数据包时使用SNDMORE
的flag参数即表示当前 数据包为multicast包之一,
socket.send(&msg, SNDMORE)
将flag参数设为0表示multicast包结束:
socket.send(&msg, 0)
Multicast的包会分为多个ZeroMQ数据包传输,但ZeroMQ保证
- 发送端在发送最后一个multicast包时才会真正发送数据包
- 原子性:接收端要么收到所有multicast包,要么完全收不到
可见multicast适合自定义协议,不适合文件分割传输。
ZeroMQ的一些使用场景
作为代理(Broker)使用
使用proxy(frontend, backend)
函数将两个ZeroMQ的Socket组合为消息代理,可实现与其它常见的消息服务器相同的功能。
下面介绍几种可能的代理组合。
多对多广播:XPUB/XSUB
XPUB/XSUB转发收到的原始消息包,通常用作代理层。
虽然不使用XPUB/XSUB节点也可以实现多对多广播,但这要求客户端预先知道服 务端的地址,这样的实现就缺少灵活性(例如服务端在内网或服务端地址为动态 变化的情况下,客户端就不好处理)。
多对多请求应答:ROUTER/DEALER
在存在多个任务分发者及多个任务处理者时,可使用此模式:
ZeroMQ的线程安全性
- ZeroMQ的context对象,即
zmq.Context()
具有线程安全性,可在多个线程中使用。 - 但使用context创建的socket不具线程安全性,不能在多线程中使用。
在多线程场景中,正确的做法是在主线程中创建context对象,并传递给子线程 中生成socket实例,并确保一个socket仅在这个线程中使用。
使用ZeroMQ传输文件
可使用 DEALER-ROUTER
模式分片发送文件。可参考imagezmq: 一个使用ZeroMQ实现的视频传输Python库。
问题
ZeroMQ似乎没有简单的权限管理方法,也没有好用的通信加密机制。