文章目录
手写rpc
自定义rpc协议
协议头长度(4) | 协议体长度(4) | ||||||
消息 ID | 版本(1) | 压缩算法(1) | 序列化协议(1) | ||||
服务名 | |||||||
方法名 | |||||||
元数据Meta key-value(客户端字段) | |||||||
元数据Meta ...(客户端字段) | |||||||
错误信息(服务端字段 系统错误) | |||||||
协议体 请求参数 |
Meta支持扩展能力
链路超时控制
超时监听
客户端必须进行超时监听,服务端可进行超时监听
客户端超时检测

客户端可以在如图1、2、3、4处进行超时检测
注意:我们的实现在超时退出时,没有中断请求响应,只是丢弃了请求响应
rpc跨端传递超时时间
传递时间戳(过期时间)
面临问题:时钟同步问题;时间戳是一般传递unix时间戳,至少需要64位。
传递剩余时间
面临问题:较难预测网络传输消耗了多少时间
调用方式
- 异步调用:业务goroutine实现
- 回调:业务goroutine实现
- one-way调用——单向调用,不需要结果
one-way调用
优势:尽快释放两端资源
注意:真one-way是指服务端不返回响应;假one-way:响应被丢弃
核心实现
-
客户端用的上面的手写连接池
-
request、response 编解码
-
客户端绑定代理,服务端代理service实现调用
客户端绑定代理(bindProxy),服务端代理service实现调用(Invoke)
使用反射,反射基础知识见:go 反射reflect速记
type Proxy interface { // 定义代理
Invoke(ctx context.Context, req *encoding_protocol.Request) *encoding_protocol.Response // 实现调用方法
}
func (c *Client) BindProxy(services ...proxy.Service) // 客户端绑定代理
func (r *ReflectionStub) Invoke(ctx context.Context, req *encoding_protocol.Request) *encoding_protocol.Response // 服务端代理service抽象实现方法调用
源码
gitee: https://gitee.com/luyue_zhang/go_rpc_2/tree/master/rpc
测试
grpc使用
protobuf生成grpc代码
user.proto文件位置:https://gitee.com/luyue_zhang/go_rpc_2/blob/master/grpc/user.proto
源码
gitee: https://gitee.com/luyue_zhang/go_rpc_2/tree/master/grpc