對於一個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庫。對於上游程序來講,他是一個觀察者,套進設計模式就是觀察者模式,好萊塢有句名言. 「不要給我打電話, 我會給你打電話」.咱們暫且叫這種策略爲「被動實時感知下游變化」。分佈式
先寫到這裏(也只想到了這些),後續有所想法再補充吧,也歡迎各位看官留言,過去的博文都長篇大論,之後儘可能作到簡約不簡單吧。畢竟時間精力有限。函數