一.rpcx介绍
1.1 rpc是什么
远程过程调用的通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用。简单地说就是能使应用像调用本地方法一样的调用远程的过程或服务。很显然,这是一种client-server的交互形式,调用者是client,执行者是server。
一个完整的rpc的调用过程如下:
一次完整的RPC调用流程(同步调用,异步另说)如下:
- 服务消费方(client)调用以本地调用方式调用服务;
- client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
- client stub找到服务地址,并将消息发送到服务端;
- server stub收到消息后进行解码;
- server stub根据解码结果调用本地的服务;
- 本地服务执行并将结果返回给server stub;
- server stub将返回结果打包成消息并发送至消费方;
- client stub接收到消息,并进行解码;
- 服务消费方得到最终结果。
1.2 rpcx介绍
RPC只是描绘了 Client 与 Server 之间的点对点调用流程,包括 stub、通信、RPC 消息解析等部分,在实际应用中,还需要考虑服务的高可用、负载均衡等问题,所以产品级的 RPC 框架除了点对点的 RPC 协议的具体实现外,还应包括服务的发现与注销、提供服务的多台 Server 的负载均衡、服务的高可用等更多的功能。目前的 RPC 框架大致有两种不同的侧重方向,一种偏重于服务治理,另一种偏重于跨语言调用。 然而rpcx 属于服务治理类型,是一个基于 Go 开发的高性能的轻量级 RPC 框架。
1.2.1 rpcx特点
- 基于net/rpc,可以将net/rpc实现的RPC项目轻松的转换为分布式的RPC
- 插件式设计,可以配置所需的插件,比如服务发现、日志、统计分析等
- 基于TCP长连接,只需很小的额外的消息头
- 支持多种编解码协议,如Gob、Json、MessagePack、gencode、ProtoBuf等
- 服务发现:服务发布、订阅、通知等,支持多种发现方式如ZooKeeper、Etcd等
- 高可用策略:失败重试(Failover)、快速失败(Failfast)
- 负载均衡:支持随机请求、轮询、低并发优先、一致性 Hash等
- 规模可扩展,可以根据性能的需求增减服务器
- 其他:调用统计、访问日志等
- 功能都可以通过插件的方式完成。
1.2.2 rpcx架构
rpcx中有服务提供者 RPC Server,服务调用者 RPC Client 和服务注册中心 Registry 三个角色。
-
Server 向 Registry 注册服务,并向注册中心发送心跳汇报状态(基于不同的registry有不同的实现)。
-
Client 需要向注册中心查询 RPC 服务者列表,Client 根据 Registry 返回的服务者列表,选取其中一个 Sever进行 RPC 调用。
-
当 Server 发生宕机时,Registry 会监测到服务者不可用(zookeeper session机制或者手工心跳),Client感知后会对本地的服务列表作相应调整。client可能被动感知(zookeeper)或者主动定时拉取。
-
可选地,Server可以定期向Registry汇报调用统计信息,Client可以根据调用次数选择压力最小的Server。
当前rpcx支持zookeeper, etcd等注册中心。rpcx基于Go net/rpc的底层实现, Client和Server之间通讯是通过TCP进行通讯的,它们之间通过Client发送Request,Server返回Response实现。Request和Response消息的格式都是Header+Body的格式。Header和Body具体的格式根据编码方式的不同而不同,可以是二进制,也可以是结构化数据如JSON。
1.2.3 容错
Client提供了两种容错方式: Failfast、Failover、Failtry:
- Failfast: 如果Client调用失败,立即返回,不会重试。
- Failover: 如果Client调用失败,会尝试从服务列表中选择另外一个服务器调用,直到成功或者到达重试次数。
- Failtry: 如果Client调用失败,会继续这个服务器重试,直到成功或者到达重试次数。
1.2.4 重选算法
- 随机选择: 随机选择一个服务器并返回,可能和上一次的重复
- RoundRobin: 按顺序选择一个服务器。
- 一致性哈希 :使用Jump Consistent Hash algorithm。
- CallLeast : 根据调用次数选择压力最小的服务器。
1.2.5 序列化
- gob: 官方提供的序列化方式,基于一个包含元数据的流
- jsonrpc :也是官方提供的编码库,以JSON格式传输
- msgp: 类似json格式的编码,但是更小更快,可以直接编码struct
- gencode: 一个超级快的序列化库,需要定义schema,但是定义方式和struct类似
- protobuf: Google推出的广受关注的序列化库,推荐使用gogo-protobuf,可以获得更高的性能
二. rpcx-server
2.1 server结构
先看一下官方Server定义的结构体:
// Server is rpcx server that use TCP or UDP.
type Server struct {ln net.Listener //监听readTimeout time.Duration //读取client数据的超时时间writeTimeout time.Duration //写入client数据的超时时间gatewayHTTPServer *http.Server DisableHTTPGateway bool //使用HTTP网关DisableJSONRPC bool //使用json-rpcserviceMapMu sync.RWMutexserviceMap map[string]*service //server端提供的service的记录表mu sync.RWMutex activeConn map[net.Conn]struct{</