RPC第一篇:一个RPC调用的执行过程

                               

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 

公众号:【转行程序员】专注新人转行入门指导,老兵技术提升,包含各种新手学习资料,架构师技能提升系列文章,欢迎关注。

发布了50 篇原创文章 · 获赞 33 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/leilei107/article/details/93248514
今日推荐