image.png
    主要接口
    RpcEndpoint:
    所有提供rpc功能的组件都必须继承的基类,其子类是真正提供rpc服务的组件。
    单线程执行,不存在并发修改endpoint状态的情况。和akka actor的理念一致。
    RpcServer:RpcEndpoint对应的Rpc服务,rpcserver和endpoint一对一的关系。在akka实现中,可以理解为RpcEndpoint与底层Actor交互的桥梁。
    RpcGateway:所有rpc 接口协议都继承此接口。
    RpcService:封装了基础的rpc功能。

    1. 启停RpcServer
    2. 连接到远程rpc服务,获得RpcGateway
    3. 调度Runnable、Callable。

    Flink RPC启动流程:

    1. 加载RpcSystem。
      RpcSystem.load()通过spi加载RpcSystemLoader
      RpcSystemLoader负责具体加载RpcSystem,loadRpcSystem会用一个SubmoduleClassLoader去加载RpcSystem,类似于flink plugin机制。
    2. RpcSystem初始化RpcService
      AkkaRpcSystem#remoteServiceBuilder创建AkkaRpcServiceBuilder
      主要逻辑在AkkaRpcServiceBuilder#createAndStart(),首先初始化ActorSystem,然后创建RpcService。
    3. rpc启动。
      Endpoint构造时,RpcService方法参数,并存为成员变量。同时this.rpcServer = rpcService.startServer(this);初始化rpcserver。此时rpcserver还不能对外提供服务。Endpoint#start()后才可以。
      start过程:Endpoint#start()->RpcServer#start()->actorRef.tell(ControlMessages.START)
      actor收到start消息处理:
      1. 调用RpcEndpoint.onStart()
      2. 把state设为STARTED。
    4. 连接远端rpc服务,AkkaRpcService#connect()。

    个人总结:

    1. ActorSystem是在AkkaRpcServiceBuilder初始化,并存到RpcService成员变量中。
    2. 每个RpcServer的actor是在rpcService.startServer时创建的。actorRef保存在RpcServer中。
    3. RpcServer和RpcGateway都是通过java Proxy实现的,底层代理类都是FencedAkkaInvocationHandler和AkkaInvocationHandler。Fenced防止脑裂,在HA的情况下使用。
    4. RpcEndpoint单线程的实现,
      1. RpcServer和RpcGateway所有的请求都通过actorRef发消息给actor实现的,actor内部通过反射调用endpoint。
      2. mainThreadValidator 进行校验,其机制使用endpoint里的currentMainThread 字段记录当前thread,