主要接口
RpcEndpoint:
所有提供rpc功能的组件都必须继承的基类,其子类是真正提供rpc服务的组件。
单线程执行,不存在并发修改endpoint状态的情况。和akka actor的理念一致。
RpcServer:RpcEndpoint对应的Rpc服务,rpcserver和endpoint一对一的关系。在akka实现中,可以理解为RpcEndpoint与底层Actor交互的桥梁。
RpcGateway:所有rpc 接口协议都继承此接口。
RpcService:封装了基础的rpc功能。
- 启停RpcServer
- 连接到远程rpc服务,获得RpcGateway
- 调度Runnable、Callable。
Flink RPC启动流程:
- 加载RpcSystem。
RpcSystem.load()通过spi加载RpcSystemLoader
RpcSystemLoader负责具体加载RpcSystem,loadRpcSystem会用一个SubmoduleClassLoader去加载RpcSystem,类似于flink plugin机制。 - RpcSystem初始化RpcService
AkkaRpcSystem#remoteServiceBuilder创建AkkaRpcServiceBuilder
主要逻辑在AkkaRpcServiceBuilder#createAndStart(),首先初始化ActorSystem,然后创建RpcService。 - rpc启动。
Endpoint构造时,RpcService方法参数,并存为成员变量。同时this.rpcServer = rpcService.startServer(this);
初始化rpcserver。此时rpcserver还不能对外提供服务。Endpoint#start()后才可以。
start过程:Endpoint#start()->RpcServer#start()->actorRef.tell(ControlMessages.START)
actor收到start消息处理:- 调用RpcEndpoint.onStart()
- 把state设为STARTED。
- 连接远端rpc服务,AkkaRpcService#connect()。
个人总结:
- ActorSystem是在AkkaRpcServiceBuilder初始化,并存到RpcService成员变量中。
- 每个RpcServer的actor是在rpcService.startServer时创建的。actorRef保存在RpcServer中。
- RpcServer和RpcGateway都是通过java Proxy实现的,底层代理类都是FencedAkkaInvocationHandler和AkkaInvocationHandler。Fenced防止脑裂,在HA的情况下使用。
- RpcEndpoint单线程的实现,
- RpcServer和RpcGateway所有的请求都通过actorRef发消息给actor实现的,actor内部通过反射调用endpoint。
- mainThreadValidator 进行校验,其机制使用endpoint里的currentMainThread 字段记录当前thread,