Zookeeper HA相关配置
## 使用zk做HA
high-availability: zookeeper
## zk地址
high-availability.zookeeper.quorum: node1:2181,node2:2181,node3:2181
## flink在zk下的工作路径
high-availability.zookeeper.path.root: /flink
## 任务所在的HA路径
high-availability.cluster-id: /default
## 保存元数据到文件系统
high-availability.storageDir: hdfs:///flink/recovery
## --任务运行在YARN上的配置--
## applicationMaster重试的次数,默认为1,当application master失败的时候,该任务不会重启。
## 设置一个比较大的值的话,yarn会尝试重启applicationMaster。
yarn.application-attempts: 10
## flink是否应该重新分配失败的taskmanager容器。默认是true。
yarn.reallocate-failed:true
## applicationMaster可以接受的容器最大失败次数,达到这个参数,就会认为yarn job失败。
## 默认这个次数和初始化请求的taskmanager数量相等(-n 参数指定的)。
yarn.maximum-failed-containers:1
flink使用Zookeeper做HA
flink的ResourceManager、Dispatcher、JobManager、WebServer组件都需要高可用保证,同时flink高可用还需要持久化checkpoint的元数据信息,保留最近一次已经完成的checkpoint等工作,其中最重要的就是组件的leader选举、leader状态跟踪。本次抽取出Flink使用zk实现leader选举、leader状态跟踪代码,学习下flink是如何使用curator的。类之间的关系如下:
ZooKeeperHaServices是HighAvailabilityServices基于zookeeper的实现,通过使用ZooKeeperUtils类来创建组件的LeaderRetrievalService以及LeaderElectionService。
LeaderRetrievalService用来跟踪leader的变化,当发现leader地址变化时,要通知依赖它的组件去依赖新的leader。比如getResourceManagerLeaderRetriever方法,flink会监听zk的/leader/resource_manager_lock节点内容变化,内容是rm的leader地址和leaderUUID,而taskmanger调用该服务的start方法传递了一个LeaderRetrievalListener。如果节点内容发生变化,意味着rm的leader地址发生变化,那么的LeaderRetrievalListener的notifyLeaderAddress就会通知taskmanger去新的ResourceManager地址进行注册。zk实现该功能使用的是curator的NodeCache并重写了nodeChanged方法。
LeaderElectionService用来进行leader选举工作,当节点成为leader后会调用LeaderContender的grantLeadership方法。以ResourceManagerLeaderElection为例,flink会在zk的/leaderlatch/resource_manager_lock路径下创建临时节点,创建成功的rm节点成为leader触发rm的grantLeadership,最终将当前地址和UUID写入/leader/resource_manager_lock中,这样就触发了LeaderRetrievalService服务。zk实现leader选举使用的是curator的LeaderLatch并重写了isLeader和notLeader方法。同时使用NodeCache监听/leader/resource_manager_lock内容变化,确保新leader地址和UUID成功写入节点。
LeaderRetrievalListener对LeaderRetrievalService的leader地址变化做出响应,通过notifyLeaderAddress传递新leader地址。
LeaderContender对LeaderElectionService的节点角色发生变化做出响应,通过grantLeadership和revokeLeadership进行leader的授权和撤销工作。
一个集群目录下的zk结构如下图所示:
zk文件系统目录
flink相关源码
简单的走一下流程,看看集群启动时是如何创建ZooKeeperHaServices的。
集群启动入口ClusterEntrypoint
- 根据集群的部署模式session or perjob由对应的子类调用ClusterEntrypoint的startCluster方法启动集群,接着会先调用initializeServices方法,启动集群相关的组件信息。这里只看启动haServices部分。
public void startCluster() throws ClusterEntrypointException {
SecurityContext securityContext = installSecurityContext(configuration);
securityContext.runSecured((Callable<Void>) () -> {
runCluster(configuration);
return null;
});
}
protected void initializeServices(Configuration configuration) {
ioExecutor = Executors.newFixedThreadPool(
Hardware.getNumberCPUCores(),
new ExecutorThreadFactory("cluster-io"));
haServices = createHaServices(configuration, ioExecutor);
blobServer = new BlobServer(configuration, haServices.createBlobStore