Rpc In Flink

Liao Jiayi Liao Jiayi #Apache Flink

Apache Flink uses Akka for communication between its Dispatcher, JobMaster, ResourceManager, and TaskExecutor components.

Translated from Chinese with AI · Read the original

Apache Flink uses Akka for communication between its Dispatcher, JobMaster, ResourceManager, and TaskExecutor components.


Dispatcher, JobMaster, ResourceManager, and TaskExecutor all extend the RpcEndpoint abstract class. Let’s look at the RpcEndpoint constructor.

/**
* Initializes the RPC endpoint.
*
* @param rpcService The RPC server that dispatches calls to this RPC endpoint.
* @param endpointId Unique identifier for this endpoint
*/
protected RpcEndpoint(final RpcService rpcService, final String endpointId) {
this.rpcService = checkNotNull(rpcService, "rpcService");
this.endpointId = checkNotNull(endpointId, "endpointId");
this.rpcServer = rpcService.startServer(this);
this.mainThreadExecutor = new MainThreadExecutor(rpcServer, this::validateRunsInMainThread);
}

One of the parameters is a RpcService instance, which is used to start or connect to a RpcEndpoint. For example, TaskExecutor uses its rpcService instance to start the Actor corresponding to its own TaskExecutor. To connect to JobMaster, it calls the connect method on rpcService to obtain the jobMasterGateway associated with JobMaster, allowing it to invoke JobMaster methods remotely through the gateway.

The RpcServer initialized in the constructor is a wrapper around the Actor, containing properties such as address and host.

How does the gateway invoke JobMaster methods remotely?

First, let’s look at how the gateway itself is generated. Starting from the connect method, we reach the end of connectInternal:

private <C extends RpcGateway> CompletableFuture<C> connectInternal(
final String address,
final Class<C> clazz,
Function<ActorRef, InvocationHandler> invocationHandlerFactory) {
checkState(!stopped, "RpcService is stopped");
........
return actorRefFuture.thenCombineAsync(
handshakeFuture,
(ActorRef actorRef, HandshakeSuccessMessage ignored) -> {
InvocationHandler invocationHandler = invocationHandlerFactory.apply(actorRef);
// Rather than using the System ClassLoader directly, we derive the ClassLoader
// from this class . That works better in cases where Flink runs embedded and all Flink
// code is loaded dynamically (for example from an OSGI bundle) through a custom ClassLoader
ClassLoader classLoader = getClass().getClassLoader();
@SuppressWarnings("unchecked")
C proxy = (C) Proxy.newProxyInstance(
classLoader,
new Class<?>[]{clazz},
invocationHandler);
return proxy;
},
actorSystem.dispatcher());
}

This uses the proxy pattern, with AkkaInvocationHandler as the invocation handler. Its invokeRpc method wraps the method being called and its arguments in a RpcInvocation (that is, a Message), then uses Akka’s own mechanisms to deliver it to the Actor corresponding to JobMaster. After receiving the message, JobMaster’s Actor invokes the corresponding method through reflection.