1、JobManager是Flink集群的主节点,它包含三大重要的组件:
总结:
Flink集群的主节点内部运行着:ResourceManager和Dispatcher,当client提交一个job到集群运行的时候(客户端会把该Job构建成一个JobGragh对象),Dispatcher负责拉起JobManager来负责这个Job内部的Task的执行,执行Task所需要的资源,JobManager向ResourceManager申请。
由上一篇我们知道,JobManager的启动类为StandaloneSessionClusterEntrypoint。这里,我们主要看其核心代码:
StandaloneSessionClusterEntrypoint.main()
ClusterEntrypoint.runClusterEntrypoint(entrypoint)
clusterEntrypoint.startCluster()
runCluster(configuration, pluginManager)
可以看到启动的核心主要在ClusterEntrypoint类中的runCluster方法:
/*************************************************
* 注释:这个方法主要是做两件事情:
* 1、initializeServices() 初始化相关服务
* 2、dispatcherResourceManagerComponentFactory.create() 启动 Dispatcher 和 ResourceManager 服务。
****/
private void runCluster(Configuration configuration, PluginManager pluginManager) throws Exception {
synchronized(lock) {
/**
* 注释: 初始化服务,如 JobManager 的 Akka RPC 服务,HA 服务,心跳检查服务,metric service
* 这些服务都是 Master 节点要使用到的一些服务
* 1、commonRpcService: 基于 Akka 的 RpcService 实现。RPC 服务启动 Akka 参与者来接收从 RpcGateway 调用 RPC
* 2、初始化一个 ioExecutor
* 3、haServices: 提供对高可用性所需的所有服务的访问注册,分布式计数器和领导人选举
* 4、blobServer: 负责侦听传入的请求生成线程来处理这些请求。它还负责创建要存储的目录结构 blob 或临时缓存它们
* 5、heartbeatServices: 提供心跳所需的所有服务。这包括创建心跳接收器和心跳发送者。
* 6、metricRegistry: 跟踪所有已注册的 Metric,它作为连接 MetricGroup 和 MetricReporter
* 7、archivedExecutionGraphStore: 存储执行图ExecutionGraph的可序列化形式。
*/
initializeServices(configuration, pluginManager);
// TODO:将 jobmanager 地址写入配置
// write host information into configuration
configuration.setString(JobManagerOptions.ADDRESS, commonRpcService.getAddress());
configuration.setInteger(JobManagerOptions.PORT, commonRpcService.getPort());
/*************************************************
* 注释: 初始化一个 DefaultDispatcherResourceManagerComponentFactory 工厂实例
* 内部初始化了三大工厂实例
* 1、DispatcherRunnerFactory = DefaultDispatcherRunnerFactory
* 2、ResourceManagerFactory = StandaloneResourceManagerFactory
* 3、RestEndpointFactory(WenMonitorEndpoint的工厂) = SessionRestEndpointFactory
* 返回值:DefaultDispatcherResourceManagerComponentFactory
* 内部包含了这三个工厂实例,就是三个成员变量
* -
* 再补充一个:dispatcherLeaderProcessFactoryFactory = SessionDispatcherLeaderProcessFactoryFactory
*/
final DispatcherResourceManagerComponentFactory dispatcherResourceManagerComponentFactory =
createDispatcherResourceManagerComponentFactory(configuration);
/*************************************************
* 注释:启动关键组件:Dispatcher 和 ResourceManager。
* 1、Dispatcher: 负责用于接收作业提交,持久化它们,生成要执行的作业管理器任务,并在主任务失败时恢复它们。
* 此外, 它知道关于 Flink 会话集群的状态。负责为这个新提交的作业拉起一个新的 JobManager 服务
* 2、ResourceManager: 负责资源的分配和记帐。在整个 Flink 集群中只有一个 ResourceManager,资源相关的内容都由这个服务负责
* registerJobManager(JobMasterId, ResourceID, String, JobID, Time) 负责注册 jobmaster,
* requestSlot(JobMasterId, SlotRequest, Time) 从资源管理器请求一个槽
* 3、WebMonitorEndpoint: 服务于 web 前端 Rest 调用的 Rest 端点,用于接收客户端发送的执行任务的请求
*/
clusterComponent = dispatcherResourceManagerComponentFactory
.create(configuration, ioExecutor, commonRpcService, haServices,
blobServer, heartbeatServices, metricRegistry,
archivedExecutionGraphStore,
new RpcMetricQueryServiceRetriever(metricRegistry.getMetricQueryServiceRpcService()),
this);
/*************************************************
* 注释:集群关闭时的回调
*/
clusterComponent.getShutDownFuture().whenComplete((ApplicationStatus applicationStatus, Throwable throwable) -> {
if(throwable != null) {
shutDownAsync(ApplicationStatus.UNKNOWN, ExceptionUtils.stringifyException(throwable), false);
} else {
// This is the general shutdown path. If a separate more specific shutdown was
// already triggered, this will do nothing
shutDownAsync(applicationStatus, null, true);
}
});
}
}
在这里做了7件初始化服务的事:
/*************************************************
* 注释: 初始化各种服务组件
*/
protected void initializeServices(Configuration configuration, PluginManager pluginManager) throws Exception {
LOG.info("Initializing cluster services.");
synchronized(lock) {
/*************************************************
* 注释: 第一步
* 创建一个 Akka rpc 服务 commonRpcService: 基于 Akka 的 RpcService 实现。
* RPC 服务启动 Akka 参与者来接收从 RpcGateway 调用 RPC
* commonRpcService 其实是一个基于 akka 得 actorSystem,其实就是一个 tcp 的 rpc 服务,端口为:6123
* 1、初始化 ActorSystem
* 2、启动 Actor
*/
commonRpcService = AkkaRpcServiceUtils
.createRemoteRpcService(configuration, configuration.getString(JobManagerOptions.ADDRESS), getRPCPortRange(configuration),
configuration.getString(JobManagerOptions.BIND_HOST), configuration.getOptional(JobManagerOptions.RPC_BIND_PORT));
// TODO 注释: 设置 host 和 port
// update the configuration used to create the high availability services
configuration.setString(JobManagerOptions.ADDRESS, commonRpcService.getAddress());
configuration.setInteger(JobManagerOptions.PORT, commonRpcService.getPort());
/*************************************************
* 注释: 第二步
* 初始化一个 ioExecutor
* 如果你当前节点有 32 个 cpu ,那么当前这个 ioExecutor 启动的线程的数量为 : 128
* 专门负责做IO
*/
ioExecutor = Executors.newFixedThreadPool(ClusterEntrypointUtils.getPoolSize(configuration), new ExecutorThreadFactory("cluster-io"));
/*************************************************
* 注释: 第三步
* HA service 相关的实现,它的作用有很多,到底使用哪种根据用户的需求来定义
* 比如:处理 ResourceManager 的 leader 选举、JobManager leader 的选举等;
* haServices = ZooKeeperHaServices
*/
haServices = createHaServices(configuration, ioExecutor);
/*************************************************
* 注释: 第四步: 初始化一个 BlobServer
* 主要管理一些大文件的上传等,比如用户作业的 jar 包、TM 上传 log 文件等
* Blob 是指二进制大对象也就是英文 Binary Large Object 的缩写
*/
blobServer = new BlobServer(configuration, haServices.createBlobStore());
blobServer.start();
/*************************************************
* 注释: 第五步
* 初始化一个心跳服务
* 在主节点中,其实有很多角色都有心跳服务。 那些这些角色的心跳服务,都是在这个 heartbeatServices 的基础之上创建的
* 这才是真正的 心跳服务的 提供者。
* 谁需要心跳服务,通过 heartbeatServices 去提供一个实例 HeartBeatImpl,用来完成心跳
*/
heartbeatServices = createHeartbeatServices(configuration);
/*************************************************
* 注释: 第六步: metrics(性能监控) 相关的服务
* 1、metricQueryServiceRpcService 也是一个 ActorySystem
* 2、用来跟踪所有已注册的Metric
*/
metricRegistry = createMetricRegistry(configuration, pluginManager);
final RpcService metricQueryServiceRpcService = MetricUtils.startRemoteMetricsRpcService(configuration, commonRpcService.getAddress());
metricRegistry.startQueryService(metricQueryServiceRpcService, null);
final String hostname = RpcUtils.getHostname(commonRpcService);
processMetricGroup = MetricUtils
.instantiateProcessMetricGroup(metricRegistry, hostname, ConfigurationUtils.getSystemResourceMetricsProbingInterval(configuration));
/*************************************************
* 注释: 第七步: ArchivedExecutionGraphStore: 存储 execution graph 的服务, 默认有两种实现,
* 1、MemoryArchivedExecutionGraphStore 主要是在内存中缓存,
* 2、FileArchivedExecutionGraphStore 会持久化到文件系统,也会在内存中缓存。
* 这些服务都会在前面第二步创建 DispatcherResourceManagerComponent 对象时使用到。
* 默认实现是基于 File 的
*/
archivedExecutionGraphStore = createSerializableExecutionGraphStore(configuration, commonRpcService.getScheduledExecutor());
}
}
初始化一个 DefaultDispatcherResourceManagerComponentFactory工厂实例,内部初始化了三个工厂实例:
可查看DefaultDispatcherResourceManagerComponentFactory的构造方法
public DefaultDispatcherResourceManagerComponentFactory(
@Nonnull DispatcherRunnerFactory dispatcherRunnerFactory,
@Nonnull ResourceManagerFactory> resourceManagerFactory,
@Nonnull RestEndpointFactory> restEndpointFactory) {
// TODO 注释: dispatcherRunnerFactory = DefaultDispatcherRunnerFactory
this.dispatcherRunnerFactory = dispatcherRunnerFactory;
// TODO 注释: resourceManagerFactory = StandaloneResourceManagerFactory
this.resourceManagerFactory = resourceManagerFactory;
// TODO 注释: restEndpointFactory = SessionRestEndpointFactory
this.restEndpointFactory = restEndpointFactory;
}
// TODO 注释: 用于 Dispatcher leader 选举
// TODO 注释: dispatcherLeaderRetrievalService = ZooKeeperLeaderRetrievalService
dispatcherLeaderRetrievalService = highAvailabilityServices.getDispatcherLeaderRetriever();
// TODO 注释: 用于 ResourceManager leader 选举
// TODO 注释: resourceManagerRetrievalService = ZooKeeperLeaderRetrievalService
resourceManagerRetrievalService = highAvailabilityServices.getResourceManagerLeaderRetriever();
// TODO 注释: Dispatcher 的 Gateway
final LeaderGatewayRetriever dispatcherGatewayRetriever = new RpcGatewayRetriever<>(rpcService,
DispatcherGateway.class, DispatcherId::fromUuid, 10, Time.milliseconds(50L));
// TODO 注释: ResourceManager 的 Gateway
final LeaderGatewayRetriever resourceManagerGatewayRetriever = new RpcGatewayRetriever<>(rpcService,
ResourceManagerGateway.class, ResourceManagerId::fromUuid, 10, Time.milliseconds(50L));
// TODO 注释: 创建线程池,用于执行 WebMonitorEndpoint 所接收到的 client 发送过来的请求
final ScheduledExecutorService executor = WebMonitorEndpoint
.createExecutorService(configuration.getInteger(RestOptions.SERVER_NUM_THREADS),
configuration.getInteger(RestOptions.SERVER_THREAD_PRIORITY), "DispatcherRestEndpoint");
// TODO 注释: 初始化 MetricFetcher
final long updateInterval = configuration.getLong(MetricOptions.METRIC_FETCHER_UPDATE_INTERVAL);
final MetricFetcher metricFetcher = updateInterval == 0 ? VoidMetricFetcher.INSTANCE : MetricFetcherImpl
.fromConfiguration(configuration, metricQueryServiceRetriever, dispatcherGatewayRetriever, executor);
/*************************************************
* 创建三个实例之一:
* 注释: 创建 WebMonitorEndpoint 实例, 在 Standalone模式下:DispatcherRestEndpoint
* 1、restEndpointFactory = SessionRestEndpointFactory
* 2、webMonitorEndpoint = DispatcherRestEndpoint
* 3、highAvailabilityServices.getClusterRestEndpointLeaderElectionService() = ZooKeeperLeaderElectionService
*/
webMonitorEndpoint = restEndpointFactory
.createRestEndpoint(configuration, dispatcherGatewayRetriever, resourceManagerGatewayRetriever, blobServer, executor, metricFetcher,
highAvailabilityServices.getClusterRestEndpointLeaderElectionService(), fatalErrorHandler);
/*************************************************
* 注释: 启动 DispatcherRestEndpoint
* 1、启动 Netty 服务端
* 2、选举
* 3、启动定时任务 ExecutionGraphCacheCleanupTask
*/
log.debug("Starting Dispatcher REST endpoint.");
webMonitorEndpoint.start();
final String hostname = RpcUtils.getHostname(rpcService);
/*************************************************
* 注释: 2.创建 StandaloneResourceManager 实例对象
* 1、resourceManager = StandaloneResourceManager
* 2、resourceManagerFactory = StandaloneResourceManagerFactory
*/
resourceManager = resourceManagerFactory
.createResourceManager(configuration, ResourceID.generate(), rpcService, highAvailabilityServices, heartbeatServices,
fatalErrorHandler, new ClusterInformation(hostname, blobServer.getPort()), webMonitorEndpoint.getRestBaseUrl(), metricRegistry,
hostname);
final HistoryServerArchivist historyServerArchivist = HistoryServerArchivist
.createHistoryServerArchivist(configuration, webMonitorEndpoint, ioExecutor);
final PartialDispatcherServices partialDispatcherServices = new PartialDispatcherServices(configuration, highAvailabilityServices,
resourceManagerGatewayRetriever, blobServer, heartbeatServices,
() -> MetricUtils.instantiateJobManagerMetricGroup(metricRegistry, hostname), archivedExecutionGraphStore, fatalErrorHandler,
historyServerArchivist, metricRegistry.getMetricQueryServiceGatewayRpcAddress());
/*************************************************
* 注释: 3.创建 并启动 Dispatcher
* 1、dispatcherRunner = DispatcherRunnerLeaderElectionLifecycleManager
* 2、dispatcherRunnerFactory = DefaultDispatcherRunnerFactory
* 第一个参数: ZooKeeperLeaderElectionService
* -
* 老版本: 这个地方是直接创建一个 Dispatcher 对象然后调用 dispatcher.start() 来启动
* 新版本: 直接创建一个 DispatcherRunner, 内部就是要创建和启动 Dispatcher
*/
log.debug("Starting Dispatcher.");
dispatcherRunner = dispatcherRunnerFactory
.createDispatcherRunner(highAvailabilityServices.getDispatcherLeaderElectionService(), fatalErrorHandler,
// TODO 注释: 注意第三个参数
new HaServicesJobGraphStoreFactory(highAvailabilityServices), ioExecutor, rpcService, partialDispatcherServices);
/*************************************************
* 注释: resourceManager 启动
*/
log.debug("Starting ResourceManager.");
resourceManager.start();
/*************************************************
* 注释: resourceManagerRetrievalService 启动
*/
resourceManagerRetrievalService.start(resourceManagerGatewayRetriever);
/*************************************************
* 注释: ZooKeeperHaServices 启动
*/
dispatcherLeaderRetrievalService.start(dispatcherGatewayRetriever);
/*************************************************
* 注释: 构建 DispatcherResourceManagerComponent
*/
return new DispatcherResourceManagerComponent(dispatcherRunner, resourceManager, dispatcherLeaderRetrievalService,
resourceManagerRetrievalService, webMonitorEndpoint);
/*************************************************
* 注释: 注意这个方法,因为当前这个类是 LeaderLatchListener 的子类,所以当该组件在进行选举如果成功的话
* 则会自动调用 isLeader() 方法,否则调用 notLeader 方法。
* 这是 ZooKeeper 的 API 框架 cruator 的机制
*/
@Override
public void start(LeaderContender contender) throws Exception {
Preconditions.checkNotNull(contender, "Contender must not be null.");
Preconditions.checkState(leaderContender == null, "Contender was already set.");
LOG.info("Starting ZooKeeperLeaderElectionService {}.", this);
synchronized(lock) {
client.getUnhandledErrorListenable().addListener(this);
// TODO 注释: 这个值到底是什么,根据情况而定
leaderContender = contender;
/*************************************************
* 注释: Flink的选举,和 HBase 一样都是通过 ZooKeeper 的 API 框架 Curator 实现的
* 1、leaderLatch.start(); 事实上就是举行选举
* 2、当选举结束的时候:
* 如果成功了: isLeader()
* 如果失败了: notLeader()
*/
leaderLatch.addListener(this);
leaderLatch.start();
/*************************************************
* 注释: 注册监听器,如果选举结束之后:
* 1、自己成为 Leader, 则会回调 isLeader() 进行处理
* 2、自己成为 Follower,则会回调 notLeader() 进行处理
*/
cache.getListenable().addListener(this);
cache.start();
client.getConnectionStateListenable().addListener(listener);
running = true;
}
}
前提:当Actor被ActorSystem创建的时候,例如,workerActorSystem.actorOf(Props[MyNodeManager], "WorkerActor"),会直接先调用其构造方法,后调用preStart()方法。
如上图所示,当执行resourceManagerFactory.createResourceManager(...)方法时,最终会通过RpcEndpoint的构造方法来创建。如下所示:
protected RpcEndpoint(final RpcService rpcService, final String endpointId) {
this.rpcService = checkNotNull(rpcService, "rpcService");
this.endpointId = checkNotNull(endpointId, "endpointId");
/*************************************************
* 注释: 启动 ResourceManager 的 RPCServer 服务
* 这里启动的是 ResourceManager 的 Rpc 服务端。
* 接收 TaskManager启动好了而之后, 进行注册和心跳,来汇报 Taskmanagaer 的资源情况
* 通过动态代理的形式构建了一个Server
*/
this.rpcServer = rpcService.startServer(this);
this.mainThreadExecutor = new MainThreadExecutor(rpcServer, this::validateRunsInMainThread);
}
当在DefaultDispatcherResourceManagerComponentFactory中执行resourceManager.start()时会调用ResourceManager中的onStart()方法,先进行ResourceManager的选举,一样的是通过ZookeeperLeaderElectionService的start(...)来执行。选举成功后,然后调用其isLeader()方法来执行子类的grantLeadership()方法。更多可查看以下代码:
@Override
public void grantLeadership(final UUID newLeaderSessionID) {
/*************************************************
* 注释: 调用: tryAcceptLeadership 方法
*/
final CompletableFuture acceptLeadershipFuture = clearStateFuture
.thenComposeAsync((ignored) -> tryAcceptLeadership(newLeaderSessionID), getUnfencedMainThreadExecutor());
// TODO 注释: 调用 confirmLeadership
final CompletableFuture confirmationFuture = acceptLeadershipFuture.thenAcceptAsync((acceptLeadership) -> {
if(acceptLeadership) {
// confirming the leader session ID might be blocking,
leaderElectionService.confirmLeadership(newLeaderSessionID, getAddress());
}
}, getRpcService().getExecutor());
// TODO 注释: 调用 whenComplete
confirmationFuture.whenComplete((Void ignored, Throwable throwable) -> {
if(throwable != null) {
onFatalError(ExceptionUtils.stripCompletionException(throwable));
}
});
}
private CompletableFuture tryAcceptLeadership(final UUID newLeaderSessionID) {
// TODO 注释: 判断,如果集群有了 LeaderResourceManager
if(leaderElectionService.hasLeadership(newLeaderSessionID)) {
// TODO 注释: 申城一个 ResourceManagerID
final ResourceManagerId newResourceManagerId = ResourceManagerId.fromUuid(newLeaderSessionID);
log.info("ResourceManager {} was granted leadership with fencing token {}", getAddress(), newResourceManagerId);
// TODO 注释: 如果之前已成为过 Leader 的话,则清理之前的状态
// clear the state if we've been the leader before
if(getFencingToken() != null) {
clearStateInternal();
}
setFencingToken(newResourceManagerId);
/*************************************************
* 注释: 启动服务
* 1、启动心跳服务
* 启动两个定时任务
* 2、启动 SlotManager 服务
* 启动两个定时任务
*/
startServicesOnLeadership();
return prepareLeadershipAsync().thenApply(ignored -> true);
} else {
return CompletableFuture.completedFuture(false);
}
}
其中的startServicesOnLeadership()方法来启动2个心跳服务以及启动2个SlotManager服务。查看
1.启动心跳服务代码如下:
/*************************************************
* 注释: 当前 ResourceManager 启动了两个心跳服务:
* 1、taskManagerHeartbeatManager 这个心跳管理器 关心点的是: taskManager 的死活
* 2、jobManagerHeartbeatManager 这个心跳管理器 关心点的是: jobManager 的死活
* taskManager 集群的资源提供者,任务执行者,从节点
* jobManager 每一个job会启动的一个主控程序
* 不管是集群的从节点执行心跳,还是每一个job会启动的一个主控程序 都是向 ResourceManager 去汇报
*/
private void startHeartbeatServices() {
/*************************************************
* 注释: 用来收听: TaskManager 的心跳
*/
taskManagerHeartbeatManager = heartbeatServices.createHeartbeatManagerSender(resourceId, new TaskManagerHeartbeatListener(), getMainThreadExecutor(), log);
/*************************************************
* 注释: 用来收听: JobManager 的心跳
*/
jobManagerHeartbeatManager = heartbeatServices.createHeartbeatManagerSender(resourceId, new JobManagerHeartbeatListener(), getMainThreadExecutor(), log);
}
区分概念:
1.taskManager:集群的资源提供者,任务执行者,从节点
2.jobManager:每一个job会启动的一个主控程序
主节点:StandaloneSessionClusterEntrypoint
从节点:TaskManager管理心跳:
主节点管理资源:ResourceManager
从节点管理资源: TaskExecutor
2.开启的2个定时任务:
开启第一个定时任务:checkTaskManagerTimeouts,检查TaskManager的心跳 时间间隔30s
开启第二个定时任务:checkSlotRequestTimeouts,检查SplotRequest超时处理 时间间隔5分钟。jobManager申请资源超过5分钟,进行处理。
resourceManager的start方法
这里只是发送START消息,意味着resourceManager启动好了。
rpcEndpoint.tell(ControlMessages.START, ActorRef.noSender());
1、重要的查看下面的调用选举方法:前面2个调用选举方法传入的是this,这里传入的dispatcherRunner。同样的,在执行完start()方法后,会执行isLeader()方法。
private DispatcherRunnerLeaderElectionLifecycleManager(T dispatcherRunner, LeaderElectionService leaderElectionService) throws Exception {
this.dispatcherRunner = dispatcherRunner;
this.leaderElectionService = leaderElectionService;
/*************************************************
* 注释: 启动选举
* 参数:dispatcherRunner = DefaultDispatcherRunner
* 调用对象:leaderElectionService = ZooKeeperLeaderElectionService
* 这个选举服务对象 leaderElectionService 内部的 leaderContender 是 : DefaultDispatcherRunner
*/
leaderElectionService.start(dispatcherRunner);
// leaderElectionService.start(this);
}
2.当上述选举成功后,会进入到DefaultDispatcherRunner
在这里开启Dispatcher服务。
public void grantLeadership(UUID leaderSessionID) {
/*************************************************
* 注释: 开启 Dispatcher 服务
*/
runActionIfRunning(() -> startNewDispatcherLeaderProcess(leaderSessionID));
}
后续流程:
DefaultDispatcherRunner.startNewDispatcherLeaderProcess(...)
AbstractDispatcherLeaderProcess.start(...)
AbstractDispatcherLeaderProcess.startInternal(...)
SessionDispatcherLeaderProcess.onStart(...)
SessionDispatcherLeaderProcess.onStart(...)如下:
@Override
protected void onStart() {
/*************************************************
* TODO 注释: 开启服务: 启动 JobGraghStore
* 一个用来存储 JobGragh 的存储组件
*/
startServices();
// TODO 注释: 到现在为止,依然还没有启动 Dispatcher
onGoingRecoveryOperation = recoverJobsAsync()
/*************************************************
* TODO 运行: createDispatcherIfRunning()
*/
.thenAccept(this::createDispatcherIfRunning)
.handle(this::onErrorIfRunning);
}
接上面:createDispatcherIfRunning
SessionDispatcherLeaderProcess.createDispatcherIfRunning(...)
SessionDispatcherLeaderProcess.createDispatcher(...)
DefaultDispatcherGatewayServiceFactory.create(...) 在这里创建和启动dispatcher()
@Override
public AbstractDispatcherLeaderProcess.DispatcherGatewayService create(DispatcherId fencingToken, Collection recoveredJobs,
JobGraphWriter jobGraphWriter) {
// TODO 注释: Dispatcher 的一个默认引导程序
// TODO 注释: 待恢复执行的 job 的集合
final DispatcherBootstrap bootstrap = new DefaultDispatcherBootstrap(recoveredJobs);
final Dispatcher dispatcher;
try {
/*************************************************
* TODO 注释: 创建 Dispatcher
* dispatcherFactory = SessionDispatcherFactory
*/
dispatcher = dispatcherFactory.createDispatcher(rpcService, fencingToken, bootstrap,
// TODO 注释: PartialDispatcherServicesWithJobGraphStore
PartialDispatcherServicesWithJobGraphStore.from(partialDispatcherServices, jobGraphWriter));
} catch(Exception e) {
throw new FlinkRuntimeException("Could not create the Dispatcher rpc endpoint.", e);
}
/*************************************************
* TODO 注释: Dispatcher 也是一个 RpcEndpoint 启动起来了之后,给自己发送一个 Hello 消息证明启动
*/
dispatcher.start();
// TODO 注释: 返回一个返回值
return DefaultDispatcherGatewayService.from(dispatcher);
}
当执行dispatcher.start()方法时,会调用内部的onStart()方法。在这里,启动Dispatcher服务和引导程序初始化,把所有中断的job恢复执行。