1 寫在前面
1.1 名詞解釋
consumer表示服務調(diào)用方?
provider標示服務提供方蝇率,dubbo里面一般就這么講考润。
下面的A調(diào)用B服務,一般是泛指調(diào)用B服務里面的一個接口蓬蝶。
1.2 拓撲圖
大寫字母表示不同的服務供炎,后面的序號表示同一個服務部署在不同機器的實例。
?
2 從微觀角度思考
?
2.1 超時(timeout)
在接口調(diào)用過程中疾党,consumer調(diào)用provider的時候音诫,provider在響應的時候,有可能會慢雪位,如果provider 10s響應竭钝,那么consumer也會至少10s才響應。如果這種情況頻度很高雹洗,那么就會整體降低consumer端服務的性能香罐。
這種響應時間慢的癥狀,就會像一層一層波浪一樣时肿,從底層系統(tǒng)一直涌到最上層庇茫,造成整個鏈路的超時。
所以螃成,consumer不可能無限制地等待provider接口的返回旦签,會設(shè)置一個時間閾值,如果超過了這個時間閾值寸宏,就不繼續(xù)等待宁炫。
這個超時時間選取,一般看provider正常響應時間是多少氮凝,再追加一個buffer即可羔巢。
?
2.2 重試(retry)
超時時間的配置是為了保護服務,避免consumer服務因為provider 響應慢而也變得響應很慢罩阵,這樣consumer可以盡量保持原有的性能竿秆。
但是也有可能provider只是偶爾抖動,那么超時后直接放棄稿壁,不做后續(xù)處理幽钢,就會導致當前請求錯誤,也會帶來業(yè)務方面的損失常摧。
那么搅吁,對于這種偶爾抖動威创,可以在超時后重試一下,重試如果正常返回了谎懦,那么這次請求就被挽救了肚豺,能夠正常給前端返回數(shù)據(jù),只不過比原來響應慢一點界拦。
重試時的一些細化策略:
重試可以考慮切換一臺機器來進行調(diào)用吸申,因為原來機器可能由于臨時負載高而性能下降,重試會更加劇其性能問題享甸,而換一臺機器截碴,得到更快返回的概率也更大一些。
?
2.2.1 冪等(idempotent)
如果允許consumer重試蛉威,那么provider就要能夠做到冪等日丹。
即,同一個請求被consumer多次調(diào)用蚯嫌,對provider產(chǎn)生的影響(這里的影響一般是指某些寫入相關(guān)的操作) 是一致的哲虾。
而且這個冪等應該是服務級別的,而不是某臺機器層面的择示,重試調(diào)用任何一臺機器束凑,都應該做到冪等。
?
2.3 熔斷(circuit break)
重試是為了應付偶爾抖動的情況栅盲,以求更多地挽回損失汪诉。
可是如果provider持續(xù)的響應時間超長呢?
如果provider是核心路徑的服務,down掉基本就沒法提供服務了谈秫,那我們也沒話說扒寄。 如果是一個不那么重要的服務,卻因為這個服務一直響應時間長導致consumer里面的核心服務也拖慢孝常,那么就得不償失了旗们。
單純超時也解決不了這種情況了,因為一般超時時間构灸,都比平均響應時間長一些,現(xiàn)在所有的打到provider的請求都超時了岸梨,那么consumer請求provider的平均響應時間就等于超時時間了喜颁,負載也被拖下來了。
而重試則會加重這種問題曹阔,使consumer的可用性變得更差半开。
因此就出現(xiàn)了熔斷的邏輯,也就是赃份,如果檢查出來頻繁超時寂拆,就把consumer調(diào)用provider的請求奢米,直接短路掉,不實際調(diào)用纠永,而是直接返回一個mock的值鬓长。
等provider服務恢復穩(wěn)定之后,重新調(diào)用尝江。
?
2.3.1 簡單的熔斷處理邏輯
目前我們框架有通過注解使用的熔斷器涉波,大家可以參考應用在項目中。
?
2.4 限流(current limiting)
上面幾個策略都是consumer針對provider出現(xiàn)各種情況而設(shè)計的炭序。
而provider有時候也要防范來自consumer的流量突變問題啤覆。
這樣一個場景,provider是一個核心服務惭聂,給N個consumer提供服務窗声,突然某個consumer抽風,流量飆升辜纲,占用了provider大部分機器時間嫌佑,導致其他可能更重要的consumer不能被正常服務。
所以侨歉,provider端屋摇,需要根據(jù)consumer的重要程度,以及平時的QPS大小幽邓,來給每個consumer設(shè)置一個流量上線炮温,同一時間內(nèi)只會給A consumer提供N個線程支持,超過限制則等待或者直接拒絕牵舵。
?
2.4.1 資源隔離
provider可以對consumer來的流量進行限流柒啤,防止provider被拖垮。?
同樣畸颅,consumer 也需要對調(diào)用provider的線程資源進行隔離担巩。 這樣可以確保調(diào)用某個provider邏輯不會耗光整個consumer的線程池資源。
?
2.4.2 服務降級
降級服務既可以代碼自動判斷没炒,也可以人工根據(jù)突發(fā)情況切換涛癌。
?
2.4.2.1 consumer 端
consumer 如果發(fā)現(xiàn)某個provider出現(xiàn)異常情況,比如送火,經(jīng)常超時(可能是熔斷引起的降級)拳话,數(shù)據(jù)錯誤,這是种吸,consumer可以采取一定的策略弃衍,降級provider的邏輯,基本的有直接返回固定的數(shù)據(jù)坚俗。
?
2.4.2.2 provider 端
當provider 發(fā)現(xiàn)流量激增的時候镜盯,為了保護自身的穩(wěn)定性岸裙,也可能考慮降級服務。?
比如速缆,1降允,直接給consumer返回固定數(shù)據(jù),2激涤,需要實時寫入數(shù)據(jù)庫的拟糕,先緩存到隊列里,異步寫入數(shù)據(jù)庫倦踢。
?
3 從宏觀角度重新思考
宏觀包括比A -> B 更復雜的長鏈路送滞。
長鏈路就是 A -> B -> C -> D這樣的調(diào)用環(huán)境。
而且一個服務也會多機部署辱挥,A 服務實際會存在 A1犁嗅,A2,A3 …
微觀合理的問題晤碘,宏觀未必合理褂微。
下面的一些討論,主要想表達的觀點是:如果系統(tǒng)復雜了园爷,系統(tǒng)的容錯配置要整體來看宠蚂,整體把控,才能做到更有意義童社。
?
3.1 超時
如果A給B設(shè)置的超時時間求厕,比B給C設(shè)置的超時時間短,那么肯定不合理把扰楼,A超時時間到了直接掛斷呀癣,B對C支持太長超時時間沒意義。
R表示服務consumer自身內(nèi)部邏輯執(zhí)行時間弦赖,TAB表示consumer A開始調(diào)用provider B到返回的時間 项栏。
那么那么TAB > RB + TBC 才對。
?
3.2 重試
重試跟超時面臨的問題差不多蹬竖。
B服務一般100ms返回沼沈,所以A就給B設(shè)置了110ms的超時,而B設(shè)置了對C的一次重試案腺,最終120ms正確返回了庆冕,但是A的超時時間比較緊,所以B對C的重試被白白浪費了劈榨。
A也可能對B進行重試,但是由于上一條我們講到的晦嵌,可能C確實性能不好同辣,每次B重試一下就OK拷姿,但是A兩次重試其實都無法正確的拿到結(jié)果。
N標示設(shè)置的重試次數(shù)
修正一下上面section的公式旱函,TAB > RB+TBC * N响巢。
雖然這個公式本身沒什么問題,但是棒妨,如果站在長鏈路的視角來思考踪古,我們需要整體規(guī)劃每個服務的超時時間和重試次數(shù),而不是僅僅公式成立即可券腔。
比如下面情況:
A -> B -> C伏穆。
RB = 100ms,TBC=10ms
B是個核心服務纷纫,B的計算成本特別大枕扫,那么A就應該盡量給B長一點的超時時間,而盡量不要重試調(diào)用B辱魁,而B如果發(fā)現(xiàn)C超時了烟瞧,B可以多調(diào)用幾次C,因為重試C成本小染簇,而重試B成本則很高参滴。 so …
?
3.3 熔斷
A -> B -> C,如果C出現(xiàn)問題了锻弓,那么B熔斷了砾赔,則A就不用熔斷了。
?
3.4 限流
B只允許A以QPS<=5的流量請求弥咪,而C卻只允許B以QPS<=3的qps請求过蹂,那么B給A的設(shè)定就有點大,上游的設(shè)置依賴下游聚至。
而且限流對QPS的配置酷勺,可能會隨著服務加減機器而變化,最好是能在集群層面配置扳躬,自動根據(jù)集群大小調(diào)整脆诉。
?
3.5 服務降級
服務降級這個問題,如果從整體來操作贷币,
1击胜,一定是先降級優(yōu)先級地的接口,兩權(quán)相害取其輕?
2役纹,如果服務鏈路整體沒有性能特別差的點偶摔,比如就是外部流量突然激增,那么就從外到內(nèi)開始降級促脉。?
3如果某個服務能檢測到自身負載上升辰斋,那么可以從這個服務自身做降級策州。
?
3.6 漣漪
A -> B -> C,如果C服務出現(xiàn)抖動宫仗,而B沒有處理好這個抖動够挂,造成B服務也出現(xiàn)了抖動,A調(diào)用B的時候藕夫,也會出現(xiàn)服務抖動的情況孽糖。
這個暫時的不可用狀態(tài)就想波浪一樣從底層傳遞到了上層。
所以毅贮,從整個體系的角度來看办悟,每個服務一定要盡量控制住自己下游服務的抖動,不要讓整個體系跟著某個服務抖動嫩码。
3.7 級聯(lián)失敗(cascading failure)
系統(tǒng)中有某個服務出現(xiàn)故障誉尖,不可用,傳遞性地導致整個系統(tǒng)服務不可用的問題铸题。
跟上面漣漪(自造詞)的區(qū)別也就是嚴重性的問題铡恕。
漣漪描述服務偶發(fā)的不穩(wěn)定層層傳遞,而級聯(lián)失敗基本是導致系統(tǒng)不可用丢间。 一般探熔,前者可能會因為短時間內(nèi)恢復而未引起重視,而后者一般會被高度重視烘挫。
3.8 關(guān)鍵路徑
關(guān)鍵路徑就是诀艰,你的服務想正常工作,必須要完整依賴的下游服務鏈饮六,比如數(shù)據(jù)庫一般就是關(guān)鍵路徑里面的一個節(jié)點其垄。
盡量減少關(guān)鍵路徑依賴的數(shù)量,是提高服務穩(wěn)定性的一個措施卤橄。
數(shù)據(jù)庫一般在服務體系的最底層绿满,如果你的服務可以會自己完整緩存使用的數(shù)據(jù),解除數(shù)據(jù)庫依賴窟扑,那么數(shù)據(jù)庫掛掉喇颁,你的服務就暫時是安全的。
?3.9 最長路徑
想要優(yōu)化你的服務的響應時間嚎货,需要看服務調(diào)用邏輯里面的最長路徑橘霎,只有縮短最長時間路徑的用時,才能提高你的服務的性能殖属。
轉(zhuǎn)載:https://www.cnblogs.com/raoshaoquan/articles/6636067.html