一、前言
前段时间看到一篇不错的文章《看了这篇你就会手写RPC框架了》,于是便来了兴趣对着实现了一遍,后面觉得还有很多优化的地方便对其进行了改进。
主要改动点如下:
- 除了Java序列化协议,增加了protobuf和kryo序列化协议,配置即用。
- 增加多种负载均衡算法(随机、轮询、加权轮询、平滑加权轮询),配置即用。
- 客户端增加本地服务列表缓存,提高性能。
- 修复高并发情况下,netty导致的内存泄漏问题
- 由原来的每个请求建立一次连接,改为建立TCP长连接,并多次复用。
- 服务端增加线程池提高消息处理能力
二、介绍
RPC,即 Remote Procedure Call(远程过程调用),调用远程计算机上的服务,就像调用本地服务一样。RPC可以很好的解耦系统,如WebService就是一种基于Http协议的RPC。
总的来说,就如下几个步骤:
- 客户端(ServerA)执行远程方法时就调用client stub传递类名、方法名和参数等信息。
- client stub会将参数等信息序列化为二进制流的形式,然后通过Sockect发送给服务端(ServerB)
- 服务端收到数据包后,server stub 需要进行解析反序列化为类名、方法名和参数等信息。
- server stub调用对应的本地方法,并把执行结果返回给客户端
所以一个RPC框架有如下角色:
- 服务消费者远程方法的调用方,即客户端。一个服务既可以是消费者也可以是提供者。
- 服务提供者远程服务的提供方,即服务端。一个服务既可以是消费者也可以是提供者。
- 注册中心保存服务提供者的服务地址等信息,一般由zookeeper、redis等实现。
- 监控运维(可选)监控接口的响应时间、统计请求数量等,及时发现系统问题并发出告警通知。
三、实现
本RPC框架rpc-spring-boot-starter涉及技术栈如下:
- 使用zookeeper作为注册中心
- 使用netty作为通信框架
- 消息编解码:protostuff、kryo、java
- spring
- 使用SPI来根据配置动态选择负载均衡算法等
由于代码过多,这里只讲几处改动点。