failover机制的小讨论

  对于一个7*24小时无间断的线上服务来讲,在服役时间内不免会遇到一些fail,例如db断开链接且短暂链接不上了, 下游的某个节点突然挂了,运维部署上依赖的某一个东西不存在了等等场景。本文主要来讨论一下这些场景使用怎样的策略会比较好。nginx

  最简单的方法,While(true) + sleep(固定时间)  不断的重试,直到成功为止。这个方法的优势就是简单,可依赖。缺点就是对于感知延迟要求比较严格的程序,会消耗大量的CPU,甚至由于一些不合理的逻辑致使CPU满载等等状况发生.这种简单粗暴的方法应用普遍,而且能解决实际问题,在不少场合仍是很是可取. 咱们暂且叫这种策略为”粗暴法”.设计模式

  我曾经在一个实时文件抓取程序中(相似于scribe这样的实时日志传输方案),使用了这样的策略,当fstat源文件发现文件不存在的时候,我会重试1000次,每次间隔sleep 10ms, 其间程序会输出不少warnning信息来支持一些报警等,重试完1000次以后(10s以后),将sleep间隔设置为固定时间,例如1s,在下降程序对CPU的消耗的同时,保证了必定的实时性,源文件不管何时出现都可以确保在1s内cover进来,并且这样的策略对于日志切分场景也很是实用,普通的日志切分(如切分nginx为每小时一个文件,crontab每小时mv access.log access.log.$date再 kill -USR1等)程序可以立马感知到并做出相应的策略调整。咱们暂且叫这种策略为”重试N次后,将间隔时间调整为最大的可接受值”.网络

  再看看另一种方法,最近看了下facebook scribe的源码(感兴趣的本身google,你们能够姑且的认为是一个多下游的日志转发工具),他在下游死掉了以后选择对sleep时间按部就班的策略,每次将retryInterval *1.414; (sqrt(2)),再加上一个范围随机数(如1-100ms),同时来设定了一个最大值的方式来相对动态的判断下游状态. 为何必定要设置最大值呢?由于这个策略在异常时间久了以后,滞后性会很是大,当一场恢复时,可能不能及时感知,因此须要一个最大值作保证。咱们暂且叫这种策略为“重试时间按部就班, 且确保不大于最大可接受值“.运维

  近两年来使用zookeeper(如下简称zk)的公司愈来愈多,不少公司都用zk来作大型分布式系统的协调,他的模式相似于:下游经过在zk上注册一个临时节点,告诉你们,我活着呢, 上游经过watch这个节点的变化来感知下游的变化。模式很简单,可是你们都是用zk是由于他提供了不少额外的东西,例以下游注册的临时节点在下游宕机,或者网络不可达(反正就是挂了)等等状况下会自动清除,而且经过回调函数实时让上游程序感知,做出相应变化,当下游活了以后,又注册一个临时节点宣称本身活了,上游程序也能经过回调函数实时感知。上游程序依赖zookeeper的一个Lib库。对于上游程序来讲,他是一个观察者,套进设计模式就是观察者模式,好莱坞有句名言. “不要给我打电话, 我会给你打电话”.咱们暂且叫这种策略为“被动实时感知下游变化”分布式

  先写到这里(也只想到了这些),后续有所想法再补充吧,也欢迎各位看官留言,过去的博文都长篇大论,之后尽可能作到简约不简单吧。毕竟时间精力有限。函数