可復用的服務模塊為業務產品提供基礎公共服務,大型網站中這些服務通常都獨立分布式部署,被具體應用遠程調用。可復用的服務和應用一樣,也是無狀態的服務,因此可以使用類似負載均衡的失效轉移策略實現高可用的服務。
除此之外,具體實踐中,還有以下幾點高可用的服務策略。
分級管理
運維上將服務器進行分級管理,核心應用和服務優先使用更好的硬件,在運維響應速度上也格外迅速。顯然,用戶及時付款比能不能評價商品更重要,所以訂單、支付比評價服務有更高優先級。
同時在服務部署上也進行必要的隔離,避免故障的連鎖反應。低優先級的服務通過啟動不同的線程或者部署在不同的虛擬機上進行隔離,而高優先級的服務則需要部署在不同的物理機上,核心服務和數據甚至需要部署在不同地域的數據中心。
超時設置
由于服務端宕機、線程死鎖等原因,可能導致應用程序對服務端的調用失去響應,進而導致用戶請求長時間得不到響應,同時還占用應用程序的資源,不利于及時將訪問請求轉移到正常的服務器上。
在應用程序中設置服務調用的超時時間,一旦超時,通信框架就拋出異常,應用程序根據服務調度策略,可選擇繼續重試或將請求轉移到提供相同服務的其他服務器上。
異步調用
應用對服務的調用通過消息隊列等異步方式完成,避免一個服務失敗導致整個應用請求失敗的情況。如提交一個新用戶注冊請求,應用需要調用三個服務:將用戶信息寫入數據庫,發送賬號注冊成功郵件,開通對應權限。如果采用同步服務調用,當郵件隊列阻塞不能發送郵件時,會導致其他兩個服務也無法執行,最終導致用戶注冊失敗。
如果采用異步調用的方式,應用程序將用戶注冊信息發送給消息隊列服務器后立即返回用戶注冊成功響應。而記錄用戶注冊信息到數據庫、發送用戶注冊成功郵件、調用用戶服務開通權限這三個服務作為消息的消費者任務,分別從消息隊列獲取用戶注冊信息異步執行。即使郵件服務器隊列阻塞,郵件不能成功發送,也不會影響其他服務的執行,用戶注冊操作可順利完成,只是晚一點收到注冊成功的郵件而已。
當然不是所有服務調用都可以異步調用,對于獲取用戶信息這類調用,采用異步方式會延長響應時間,得不償失。對于那些必須確認服務調用成功才能繼續下一步操作的應用也不適合使用異步調用。
服務降級
在網站訪問高峰期,服務可能因為大量的并發調用而性能下降,嚴重時可能會導致服務宕機。為了保證核心應用和功能的正常運行,需要對服務進行降級。降級有兩種手段:拒絕服務及關閉服務。
拒絕服務
拒絕低優先級應用的調用,減少服務調用并發數,確保核心應用正常使用;或者隨機拒絕部分請求調用,節約資源,讓另一部分請求得以成功,避免要死大家一起死的慘劇。Twitter 就喜歡用隨機拒絕請求的策略,經常有用戶看到請求失敗的故障頁面,但是問下周圍的人,其他人都正常使用,自己再刷新頁面,也好了。關閉服務
關閉部分不重要的服務,或者服務內部關閉不重要的功能,以節約系統開銷,為重要的服務和功能讓出資源。淘寶在每年雙十一促銷中就使用這種方法,在系統最繁忙時關閉“評價”、“確認收貨”等非核心服務,以保證核心交易服務順利完成。
冪等性設計
應用調用服務失敗后,會將調用請求重新發送到其他服務器,但是這個失敗可能是虛假的失敗。比如服務已經處理成功,但因為網絡故障應用沒有收到響應,這是應用重新提交請求就導致服務重復調用,如果這個服務是一個轉賬操作,就會產生嚴重后果。
服務重復調用是無法避免的,應用層也不關心服務是否真的失敗,只要沒有收到調用成功的響應,就可以認為調用失敗,并重試服務調用。因此必須在服務層保證服務重復調用和調用一次產生的結果相同,即服務具有冪等性。
有些服務天然具有冪等性,比如將用戶性別設置為男性,不管設置多少次,結果都一樣。但是對于轉賬交易等操作,問題就會比較復雜,需要通過交易編號等信息進行服務調用有效性校驗,只有有效的操作才能繼續執行。