基于Zmq的后台通信模型介绍
- 2020 年 1 月 20 日
- 笔记
Zmq是一个简单好用的传输组建,使得socket变成更加简洁、高效、高性能。本文主要介绍后台服务实现、多线程任务实现、线程无锁计数实现。
1.Zmq通常通信模型
Zmq通信场景:
- 线程之间(inproc)
- 进程之间(ipc)
- 机器之间(tcp)
Zmq通信模式:
- 请求-回复(Request-reply)。分为ZMQ_REQ、ZMQ_REP、ZMQ_DEALER、ZMQ_ROUTER
- 发布-订阅(Publish-subscribe)。分为ZMQ_PUB、ZMQ_SUB
- 管道(Pipeline)。分为ZMQ_PUSH、ZMQ_PULL
- 对立对(Exclusive pair)。分为ZMQ_PAIR
2.后台服务实现
多线程模式后台服务一般启动一线程接收外部请求,再派发给工作线程进行处理请求,工作线程完成后返回给派发线程,最终返回请求方。
使用zmq线程间,请求-回复,ROUTER-DEALER模式可以很方便的实现多线程后台服务。实现原理如图2-1。

1、Dispatcher线程通过tcp socket接收来自Client的请求。这里tcp socket可以是基于zmq的tcp,也可以是普通的tcp请求,只要与client统一通信协议即可,其中如果基于zmq则需要使用zmq的协议格式。
2、Dispatcher线程收到Client请求后采用zmq inproc socket派发给Worker线程。其中Dispatcher线程的zmq inproc socket采用DEALER模式。
3、Worker线程通过zmq inproc socket收到请求,进行处理,处理完后将结果返回给Dispatcher线程。Worker线程的zmq inproc socket采用ROUTER模式。
4、Dispatcher线程收到Worker线程的返回后将返回通过tcp返回给Client,完成一个完整的后台服务。
3 .多线程任务实现
很多后台任务并不是对外服务,仅仅是为了完成某项具体的任务,如数据处理、数据搬移、定时任务等。很多后台任务在多线程处理时,多任务需要在多线程完成,直接用锁、共享资源来分配任务实现比较复杂,且容易出错,如果采用zmq实现线程间通信,其中一线程来派发任务,多线程循环完成任务。这种场景实现原理如图3-1。

1.启动一个Dispatcher线程进行任务派发;
2.Worker线程处理任务并返回处理结果;
3.Dispatcher线程统计结果,且继续派发任务,这里Dispatcher需要异步来接收任务返回。
4.多线程无锁计数实现
如果多个后台任务线程需要做一个互斥计数或取某一个数值,通常会想到直接用互斥锁来实现,这里基于zmq介绍一种通过线程间通信来实现的方式。通过启动一个Dispatcher来处理互斥资源操作,把操作结果返回给Worker线程,而这里由于只有一个Dispatcher线程,能够实现无锁互斥效果。实现原理如图4-1。

1.启动一个Dispatcher线程进行操作需要互斥的资源,如计数等;
2.Worker线程发送请求给Dispatcher线程;
3.Dispatcher线程进行处理,处理完后返回给Worker线程。
5 .总结
Zmq本身是一个应用非常广泛的通信组建,这里介绍的通信模式在生产环境得到了充分的验证,目前腾讯内部有基于zmq的成熟c++ rpc组件,本文主要讲线程间的通信,基于zmq多进程的模式实现后台框架,基本原理是一致的,可以进一步去研究。