zerorpc 是利用 zeroMQ消息队列 + msgpack 消息序列化(二进制) 来实现类似 grpc 的功能,跨语言远程调用。
主要使用到 zeroMQ 的通信模式是 ROUTER–DEALER,模拟 grpc 的 请求-响应式 和 应答流式 RPC :
zerorpc 还支持 PUB-SUB 通信模式的远程调用
zerorpc 的 UML 图(大体):
Server 端向 Client 端发送的 event name 有:
_zpc_hb
: 心跳event name(若 protocol = 2 那么还有沟通队列大小的功能)_zpc_more
: Server 与Client 沟通缓存队列大小(若 protocol = 2,那么 要使用_rpc_hb
)OK
:正常 REP 响应ERR
:异常 REP 响应STREAM
: 这是一个流响应( 模拟http2 中的 stream)STREAM_DONE
: 说明该流响应结束
Client 端 向 Server 端发送的 event name 有:
_zpc_hb
: 心跳event name(若 protocol = 2 那么还有沟通队列大小的功能)_zpc_more
: Server 与Client 沟通缓存队列大小(若 protocol = 2,那么 要使用 _rpc_hb)function name
就是要请求的函数名称
Server 启动流程:
- Server 继承自 SocketBase 和 ServerBase:
- 首先初始化 SocketBase:
- 实例化 Context:定义了 msgid 范围、注册中间件(钩子)、zmq.socket
- 实例化 Events:来管理所有 event
- 然后初始化 ServerBase :
- 实例化 ChannelMultiplexer(channel) 作为 Server 的多路复用器(channel 是 SocketBase 实例化的 events);
- 如果支持接收数据 并且 没有忽略广播, 则创建 _channel_dispatcher 频道调度器 协程,_channel_dispatcher 接收没有 channel_id 的 initial_event 和 包含 channel_id 的 event并分发到与channel_id 相对应的 channel 消息队列中;
- channel 由 ChannelMultiplexer 来创建;
- 使用
_filter_methods
来过滤掉 methods 中的属性以及私有方法,过滤后 methods 有类变为字典类型; - 使用
_inject_builtins
注入一些辅助函数(都以_
开头),比如_zerorpc_list
、_zerorpc_name
、_zerorpc_args
等; - run() 是服务的开始, 创建协程来执行
_acceptor
方法(死循环)来接收initial_event
(来自 ChannelMultiplexer); - 每接收到一个
initial_event
就创建一个协程(_async_task
方法)来处理initial_event
- 在
_async_task
中根据 initial_event 来 创建 channel,发送心跳接收心跳帧,执行 function 并发送结果。
- 实例化 ChannelMultiplexer(channel) 作为 Server 的多路复用器(channel 是 SocketBase 实例化的 events);