本文介绍下Flink的容错机制,目的主要是了解下如果Flink环境发生异常,会不会对计算结果造成影响。
Flink JobManager的HA仅支持StandAlone和Yarn Cluster两种集群模式。
StandAlone和Yarn Cluster模式下的HA实现方式各不相同:
Standalone 集群的 JobManager 高可用性的概念是,任何时候都有一个主 JobManager 和 多个备 JobManagers,在主JobManager失异常退出时,会由备JobNamager 接管集群。这样就保证了没有单点故障,一旦备 JobManager 接管集群,作业依旧可以正常运行。
Yarn Session高可用的话,只会启动一个 JobManager。当 JobManager 发生异常退出时,Yarn 根据yarn.resourcemanager.am.max-attempts(这个配置是个全局配置,如果是1,那么所有提交的job都将只尝试运行一次,所以要设置的大于1),通过将ApplicationMaster重启来保证Flink集群的高可用。
如何配置JobManager的HA详见“参考一”,别人已经写的很详细了,我这里就不搬运了。
(ps:个人建议是长作业尽量使用Yarn Cluster模式中的Single Job Model,而不是Yarn Session Model或者StandAlone,这样可以做到资源隔离,避免Job之间相互干扰,而且也不会导致某个Job导致TaskManager异常,所有Job都要重启。Per job的方式一般不需要配置HA,如果配置了的话,那么使用的方式是Standalone的那种HA方式)
如果TaskManager挂了,Flink会先将Job cancel掉,然后再以相同的JobID,往集群中仍然存活的TaskManager上部署Job,这时候,如果还有足够的Slot,则Job能够恢复。或者如果使用的per Job的模式,container异常退出了,job会重新启动一个新的container,然后再从Checkpoint恢复,如下图所示:
反正就是一般情况下TaskManager挂了,Job也能从checkpoint中恢复。但是这时候会有一个问题:部署在某些TaskManager上的Task数会比之前多,造成了这些TaskManager的负载较重,可能还是会出现问题。这时候还是尽快恢复挂掉的TaskManager为好。
除了JobManager和TaskManager会出现问题,Job也会出现异常,比如本人在Flink1.10中遇到过序列化问题,Job老是报序列化出错然后自行重启,重启完毕之后又能继续运行下去了(至今没定位到这个错误的原因是啥,换了ES客户端版本之后又不出现了...)。
Flink提供了多种Job重启策略,可以使Job从最近一次checkpoint自动恢复。重启策略有如下几种:
Job重启策略 | 重启策略介绍 |
Fixed delay | 按照固定的时间间隔,尝试多次重启Job |
Failure rate | Job失败后会重启,但是超过失败率后,Job会最终被认定失败 |
No restart | Job失败后,不会重启 |
Fall back | 使用集群的重启策略(默认配置) |
重启策略可以在配置文件中进行全局配置,也可以从代码中对单个作业进行单独配置,例如:
// 在代码中设置 env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, Time.of(10, TimeUnit.SECONDS))); // 在flink-conf.yaml配置文件中设置 restart-strategy: fixed-delay restart-strategy.fixed-delay.attempts: 3 restart-strategy.fixed-delay.delay: 10 s
为了与Job重启做区分,官方将Task的重启策略叫做故障恢复策略(failover strategy)。
Restart strategies and failover strategies are used to control the task restarting. Restart strategies decide whether and when the failed/affected tasks can be restarted. Failover strategies decide which tasks should be restarted to recover the job.
它有两个选项:
重启Job中所有的Task,即重置整个ExecutionGraph,简单粗暴。配置文件中配置full。
只重启ExecutionGraph中对应的Region包含的Task,更加智能,降低overhead。配置文件中配置region。
如下所示,如果我们的ExecutionGraph是一个非连通图(即可以划分为多个独立的pipeline),那么当某个Task失败时,就可以只回溯到该Task所在的连通分量的Source,并重启该连通分量涉及到的所有Task,而其他Task不受影响,如下图所示。此时一个连通分量就是一个Region。
参考:
https://www.cnblogs.com/zz-ksw/p/11990612.html(HA如何配置)
https://blog.csdn.net/weixin_34342578/article/details/85768114(Yarn app max attempt解析)
https://bobjin.com/blog/view/c5f7e5827fc5a9aaeac818fb53ddeafd.html(Flink开发中遇到的问题及解决办法)
https://www.jianshu.com/p/ee30a5da90ba?tdsourcetag=s_pcqq_aiomsg(Flink JobManager HA)
https://ci.apache.org/projects/flink/flink-docs-stable/ops/jobmanager_high_availability.html
https://ci.apache.org/projects/flink/flink-docs-release-1.10/dev/task_failure_recovery.html(Job重启策略)
https://www.jianshu.com/p/e701e7ecdc08(Restart Pipelined Region Failover Strategy图示)