flink为了保证线上作业的可用性,提供了ha机制,如果发现线上作业失败,则通过ha中存储的信息来实现作业的重新拉起。
我们在flink的线上环境使用了zk为flink的ha提供服务,但在初期,由于资源紧张,只是对zk进行了standalone的部署,但是在后期的使用中,发现单节点的集群很难提供很高的可用性,
所以就尝试将目前的standalone的zk服务扩展为cluster的zk服务,这其中,也踩了不少坑。
第一次尝试,将standalone的zk扩展为cluster
扩展为cluster很简单,找了两台集群,部署了zk服务,然后将三台节点的zk的zoo.cfg同步了下,然后重启每个zk服务。
结果失败了,线上的作业都死掉了。
这里的坑在于重启之后,zk的信息都丢掉了,成了一个空集群,已经在线上跑的作业拿不到相应的信息,就死掉了。
第二次尝试,将standalone的zk扩展为cluster
第一次之所以信息都丢了,是因为最初的那个standalone的机器,并没有一开始就重启,反而是放到最后重启了,导致他从别人往自己同步信息,自己的信息都丢了。
所以这次,前面还是一样的套路,但是zoo.cfg同步之后,先重启之前standalone的节点,之后重启其他两个节点。
完美,这次信息没有发生丢失,相应的数据都在。
结果作业还是挂了,为啥?因为重启zk的节奏太慢,信息虽然都在,但是zk不可用的时间太长。
然后又试了一次,这次加快节奏,别拖泥带水。
信息没有丢失,作业没有失败,但是作业重启了,因为虽然重启各个zk很快,但也要20s左右的时间,这个时间以及超过zk与客户端维护心跳的时间了。但万幸作业没有挂掉。
但是商量之后觉得,线上那么多作业,如果都restart一次,还是不太好。所以最终决定还是搭新集群,以前的作业走老集群,新提的作业走新集群,维护两个集群,直到没有人使用老集群,麻烦,但是对用户友好。
第三次尝试,组建完全新的zk集群
这个就很好弄了,先搭了个5个节点的zk集群,然后测试了下作业提交,没有问题,完美。
结果没几分钟就被打脸,用户反映之前的作业没法下线。
好吧,这个场景没考虑到。因为用户下线作业的时候,其实也需要到zk中去获取线上dispatcher的地址,但是新集群是不包含之前应用的信息啊。
没办法,只能同步zk信息了,好在在github上找到一个zkMove的项目,测了下,可以用,就赶紧同步了下相应的信息。
教训,其实可以在一开始就通过离线同步zk信息的方式来组建新的zk集群,这样就不会发生类似的事情了。
第四次尝试,复用yarn的zk集群
因为资源限制,上面搭的集群都在yarn的zk集群上,但是启用了2183端口。运维同学不干了,他们监控zk只监控2183接口。
所以最终还是复用yarn的zk集群,那么就又得找个夜深人静的时候去同步zk信息了。
其实最大的教训在于,一开始就应该将zk搞成cluster模式,哪怕是伪集群,即在一个节点上的集群,这样后期要扩容或者缩容,都会方便很多。