1 基本介绍
image.png1.1客户端介绍:
1.1.1 客户端代理
RPC 要求像调用本地函数一样来调用远程函数,所以需要对调用方屏蔽调用细节。RPC中使用代理模式来实现。
1.1.2 客户端filter
代理模式的具体实现,是用责任链模式衔接,为框架提供了高可扩展性。目前 Filter 中包含:服务监控、服务路由、故障注入、服务鉴权、服务降级、服务调用等模块。
1.1.3 连接池
连接池的概念是调用端做IO操作的时需要创建的对象,线程池是服务端处理业务逻辑时需要创建的对象。
1.1.4 线程池
负责在收到服务端返回的数据后,通知(唤醒)业务线程。
1.1.5 netty client
RPC 客户端和服务端的网络通信是交给 Netty ( 关于 Netty ... )来完成的,而 Netty 是基于 Reactor 模型实现的基于事件驱动的网络I/O框架,其包含 Boss( Reactor 模型中的 MainReactor )、Worker(Reactor 模型中的 SubReactor)以及基于Channel 的 Pipeline。
image.png
1.1.5.1 Boss
在客户端中,负责发起 connect 请求。而在服务端中则负责 accept 客户端发来的 connect 请求。客户端和服务端建立连接后,则将相应的连接丢给 Worker 去维护。
1.1.5.2 Worker
负责轮询连接(I/O多路复用)是否有数据送达,并负责将数据读写到相应的 Channel 中。
1.1.5.3 Pipeline
负责对 Channel 中的数据进行加工,在 Pigeon 中,其主要包含:序列化、反序列化、完整性校验、解压缩等。
1.2 Server 端
Server 端包括:服务端 Filter、业务线程池、NettyServer。
1.2.1 服务端 Filter
与客户端 Filter 对应,一个请求在进入业务代码之前,要先经过:服务监控、服务鉴权、服务限流等模块。
1.2.2 线程池
将业务逻辑从I/O操作中剥离,数据准备好后,业务代码将在业务线程中执行。在 Pigeon 中,为了防止慢请求影响其他正常请求,会将满足一定条件的慢请求隔离到 SlowRequestPooling 中。
1.2.3 Netty Server
与 NettyClient 类似。
2.远程服务调用的执行过程
image.png假设当客户端和服务端建立连接之后,客户端调用远程服务,参照上图,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 通知后,就将结果返回给之前的方法调用。
3.RPC代理
RPC(Remote Procedure Call) : 远程过程调用,是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。
对于用户来说,使用RPC服务的最佳体验就是,能够像调用本地服务一样调用远程服务,这个功能的实现,就依赖于代理。
RPC中实现代理的方案有jdk 动态代理、cglib 动态代理、javassist 动态代理、ASM字节码等,Pigeon中使用了jdk动态代理
4. 一些问题
- Java服务比如缓存层服务,刚注册到线上就会接收大量流量,有时会因为服务没有完全warmup导致服务不可用(TP耗时飙升),极端情况下会出现雪崩的危险
2.长尾效应
第一次请求在规定时间没有返回,发起第二次请求
网友评论