Flink Standalone集群启动源码分析

1、JobManager源码分析

JobManager 是 Flink 集群的主节点,它包含三大重要的组件
1、ResourceManager
Flink的集群资源管理器,只有一个,关于slot的管理和申请等工作,都由他负责
2、Dispatcher
负责接收用户提交的 JobGragh, 然后启动一个 JobManager, 类似于 YARN 集群中的
AppMaster 角色,类似于 Spark Job 中的 Driver 角色
3、WebMonitorEndpoint
里面维护了很多很多的Handler,如果客户端通过 flink run 的方式来提交一个 job 到 flink
集群,最终,是由 WebMonitorEndpoint 来接收,并且决定使用哪一个 Handler 来执行处理
submitJob ===> SubmitJobHandler

JobMaster(Dispatcher中创建)
负责一个具体的 Job 的执行,在一个集群中,可能会有多个 JobMaster同时执行,类似于 YARN
集群中的 AppMaster 角色,类似于 Spark Job 中的 Driver 角色
flink job执行总结:
Flink 集群的主节点内部运行着:ResourceManager 和 Dispatcher,当 client 提交一个 job 到
集群运行的时候(客户端会把该 Job 构建成一个 JobGragh 对象),Dispatcher 负责拉起
JobMaster来负责这个 Job 内部的 Task 的执行,执行Task所需要的资源,JobMaster向
ResourceManager 申请。

StandaloneSessionClusterEntrypoint
ClusterEntrypoint.runClusterEntrypoint-> startCluster -> ClusterEntrypoint.runCluster
	private void runCluster(Configuration configuration, PluginManager pluginManager) throws Exception {
   
		synchronized(lock) {
   
			/**
			 * TODO ->
			 *  注释: 初始化服务,如 JobManager 的 Akka RPC 服务,HA 服务,心跳检查服务,metric service
			 *  这些服务都是 Master 节点要使用到的一些服务
			 *  1、commonRpcService: 	基于 Akka 的 RpcService 实现。RPC 服务启动 Akka 参与者来接收从 RpcGateway 调用 RPC
			 *  2、haServices: 			提供对高可用性所需的所有服务的访问注册,分布式计数器和领导人选举
			 *  3、blobServer: 			负责侦听传入的请求生成线程来处理这些请求。它还负责创建要存储的目录结构 blob 或临时缓存它们
			 *  4、heartbeatServices: 	提供心跳所需的所有服务。这包括创建心跳接收器和心跳发送者。
			 *  5、metricRegistry:  	跟踪所有已注册的 Metric,它作为连接 MetricGroup 和 MetricReporter
			 *  6、archivedExecutionGraphStore:  	存储执行图ExecutionGraph的可序列化形式。
			 */
			initializeServices(configuration, pluginManager);

			// TODO 注释: 将 jobmanager 地址写入配置
			// write host information into configuration
			configuration.setString(JobManagerOptions.ADDRESS, commonRpcService.getAddress());
			configuration.setInteger(JobManagerOptions.PORT, commonRpcService.getPort());

			/*************************************************
			 * TODO 
			 *  注释: 初始化一个 DefaultDispatcherResourceManagerComponentFactory 工厂实例
			 *  内部初始化了四大工厂实例
			 *  1、DispatcherRunnerFactory = DefaultDispatcherRunnerFactory
			 *  2、ResourceManagerFactory = StandaloneResourceManagerFactory
			 *  3、RestEndpointFactory(WenMonitorEndpoint的工厂) = SessionRestEndpointFactory
			 *  返回值:DefaultDispatcherResourceManagerComponentFactory
			 *  内部包含了这三个工厂实例,就是三个成员变量
			 *  -
			 *  再补充一个:dispatcherLeaderProcessFactoryFactory = SessionDispatcherLeaderProcessFactoryFactory
			 *
			 * --> StandaloneSessionClusterEntrypoint.createDispatcherResourceManagerComponentFactory
			 *
			 */
			final DispatcherResourceManagerComponentFactory dispatcherResourceManagerComponentFactory =
				createDispatcherResourceManagerComponentFactory(configuration);

			/*************************************************
			 * TODO 
			 *   注释:启动关键组件: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 端点,用于接收客户端发送的执行任务的请求
			 *
			 *   --> DefaultDispatcherResourceManagerComponentFactory.create
			 */
			clusterComponent = dispatcherResourceManagerComponentFactory
				.create(configuration, ioExecutor, commonRpcService, haServices,
					blobServer, heartbeatServices, metricRegistry,
					archivedExecutionGraphStore,
					new RpcMetricQueryServiceRetriever(metricRegistry.getMetricQueryServiceRpcService()),
					this);

			/*************************************************
			 *  TODO
			 *  注释:集群关闭时的回调
			 */
			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);
				}
			});
		}
	}

1、 initializeServices

	 -> commonRpcService = AkkaRpcServiceUtils.createRemoteRpcService -> createAndStart
	   -> new AkkaRpcService -> supervisor = startSupervisorActor();
	          SupervisorActor是个actor (class SupervisorActor extends AbstractActor  extends Actor)
           -> final ActorRef actorRef = SupervisorActor.startSupervisorActor(actorSystem, terminationFutureExecutor);
           -> Supervisor.create(actorRef, terminationFutureExecutor) ->  new Supervisor()

2、 创建和启动WebMonitorEndpoint,ResourceManager,Dispatcher

     --> clusterComponent = dispatcherResourceManagerComponentFactory.create
              -> DefaultDispatcherResourceManagerComponentFactory.create(
             创建和启动WebMonitorEndpointResourceManagerDispatcher) 

