Pigeon 作为 RPC 中间件,本篇文章就以 Pigeon-2.10.8 为例,
什么是Pigeon
Pigeon是一个纯粹使用HTTP协议封装的一个符合RESTful规范的用于客户端与服务端之间通过接口规范来进行通讯的RPC框架
尤其擅长于Android/iOS与JAVA服务端的API调用,致力于解决目前移动互联网开发过程中网络通讯方面的各种问题.
其基本框架如下:
大体上,Pigeon 分为 Client 端和 Server 端
Client 端包括:客户端代理、客户端Filter、连接池、业务线程池、NettyClient。
客户端代理
RPC 要求像调用本地函数一样来调用远程函数,所以需要对调用方屏蔽调用细节。Pigeon 中使用代理模式来实现。
客户端Filter
代理模式的具体实现,是用责任链模式衔接,为框架提供了高可扩展性。目前 Filter 中包含:服务监控、服务路由、故障注入、服务鉴权、服务降级、服务调用等模块。
连接池
首先明确一点,连接池的概念是调用端做IO操作的时需要创建的对象,线程池是服务端处理业务逻辑时需要创建的对象。
Pigeon 允许客户端与一个服务端机器建立多个连接,这个连接是在 Client 的 ChannelPool 中维护。
线程池
负责在收到服务端返回的数据后,通知(唤醒)业务线程。
Netty Client
Pigeon 客户端和服务端的网络通信是交给 Netty ( 关于 Netty ... )来完成的,而 Netty 是基于 Reactor 模型实现的基于事件驱动的网络I/O框架,其包含 Boss( Reactor 模型中的 MainReactor )、Worker(Reactor 模型中的 SubReactor)以及基于Channel 的 Pipeline。
Reactor 模型
Boss
在客户端中,负责发起 connect 请求。而在服务端中则负责 accept 客户端发来的 connect 请求。客户端和服务端建立连接后,则将相应的连接丢给 Worker 去维护。
Worker
负责轮询连接(I/O多路复用)是否有数据送达,并负责将数据读写到相应的 Channel 中。
Pipeline
负责对 Channel 中的数据进行加工,在 Pigeon 中,其主要包含:序列化、反序列化、完整性校验、解压缩等。
Server 端
Server 端包括:服务端 Filter、业务线程池、NettyServer。
服务端 Filter
与客户端 Filter 对应,一个请求在进入业务代码之前,要先经过:服务监控、服务鉴权、服务限流等模块。
线程池
将业务逻辑从I/O操作中剥离,数据准备好后,业务代码将在业务线程中执行。在 Pigeon 中,为了防止慢请求影响其他正常请求,会将满足一定条件的慢请求隔离到 SlowRequestPooling 中。
Netty Server
与 NettyClient 类似。
上面介绍了 Pigeon 的基本架构以及相应的模块,下面将详细解释远程服务调用的执行过程:
假设当客户端和服务端建立连接之后( pigeon启动过程 ),客户端调用远程服务,参照上图,Pigeon 的执行路径如下:
1、首先在客户端调用远程服务方法时,其真正调用的是 InvocationHandler 的 invoke 方法(这里使用 JDK 的动态代理)。Pigeon 中 InvocationHandler 的实现为 ServiceInvocationProxy, 所以调用接口声明的任意方法最终都会进到 ServiceInvocationProxy.invoke 方法。
2、ServiceInvocationProxy.invoke 中会调用客户端 Filter ,请求会依次经过 监控、路由、降级、网关、鉴权 等模块后,进入 RemoteCallInvokeFilter。
3、在 RemoteCallInvokeFilter 中调用 Client.write 方法,其逻辑为从连接池(ChannelPool)中 获取连接(获取连接的超时时间默认为:2000ms),然后将数据写进 Channel。
4、在向服务端发送数据之前,需经过 Channel 的 Pipeline(序列化、压缩等,减少网络传输的数据量)。
5、然后就开始向服务端发送数据,由于 Netty 发送消息是异步的,所以如果是同步调用的话,Pigeon 这里会让业务线程主动 await ,直到收到服务端响应或超时后唤醒。
6、服务端收到客户端发过的消息后,从 Channel 中将消息读出来之前,也会先经过一些 Pipeline(反序列化、解压缩等)后到达 NettyServerHandler,在其中 Pigeon 这边还做了服务隔离的设计:
默认的隔离机制(统计和隔离级别都是方法级的):
当超时数超过300,或者超时率超过5%,就将后续对应请求放入slow线程池处理。
当超时数低于300,或者超时率低于5%,就将后续对应请求放入shared线程池处理。
默认还开启方法限流(非Rhino),限制单个方法不能占用多于 380(动态控制)个线程。
提供业务自定义独立线程池的支持
7、在选择相应的线程池并成功的拿到线程后,请求就到了服务端 Filter 中。请求会依次经过 监控、流量录制、鉴权、泛化调用、网关等模块后,进入 BusinessProcessFilter。
8、在 BusinessProcessFilter 中会根据客户端传递来的服务信息和参数,通过反射调用相应的业务服务并拿到业务处理结果。然后在 WriteResponseProcessFilter 中将返回结果写入 Channel。
9、返回结果再经过服务端的 Pipeline 处理(序列化、压缩等),就发给客户端
10、客户端收到消息后,经过客户端的 Pipeline 处理(反序列化、解压缩等)后到达 NettyClientHandler,然后交给 ResponseThreadPoolProcessor 线程池处理。
11、ResponseThreadPoolProcessor 收到消息后,会通知之前 await 的业务线程,并将结果传递给他。
12、业务线程收到 signal 通知后,就将结果返回给之前的方法调用。
总结:知原理,才能快速定位问题
更快更新请关注我公众号:be_coder
公众号:【转行程序员】专注新人转行入门指导,老兵技术提升,包含各种新手学习资料,架构师技能提升系列文章,欢迎关注。