C++ RPC Library – Based on Protobuf, and Core Library Independent of Network
source link: https://github.com/IronsDu/gayrpc
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
gayrpc
跨平台全双工双向(异步)RPC系统,也即通信两端都可以同时作为RPC服务方和客户端.
Build Status
Windows : Linux:
动机
目前的RPC系统大多用于互联网行业后端系统,但他们之间更像一个单向图(不存在两个服务彼此依赖/互相调用),但游戏等行业中则两节点之间可能相互调用。 因此我们需要一个全双工RPC,在一个"链接"的两端均可开启服务和客户端,当然这里的"链接"是一个虚拟概念,它不一定基于TCP,也即"链接"的两端可以只存在逻辑链接而没有网络直连。
设计准则
- RPC支持拦截器,能够对Request或Response做一些处理(比如监控、认证、加解密、分布式跟踪)
- RPC核心不依赖网络和网络传输协议,即:我们可以开发任何网络应用和逻辑来开启RPC两端,将"收到"的消息丢给RPC核心,并通过某个出站拦截器来实现/决定把Request或Response以何种方式传递给谁。
- 此RPC是基于异步回调的,我认为这是目前C++里比较安全和靠谱的方式,除了回调地狱让人恶心……
- RPC系统核心(以及接口)是线程安全的,可以在任意线程调用RPC;且可以在任意线程使用XXXReply::PTR对象返回Response。
- RPC是并行的,也即:客户端可以随意发送Request而不必等待之前的完成。 且允许先收到后发出的Request的Response。
- RPC系统会为每一个"链接"生成一个XXXService对象,这样可以让不同的"链接"绑定/持有各自的业务对象(有状态)(而不是像grpc等系统那样,一个服务只存在一个service对象,这类RPC调用类似短链接:收到请求返回数据即可)
- 支持HTTP API(同理2,此功能通过具体通信协议和拦截器进行支持,RPC核心本身与此无关).
依赖
Windows下可使用 vcpkg 进行安装以下依赖库.
请注意,当使用Windows时,务必使用 vcpkg install brynet --head
安装brynet.
且务必根据自身系统中的protoc版本对gayrpc_meta.proto和gayrpc_option.proto预先生成代码,请在 src目录里执行:
protoc --cpp_out=. ./gayrpc/core/gayrpc_meta.proto ./gayrpc/core/gayrpc_option.proto
代码生成工具
地址: https://github.com/IronsDu/protoc-gen-gayrpc
,由 liuhan 编写完成。
首先将插件程序放到系统 PATH路径下(比如Linux下的/usr/bin),然后执行代码生成,比如(在具体的服务目录里,比如 gayrpc/examples/echo/pb
):
protoc -I. -I../../../src --cpp_out=. echo_service.proto protoc -I. -I../../../src --gayrpc_out=. echo_service.proto
Example
https://github.com/IronsDu/gayrpc/tree/master/examples
Benchmark
Latency(single threaded):
connection num:1000 took 13285ms, for 3000000 requests throughput (TPS):230769 mean:3 ms ,3920200 ns median:3 ms ,3050227 ns max:40 ms ,40070708 ns min:0 ms ,15601 ns p99:3 ms ,3757835 ns
Throughput(two threaded):
Ubuntu 18.04 (i5 CPU)下,echo 300k QPS,当并发echo时 1000K QPS.
协议
目前实现的RPC通信协议底层采用两层协议.(注意!RPC核心库并不依赖具体通信协议!) 第一层采用二进制协议,且字节序统一为大端. 通信格式如下:
[data_len | op | data] 字段解释: data_len : uint64_t; op : uint32_t; data : char[data_len];
当 op
值为1时表示RPC消息,此为第二层协议!这时第一层协议中的data的内存布局则为:
[meta_size | data_size | meta | data] 字段解释: meta_size : uint32_t; data_size : uint64_t; meta : char[meta_size]; data : char[data_size];
其中 meta
为 RpcMata
的binary. data
为某业务上的Protobuf Request或Response类型对象的binary或JSON.
RpcMata
的proto定义如下:
syntax = "proto3"; package gayrpc.core; message RpcMeta { enum Type { REQUEST = 0; RESPONSE = 1; }; enum DataEncodingType { BINARY = 0; JSON = 1; }; message Request { // 请求的服务函数 uint64 method = 1; // 请求方是否期待服务方返回response bool expect_response = 2; // 请求方的序号ID uint64 sequence_id = 3; }; message Response { // 请求方的序号ID uint64 sequence_id = 1; // 执行是否成功 bool failed = 2; // (当failed为true)错误码 int32 error_code = 3; // (当failed为true)错误原因 string reason = 4; }; // Rpc类型(请求、回应) Type type = 1; // RpcData的编码方式 DataEncodingType encoding = 2; // 请求元信息 Request request_info = 3; // 回应元信息 Response response_info = 4; }
服务描述文件范例
以下面的服务定义为例:
syntax = "proto3"; package dodo.test; message EchoRequest { string message = 1; } message EchoResponse { string message = 1; } service EchoServer { rpc Echo(EchoRequest) returns(EchoResponse){ option (gayrpc.core.message_id)= 1 ;//设定消息ID,也就是rpc协议中request_info的method }; }
处理请求或Response的实现原理
- 编写第一层通信协议的编解码
- 将第一层中的
data
作为第二层协议数据,反序列化其中的meta
作为RpcMeta
对象 - 判断
RpcMata
中的type
- 如果为
REQUEST
则根据request_info
中的元信息调用method
所对应的服务函数. 此时第二层协议中的data
则为服务函数的请求请求对象(比如EchoRequest
). - 如果为
RESPONSE
则根据response_info
中的元信息调用sequence_id
对应的回调函数. 此时第二层协议中的data
则为服务方返回的Response(比如EchoResponse
)
- 如果为
发送请求的实现原理
以 client->echo(echoRequest, responseCallback)
为例 参考代码: GayRpcClient.h
data meta
发送Response的实现原理
以 replyObj->reply(echoResponse)
为例 参考代码: GayRpcReply.h
data meta
编解码参考
https://github.com/IronsDu/gayrpc/tree/master/src/gayrpc/protocol
注意点
- RPC核心并不依赖通信采用的协议,而且网络传输可以是TCP、UDP、WebSocket等等,抑或消息队列等等。
- RPC服务方的reply顺序与客户端的调用顺序无关,也就是可能后发起的请求先得到返回.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK