互聯網等系統對於可用性都非常的重視,構建一個高可用的系統,有些常用的招數,在這裡簡單的說下,其實多數都是靠各互聯網公司在實戰中摸爬滾打積累出來的“血淚”經驗。
1. 監控和報警
沒有監控和報警的在線系統,就像是開著一輛沒有儀表盤的車一樣,因此如果沒有監控和報警,其他一切都是浮雲,這點說起來容易,做起來卻是比較折騰的,例如監控點需要有哪些,怎麼報警是合適的。
這個的評估比較容易,就是故障發生是不是都是監控和報警先發現的,故障發現率是衡量這件事做的咋樣的一個不錯的指標。
2. SPoF(Single Point of Failure)
這是高可用系統中最不允許的現象,應用如果只部署在一台機器上,就意味著只要這台機器出現問題,就不可用了,為了避免這個問題,通常會采用cluster、主備的方式,實在不好做的情況下才用主備,例如帶狀態的DB等,而對於不帶狀態的,最好還是用cluster的方式,因為主備方式實現較麻煩,另外不具備伸縮性。
單台機器這只是SPoF中的一個狹義的點,更放大看還會有單框機器(如果是刀框的話)、單個機櫃、單個網絡核心路由、單個機房、單個城市,可見一個真正的高可用系統要解決的技術問題是不少的,並且是要付出較高的成本的。
3. 解耦
業務邏輯在實現上總是會有很多關鍵的邏輯,還有一些附加的邏輯,例如在做完操作後要發個短信通知什麼的,如果把這些邏輯也放到主邏輯過程中一起實現,可能會出現的問題就是這些邊緣邏輯出問題,然後導致主邏輯掛了,因此在實現系統時需要做一定的解耦,關鍵的邏輯同步完成,而非關鍵邏輯則通過異步的消息系統來完成,這是在設計高可用系統時一個非常關鍵的點。
除了後端這種實現的解耦外,前端頁面的構成其實也需要考慮好解耦,例如一個頁面上,有些內容即使不顯示也不會出什麼問題的,對於這些內容應該通過ajax等方式來實現和主要內容解耦。
4. 隔離
一個業務系統,必然會涵蓋多種多樣的功能,而這些功能中必然會有重要的和不重要的,例如上面解耦後頁面上有些不重要的內容會通過ajax來異步獲取,而如果這個不重要的內容的生成和重要的內容生成是同一個系統的話,有可能會出現不重要的內容生成的代碼處理慢,從而導致把共同的處理線程池的所有線程耗滿。
為了解決這個問題,通常可以采用兩種辦法,一是拆分系統,直接把重要的和不重要的拆成兩個應用,二是通過七層路由來分到不同的機器上,也可以是域名,這樣系統仍然是同一個,七層路由對性能損害很大,慎用(除非是類似基於zk實現的軟負載,然後在客戶端執行的七層路由)。
除了重要功能和不重要功能外,還會出現耗資源和相對不怎麼耗資源(包括很多種,例如DB連接..)、給重要用戶和普通用戶,對於這些情況,都需要采用上面的兩種辦法來做到隔離。
5. 容災
一個在線運行的系統,不可避免的要面對各種災難事件,而一個高可用的系統,必須做到在各種災難事件面前堅挺的活著,為了做到這個,需要有N多的措施。
通常系統都會依賴到其他的一些系統,而這個時候首先要做的就是超時控制,看過N多的case,都是由於沒有設置超時時間,從而在依賴的系統響應變慢的情況下,自己的系統的所有處理線程也被拖S的現象,因此所有的阻塞的wait的地方都一定要是帶超時的,在線系統更能接受的是失敗,響應慢絕對是在線系統的噩夢。
除了超時外,在代碼的實現上需要做一些自動降級的策略,有些時候調用的這個後端系統可能不是那麼關鍵的邏輯,那麼在這種情況下,應支持自動的降級,當後端系統出現超時等問題的時候,直接忽略掉,例如很多應用都會有待讀的消息數,當讀不到的時候,其實不顯示關系也不大,因此此時可以自動降級掉。
除了自動降級外,還需要有多種手動降級的策略,例如一個頁面上的很多功能點都需要支持手工關閉的開關,這樣可以在某些系統出現問題,或壓力大時可以直接關閉掉,降低系統壓力,一種典型的例子是例如高清晰的圖片會消耗掉很多的帶寬,如果帶寬緊急的情況下,應該支持顯示更低質量一點的圖片,當然,這是有一定損害的降級,但相比系統全掛,顯然是這個方式好。
自恢復能力也是系統設計時的重要考慮點,例如當依賴的系統出問題到恢復後,系統本身也要能自恢復,例如一個最簡單的是依賴的一個系統掛了,不能說還得重啟系統本身才能恢復。
自我保護能力是容災中的重要點,例如需要處理的請求超過了處理能力,那這個時候應該拒絕,要做到這點,必須首先知道系統的處理能力到底是多少(小聲的說一句:所有的模擬的壓力測試都是無法反應系統的處理能力的,要拿到系統的處理能力必須是用真實的訪問來測試,原因是數據、用戶行為其實是無法模擬的或者說難度非常非常的高),除了處理能力的保護外,還應該做負載層面的保護,以避免某些情況下即使在處理能力范圍內,負載出現飙高導致無法登陸機器處理故障的現象。
除了上面說的這些系統層面的策略外,容災還需要考慮機房層面的容災、地域的容災。
從上面5點來說,要做到一個高可用的系統真心不容易,從編程技巧、系統設計以及基礎設施(IDC)建設都需要作出巨大的努力,並且要付出巨大的成本,而對於一個高訪問量的大規模系統而言,基本上所有認為不太可能發生的事其實都是會發生的,如果沒有准備好的話,瞬間可用率就會大幅損失。