容錯機制的研究
本文最好結合 https://github.com/apache/dubbo 源碼理解。
找到 AbstractClusterInvoker 的所有子類,他們的集羣容錯功能都在 AbstractClusterInvoker.doInvoker()實現。
在此之前最好理解:
[集羣 cluster]
https://zh.wikipedia.org/wiki/%E8%AE%A1%E7%AE%97%E6%9C%BA%E9%9B%86%E7%BE%A4
[容錯 ]
https://zh.wikipedia.org/wiki/%E6%95%85%E9%9A%9C%E5%AE%B9%E8%A8%B1%E5%BA%A6
[目錄]
https://zh.wikipedia.org/wiki/%E7%9B%AE%E5%BD%95%E6%9C%8D%E5%8A%A1
[節點]
dubbo節點包括,directory,monitor,invoker,registry 四類的概念
一、 通俗解釋
容錯就是當我們在進行函數調用過程中被調用者出現故障時承諾的補償處理方案。
二、具體方案
1).故障轉移 Fail Over
- 處理方案
通過負載均衡重新選一臺Provider提供服務。
- 特點
需要處理等冪性,Loadbalance。會一直轉移直到碰到對的provider。會拉長響應時間。
2).快速失敗 Fast Fail
- 處理方案
出錯直接返回
- 特點
等於放棄做容錯了,直接拋出異常,讓業務端自己處理問題。也會做Loadbalance。
3).忽略錯誤 Fail Safe (佛系處理)
- 處理方案
直接忽略錯誤,返回一個null值,並記錄日誌。
- 特點
等於沒有異常了,服務提供者要麼返回空值,要麼返回正確值。可以理解爲是一種特殊快速失敗法。
4).異步重試 Fail Back (死信隊列重試)
- 處理方案
異常,則啓動定時任務進行重試,直到重試指定次數後異步返回或者輸出log宣告失敗。
- 特點
loadbalance,會重試n次,需要等冪處理,由於調用過的provider可能會被重新調用(巨坑),所以當provider大面積不可用容易引發雪崩,雪崩的原因爲 調用過的provider可能會被重新調用。
5).並行調用 Fork
- 處理方案3
用線程池調用指定個數的provider,只要有一個返回就推出,不管返回的是否爲異常。
- 特點
可以利用集羣提高響應性能,不算容錯,這個性能提升代價,就是要用到線程池。
花裏花俏,沒有想到合適應用場景。
6).廣播調用 Broadcast
- 處理方案
所有provider都會被同步調用一遍,如果發送異常,則只是簡單log。等同步調用完畢後, 只要有一個發送異常,最後會拋出異常,如果全部沒有異常,則返回最後一個provider的result.
- 特點
適合用來做consumer推送通知給Provider集羣,我們通過返回值可以判斷是否有接收者異常,還說說全都成功了。
7).僞造返回 Mock
實現類,他有點特殊,他不是集羣級別的容錯,他只是接口級別的容錯。所以不屬於 AbstractClusterInvoker 的子類。
public class MockClusterInvoker implements Invoker
- 處理方案
可以用來做服務降級,當發送故障時自動調用mockInvoker接口,也可以人工到monitor後臺去強制force.mock實現主動屏蔽provider列表。服務降級可以作爲容錯的兜底方案,當容錯解決不了問題,就用降級做兜底。
- 特點
不屬於集羣容錯,作爲容錯失效的兜底方案,可以人工在monitor後臺對服務接口進行force.mock屏蔽。
8).遍歷找到可用的爲止 Available
- 處理方案
算是非負載均衡版本的故障轉移,他會遍歷所有Invoker節點(dubbo節點包括,directory,monitor,invoker,registry),然後調用Node.isAvailable函數。每個Node都會實現自己的isAvailable函數,用來告訴調用者節點是否有效,比如,有點通過套接字是否關閉,有的判斷destroy()函數是否被調用。
- 特點
涉及到了Node的概念和Node.isAvailable()概念,其原理很簡單就是robin.
9).合併請求 Mergeable
- 處理方案
如果有指定merger的話,合併所有請求的非異常結果。如果沒有則會robin,找一個有效結果執行返回而已。
- 特點
適合用來對所有provider數據做採集。這個方法會使用反射機制自己組合返回結果列表。調用起來相對慢。
總結:
-
負載均衡未必是好事,他會使得請求變得難以跟蹤。一些類似 Available這種遍歷的方法,反而有利於我們跟蹤調用鏈路和簡單定位錯誤。
-
故障轉移的方式有很多種,他們都有一個缺點,得處理等冪問題。
-
拋出異常是最直接的手段,即把問題交給客戶端,但是這顯得很不負責人。而容錯機制就是提客戶端做決定。這種人性化的決定是有代價的,那就是增大延遲(降低了響應速度)。
-
所有具有容錯功能的Invoker節點都是 AbstractClusterInvoker 的子類,他們的集羣容錯功能都在 AbstractClusterInvoker.doInvoker()可以找到。
關鍵詞:
負載均衡,定位故障
故障轉移,等冪處理,
替客戶端做決定, 響應變慢