手动实现RPC框架
目录 | 二级目录 |
---|---|
理解 | 生活化类比 |
实现 | 客户端,传输,服务端,类图 |
运行展示 | 启动服务注册中心,启动服务端,客户端测试 |
其他的 服务模型:操作系统处理请求(select/epoll将请求转发给进程,RPC框架/web框架转发请求正是依赖于此)、Go语言中调度模型(将协程任务G转发给空闲的M处理)。
类别 | 生活例子 | RPC框架 | web框架 |
---|---|---|---|
客户端 | 用户:打开并保留对话窗口-服务缓存/长连接;咨询想要的服务-构造请求;遇到人满为患的店家则换一家-负载均衡 | 微服务中的调用方 | 浏览器/APP |
通信协议 | 电话/文字/语言 | TCP/http2 | http |
接待与转发 | 前台/客服:尽职在线(需要将交接完手头接收的请求才能下班)、将请求转发给具体服务方 | Server中的监听模块 | web服务器(Nginx)、框架中的路由模块 |
服务平台 | 菜市场/电商平台 | 服务注册中心 | 路由定义 |
服务方 | 商家(如果下线,也需要通知平台,不然用户得到空地址) | 注册到注册中心的服务 | 请求路径对应的处理方法 |
类别 | 说明 | TODO |
---|---|---|
获取服务列表 | 缓存在本地 | watch注册中心的服务、更新本地服务缓存 |
如何请求 | 负载均衡、设置重试、超时控制、失败策略 | 熔断 |
-
轮询(大家轮流来)
类别 说明 轮询 轮询下标index依次递增,增长为节点数量时重新置0 加权轮询 指定所有节点的权重W,实时权重Dw[i]初始均为0;每轮计算中,实时权重Dw[i]+=W[i],取Dw最大的作为本轮选择的节点,同时更新Dw[i]-=totalW 动态加权轮询 根据节点响应情况更新W的值,比如成功处理一个请求则权重+1,超时则权重-10 -
随机
普通随机只是加权随机的特殊情况,即所有节点的权重相同。
类别 说明 随机 每轮随机生成index,获得本轮选择的节点下标 加权随机 根据权重分配每个节点对应的区间长度,每轮随机生成index,根据index所在区间决定本轮选择的节点下标 -
哈希(固定分配,考虑session或登录状态)
类别 说明 哈希 对客户端ip(或其他属性)进行hash、hash值对服务器数量取模,得到节点下标 一致性哈希 解决“服务器节点变化时,大规模哈希值发生变化”的问题。数量较多的虚拟节点均匀分布在环中,然后将物理机器映射到虚拟节点,获得hash值后,顺时针方向遇到的第一个节点作为本轮选择
类别 | 说明 |
---|---|
通信协议 | 网络传输TCP/HTTP/WebSocket |
粘包 | 思路:使用定长字段表示变长数据的长度 |
消息头 | 5字节长,保存:校验数、协议版本、消息类型(请求/响应)、压缩类型(Gzip)、序列化类型(Protobuf/Json) |
类别 | 说明 | TODO |
---|---|---|
注册服务 | 服务名与对应处理类保存在内存中 | |
处理请求 | 监听端口-接收请求,读数据-解码,调用对应方法,编码-返回 | 限流,认证授权 |
“负责任”-优雅启停 | 先启动服务再注册到服务中心;先注销再关闭服务,处理中的请求数为0时才真正关闭服务 |
cd demo
go run server.go -c config.yaml
go run client_proxy.go