2.1 启动 webMonitorEndpoint

    ->  webMonitorEndpoint.start() -> RestServerEndpoint.start
           -> (2.1.1) 初始化handler(包括: JobSubmitHandler)  
                 handlers = initializeHandlers -> DispatcherRestEndpoint.initializeHandlers
              -> super.initializeHandlers -> 
              		/*************************************************
			 * TODO 
			 *  注释: Handler 容器初始化
			 *  
			 *   ChannelInboundHandler  channelRead0()  方法,这个方法会自动被 Netty 去调用执行
			 * 	不管是这里初始化的那个 Handler, 里面都有一个 handleRequest 的方法
			 * 	channelRead0() 的底层,最终调用的就是 Hnadler.handleRequest() 方法
			 * 	将来我们提交 Job 的时候,最终,由 WebMonitorEndpoint(DispatcherRestEndpoint) 接收到,
			 * 	跳转到使用 JobSubmitHandler 来执行 最终执行请求的就是 JobSubmitHandler.handleRequest()
			 *  这些 Handler 的作用,其实就对应到 Flink web 页面的 rest 服务, Handler == Servlet 如   bigdata02:port/list
			 */ 
			ArrayList<Tuple2<RestHandlerSpecification, ChannelInboundHandler>> handlers = new ArrayList<>(30);
              -> new JobSubmitHandler(将来客户端提交应用程序上来,由 JobManager 中的 Netty 服务端的 JobSubmitHandler 来执行处理)
              
            ->(2.1.2) 启动 Netty 服务端,添加所有初始化好的handler -> bootstrap = new ServerBootstrap();
                     -> bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(initializer);
                     
            ->(2.1.3) 启动 startInternal -> WebMonitorEndpoint.startInternal
                    选举通用套路
                   		/*************************************************
				 * TODO 
				 *  注释: 选举 ZooKeeperLeaderElectionService
				 *   this 很重要,哪个对象进行选举操作就是那个对象 这里是WebMonitorEndpoint
				 *               选举成功后会调用该对象的grantLeaderShip方法
				 *   不管你在那个地方见到这种格式的代码:leaderElectionService.start(this);
				 *  一定要记住,最终,
				 *  1、参与选举的 某个获胜的角色会调用:
				 *      leaderElectionService.isLeader() ==> leaderContender.grantLeaderShip()
				 *  2、参与选举的 某个失败的角色会调用: leaderElectionService.notLeader()
				 */
				leaderElectionService.start(this);
				-> ZooKeeperLeaderElectionService.start(){
   
				    /*************************************************
					 * TODO 
					 *  注释: Fink 的 选举,和 HBase 一样都是通过 ZooKeeper 的 API 框架 Curator 实现的
					 *  1、leaderLatch.start(); 事实上就是举行选举
					 *  2、leaderLatch.addListener 添加了监听器 当选举结束的时候:
					 *  	如果监听到成功了: isLeader()
					 *      如果监听到失败了: notLeader()
					 */
					leaderLatch.addListener(this);
					leaderLatch.start();
				}
				-> isLeader(){
   
					/*************************************************
					 * TODO 
					 *  注释: 分配 LeaderShip
					 *  leaderContender = JobManagerRunnerImpl
					 *  leaderContender = ResourceManager
					 *  leaderContender = DefaultDispatcherRunner
					 *  leaderContender = WebMonitorEndpoint 
					 *  当前是WebMonitorEndpoint,后续 哪个组件进行选举就执行那个组件的grantLeadership方法
					 *
					 *  leaderElectionService.start(this);
					 *  leaderContender = this
					 */
					leaderContender.grantLeadership(issuedLeaderSessionID);
				}
				--> WebMonitorEndpoint.grantLeadership(){
   
						 * TODO 
						 *  注释: 确认 Leader
						 */
						leaderElectionService.confirmLeadership(leaderSessionID, getRestBaseUrl());
				}

2.2 创建 StandaloneResourceManager 实例对象和SlotManager

       DefaultDispatcherResourceManagerComponentFactory.create() 
        resourceManager = resourceManagerFactory.createResourceManager -> ResourceManagerFactory.createResourceManager
        --> (2.2.1) 创建SlotManager   
          createResourceManagerRuntimeServices -> ResourceManagerRuntimeServices.fromConfiguration
          -> SlotManager slotManager = new SlotManagerImpl
        --> (2.2.2) 创建 ResourceManager 实例
          createResourceManager -> StandaloneResourceManagerFactory.createResourceManager
           -> new StandaloneResourceManager -> super -> ResourceManager -> super -> FencedRpcEndpoint -super
           -> RpcEndpoint(){
   
			this.rpcService = checkNotNull(rpcService, "rpcService");
		    this.endpointId = checkNotNull(endpointId, "endpointId");
			/*************************************************
			 * TODO 
			 *  注释: 启动 ResourceManager 的 RPCServer 服务
			 *  这里启动的是 ResourceManager 的 Rpc 服务端。
			 *  接收 TaskManager启动好了而之后, 进行注册和心跳,来汇报 Taskmanagaer 的资源情况
			 *  通过动态代理的形式构建了一个Server、
			 *
			 *  --> AkkaRpcService.startServer
			 */
			this.rpcServer = rpcService.startServer(this);
	
			/*************************************************
			 * TODO 
			 *  注释: 线程池的初始化
			 */
			this.mainThreadExecutor = new MainThreadExecutor(rpcServer, this::validateRunsInMainThread);
}
-> rpcService.startServer(this); -> AkkaRpcService.startServer(){
   
        /*************************************************
		 * TODO 通过代理的方式来获取一个 ActorRef 对象
		 *  注释: RpcServer 实现类
		 *  JDK 提供的动态代理: Proxy InvocationHandler
		 */
		akkaInvocationHandler = new AkkaInvocationHandler(akkaAddress, hostname, actorRef, configuration.getTimeout(),
			configuration.getMaximumFramesize
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值