1、Flink RPC 详解 0:5:00 ~ 0:26:00
1、ActorSystem 是管理 Actor生命周期的组件, Actor是负责进行通信的组
2、每个 Actor 都有一个 MailBox,别的 Actor 发送给它的消息都首先储存在 MailBox 中,通过这种 方式可以实现异步通信。
3、每个 Actor 是单线程的处理方式,不断的从 MailBox 拉取消息执行处理,所以对于 Actor 的消息处 理,不适合调用会阻塞的处理方法。
4、Actor 可以改变他自身的状态,可以接收消息,也可以发送消息,还可以生成新的 Actor
5、每一个ActorSystem 和 Actor都在启动的时候会给定一个 name,如果要从ActorSystem中,获取一 个 Actor,则通过以下的方式来进行 Actor的获取: akka.tcp://asname@bigdata02:9527/user/actorname 6、如果一个 Actor 要和另外一个 Actor进行通信,则必须先获取对方 Actor 的 ActorRef 对象,然 后通过该对象发送消息即可。
7、通过 tell 发送异步消息,不接收响应,通过 ask 发送异步消息,得到 Future 返回,通过异步回到 返回处理结果
Flink 中的 RPC 实现主要在 flink-runtime 模块下的 org.apache.flink.runtime.rpc 包中,涉及
到的最重要的 API 主要是以下这四个:
1、RpcGateway 路由,RPC的老祖宗,各种其他RPC组件,都是 RpcGateWay 的子类
2、RpcServer RpcService 和 RpcEndpoint 之间的粘合层
3、RpcEndpoint 业务逻辑载体,对应的 Actor 的封装
4、RpcService 对应 ActorSystem 的封装
RpcEndpoint 下面有四个比较重要的子类:
1、TaskExecutor 2、Dispatcher 3、JobMaster 4、ResourceManager
创建成功了之后,都会要去执
行他的 onStart() ,在集群启动的源码分析中,其实这些组件的很多的工作流程,都被放在 onStart() 里
面。
2、Flink 集群启动脚本分析 0: 26:00 ~ 0:37:00
flink-dist 子项目中,位于 flink-bin 下的 bin 目录:启动脚本为:start�cluster.sh
会首先调用 config.sh 来获取 masters 和 workers,masters 的信息,是从 conf/masters 配置
文件中获取的, workers 是从 conf/workers 配置文件中获取的。然后分别:
1、通过 jobmanager.sh 来启动 JobManager
2、通过 taskmanager.sh 来启动 TaskManager
内部,都通过 flink-daemon.sh 脚本来启动 JVM 进程,分析 flink-daemon.sh 脚本发现:
1、JobManager 的启动代号:standalonesession,实现类是: StandaloneSessionClusterEntrypoint
2、TaskManager 的启动代号:taskexecutor,实现类是:TaskManagerRunner
3、Flink 主节点 JobManager 启动分析 0:37:00 ~ 3:16:00
1、ResourceManager Flink的集群资源管理器,只有一个,关于slot的管理和申请等工作,都由他负责 2、Dispatcher 负责接收用户提交的 JobGragh, 然后启动一个 JobManager, 类似于 YARN 集群中的 AppMaster 角色,类似于 Spark Job 中的 Driver 角色
3、JobManager 负责一个具体的 Job 的执行,在一个集群中,可能会有多个 JobManager 同时执行,类似于 YARN 集群中的 AppMaster 角色,类似于 Spark Job 中的 Driver 角色
4、WebMonitorEndpoint 里面维护了很多很多的Handler,如果客户端通过 flink run 的方式来提交一个 job 到 flink 集群,最终,是由 WebMonitorEndpoint 来接收,并且决定使用哪一个 Handler 来执行处理 submitJob ===> SubmitJobHandler
JobManager的启动主类:
org.apache.flink.runtime.entrypoint.StandaloneSessionClusterEntrypoint
-------------------源码开始 1、 webMonitor 启动 ---------------------
StandaloneSessionClusterEntrypoint#main()
▼
/** 注释:创建 StandaloneSessionClusterEntrypoint
*/
StandaloneSessionClusterEntrypoint entrypoint = new
StandaloneSessionClusterEntrypoint(configuration);
/*************************************************
注释:启动集群的entrypoint
* 这个方法接受的是父类 ClusterEntrypoint,可想而知其他几种启动方式也是通过这个方法。
*/
ClusterEntrypoint.runClusterEntrypoint(entrypoint);
——》ClusterEntrypoint#runClusterEntrypoint
clusterEntrypoint.startCluster();
——》ClusterEntrypoint#startCluster
▼
* 注释: 根据配置初始化文件系统
* 三种东西;
* 1、本地 Local 客户端的时候会用 JobGragh ===> JobGraghFile
* 2、HDFS FileSytem(DistributedFileSystem)
* 3、封装对象 HadoopFileSystem, 里面包装了 HDFS 的 FileSYSTEM 实例对象
*/
configureFileSystems(configuration, pluginManager);
* 注释: 集群启动入口
*/
runCluster(configuration, pluginManager);
——》ClusterEntrypoint#runCluster
▼
/* 1 注释 初始化各类服务线程池
initializeServices(configuration, pluginManager);
/* 2 初始化 4大 工厂实例
* DispatcherRunnerFactory = DefaultDispatcherRunnerFactory
* ResourceManagerFactory = StandaloneResourceManagerFactory
* RestEndpointFactory(WenMonitorEndpoint的工厂) = SessionRestEndpointFactory
* 返回值:DefaultDispatcherResourceManagerComponentFactory
* 内部包含了这三个工厂实例,就是三个成员变量
* 再补充一个:dispatcherLeaderProcessFactoryFactory = SessionDispatcherLeaderProcessFactoryFactory
*/
final DispatcherResourceManagerComponentFactory dispatcherResourceManagerComponentFactory = createDispatcherResourceManagerComponentFactory(configuration);
clusterComponent = dispatcherResourceManagerComponentFactory.create(
↓
***1重点方法 DefaultDispatcherResourceManagerComponentFactory#create
▼
(163行) webMonitorEndpoint.start(); //
------------------- 2 、Resourcemanager启动部分 2:14:00 ----------------
167行)resourceManager = resourceManagerFactory.createResourceManager
↓
ResourceManagerFactory#createResourceManager
↓
StandaloneResourceManagerFactory#createResourceManager
↓
ResourceManager#构造函数
当执行完毕这个构造方法的时候,会触发调用 onStart() 方法执行
↓
FencedRpcEndpoint#构造函数
↓
RpcEndpoint#构造函数
▼
this.rpcServer = rpcService.startServer(this);
↓
AkkaRpcService#startServer
.......▲▲(回到ResourceManager类Onstart)
ResourceManager#Onstart() —— 2:24:00
——》ResourceManager#startResourceManagerServices
▼
// TODO_MA 注释: 注意这个 this 对象
// TODO_MA 注释: 执行选举,成功之后,调用 leaderElectionService.isLeader()
// TODO_MA 注释: this = ResourceManager
leaderElectionService.start(this);
↓
ZooKeeperLeaderElectionService#start
▼
/*** 注释: Fink 的 选举,和 HBase 一样都是通过 ZooKeeper 的 API 框架 Curator 实现的
* 1、leaderLatch.start(); 事实上就是举行选举
* 2、当选举结束的时候:
* 如果成功了: isLeader()
* 如果失败了: notLeader()
/
leaderLatch.addListener(this);
leaderLatch.start();
——》ZooKeeperLeaderElectionService#isLeader()
▼
/* 注释: 分配 LeaderShip
* leaderContender = JobManagerRunnerImpl
* leaderContender = ResourceManager
* leaderContender = DefaultDispatcherRunner
* leaderContender = WebMonitorEndpoint
*
* leaderElectionService.start(this);
* leaderContender = this
/
leaderContender.grantLeadership(issuedLeaderSessionID);
↓
ResourceManager#grantLeadership
(ignored) -> tryAcceptLeadership
↓ 实现类为 ResourceManager
——》ResourceManager# tryAcceptLeadership
▼
/ 注释: 启动服务
* 1、启动心跳服务 启动两个定时任务
* 2、启动 SlotManager 服务 启动两个定时任务
/
startServicesOnLeadership();
▼
/
* 注释: 开启心跳服务
*/
startHeartbeatServices();
/* 注释: 启动 SlotManagerImpl
* 这个里面只是开启了两个定时任务而已
*/
slotManager.start(getFencingToken(), getMainThreadExecutor(), new
. ......▲▲▲▲(回到DefaultDispatcherResourceManagerComponentFactory)
------------------- 3、 Dispatcher启动部分 2:47 :00 ----------------
回到 : DefaultDispatcherResourceManagerComponentFactory#create 方法
dispatcherRunner = dispatcherRunnerFactory .createDispatcherRunner(highAvailabilityServices.getDispatcherLeaderElectionService(), fatalErrorHandler,// TODO_MA 注释: 注意第三个参数
new HaServicesJobGraphStoreFactory(highAvailabilityServices), ioExecutor, rpcService, partialDispatcherServices);
↓
DefaultDispatcherRunnerFactory#createDispatcherRunner
return DefaultDispatcherRunner.create
——》DefaultDispatcherRunner#create
return DispatcherRunnerLeaderElectionLifecycleManager.createFor
——》DispatcherRunnerLeaderElectionLifecycleManager#createFor
return new DispatcherRunnerLeaderElectionLifecycleManager<>(dispatcherRunner, leaderElectionService);
——》DispatcherRunnerLeaderElectionLifecycleManager构造函数
/*** * 又开启了选举 ,同上resourcemanager相同
* 这个选举服务对象 leaderElectionService 内部的 leaderContender 是 :
** DefaultDispatcherRunner
leaderElectionService.start(dispatcherRunner);
↓
——》同上节一样启动 ZooKeeperLeaderElectionService#isLeader()
leaderContender.grantLeadership(issuedLeaderSessionID);
↓ 实现类为 DefaultDispatcherRunner
DefaultDispatcherRunner#grantLeadership
* 注释: 开启 Dispatcher 服务
runActionIfRunning(() -> startNewDispatcherLeaderProcess(leaderSessionID));
——》DefaultDispatcherRunner#startNewDispatcherLeaderProcess
thenRun(newDispatcherLeaderProcess::start))
↓
AbstractDispatcherLeaderProcess#start
——》AbstractDispatcherLeaderProcess#startInternal
onStart()
↓
SessionDispatcherLeaderProcess#onStart()
▼
/* 注释: 开启服务: 启动 JobGraghStore
* 一个用来存储 JobGragh 的存储组件
/
startServices();
// TODO_MA 注释: 到现在为止,依然还没有启动 Dispatcher
.thenAccept(this::createDispatcherIfRunning)
——》SessionDispatcherLeaderProcess#createDispatcherIfRunning
——》 SessionDispatcherLeaderProcess#createDispatcher
final DispatcherGatewayService dispatcherService = dispatcherGatewayServiceFactory.create(
↓
DefaultDispatcherGatewayServiceFactory#create
▼
/ 注释: 创建 Dispatcher
dispatcher = dispatcherFactory.createDispatcher(rpcService, fencingToken, bootstrap,
↓
SessionDispatcherFactory#createDispatcher
return new StandaloneDispatcher(rpcService, fencingToken, dispatcherBootstrap,
↓
StandaloneDispatcher构造函数
↓ StandaloneDispatcher为RPCendpoint类
Dispatcher 类 Onstart方法
▼
* 注释: 启动 Dispatcher 服务
*/
startDispatcherServices();
* 注释: 引导程序初始化
* 把所有中断的 job 恢复执行
*/
dispatcherBootstrap.initialize(this,
↓
DefaultDispatcherBootstrap#initialize
launchRecoveredJobGraphs(dispatcher, recoveredJobs);
↓
AbstractDispatcherBootstrap#launchRecoveredJobGraphs
* 注释: 恢复执行 待恢复的 Job
*/
dispatcher.runRecoveredJob(recoveredJob);
▼
* 注释: 调用 runJob 运行一个任务
FutureUtils.assertNoException(runJob(recoveredJob).handle
——》Dispatcher#runJob
......▲▲▲▲(回到DefaultDispatcherResourceManagerComponentFactory)结束 3:17 :00