Tungsten Fabric SDN — SmartNIC vRouter
1751
2022-05-29
文章收錄在我的 GitHub 倉庫,歡迎Star
Java-Interview-Tutorial
0 前言
相比單體架構(gòu),微服務(wù)架構(gòu)下,服務(wù)調(diào)用從同一臺(tái)機(jī)器內(nèi)部的本地調(diào)用變成了不同機(jī)器間的遠(yuǎn)程方法調(diào)用,這就引入不確定因素:
調(diào)用的執(zhí)行是在服務(wù)提供者一端,即使服務(wù)消費(fèi)者本身正常,服務(wù)提供者也可能由于諸如CPU、網(wǎng)絡(luò)I/O、磁盤、內(nèi)存、網(wǎng)卡等硬件原因?qū)е抡{(diào)用失敗,還可能因本身程序執(zhí)行問題如GC暫停導(dǎo)致調(diào)用失敗
調(diào)用發(fā)生在兩臺(tái)機(jī)器間,所以要經(jīng)過網(wǎng)絡(luò)傳輸,而網(wǎng)絡(luò)不可控:丟包、延遲及抖動(dòng)都可能造成調(diào)用失敗。
所以必須要針對(duì)服務(wù)調(diào)用失敗進(jìn)行特殊處理。
1 超時(shí)
微服務(wù)化后,一次用戶調(diào)用可能會(huì)被拆分成多系統(tǒng)間的服務(wù)調(diào)用,任何一次服務(wù)調(diào)用若發(fā)生問題都可能導(dǎo)致用戶請(qǐng)求最終是失敗的。一個(gè)系統(tǒng)異常會(huì)影響所有依賴該系統(tǒng)所提供服務(wù)的服務(wù)消費(fèi)者,可能導(dǎo)致服務(wù)雪崩。
所以針對(duì)服務(wù)調(diào)用,都要設(shè)置超時(shí)時(shí)間,避免依賴服務(wù)遲遲沒有返回調(diào)用結(jié)果,把服務(wù)消費(fèi)者拖死。
但超時(shí)時(shí)間的設(shè)定也需考量:
太短,可能有些服務(wù)調(diào)用還沒有來得及執(zhí)行完,就被丟棄
太長(zhǎng),可能導(dǎo)致服務(wù)消費(fèi)者被拖垮
因此,需根據(jù)正常情況下,服務(wù)提供者的服務(wù)水平來決定。按服務(wù)提供者線上真實(shí)服務(wù)水平,取P999或P9999值,即以99.9%或者99.99%的調(diào)用都在多少ms內(nèi)返回為準(zhǔn)。
2 重試
雖然設(shè)置超時(shí)時(shí)間可及時(shí)止損,但是服務(wù)調(diào)用結(jié)果畢竟還是失敗,而大部分情況下,調(diào)用失敗只是因?yàn)榕及l(fā)的網(wǎng)絡(luò)問題或個(gè)別服務(wù)提供者節(jié)點(diǎn)有問題,若能換個(gè)節(jié)點(diǎn)再訪問說不定就能成功。
假如一次服務(wù)調(diào)用失敗概率為1%,則連續(xù)兩次服務(wù)調(diào)用失敗的概率0.01%,失敗率大大降低。
所以,實(shí)際服務(wù)調(diào)用時(shí),一般還設(shè)置一個(gè)服務(wù)調(diào)用超時(shí)后的重試次數(shù)。
若某服務(wù)調(diào)用的超時(shí)時(shí)間設(shè)置為100ms,重試次數(shù)設(shè)置為1,則當(dāng)服務(wù)調(diào)用超過100ms后,服務(wù)消費(fèi)者就會(huì)立即發(fā)起第二次服務(wù)調(diào)用,不會(huì)再等待第一次調(diào)用返回的結(jié)果。
3 雙發(fā)
若一次調(diào)用不成功的概率1%,則連續(xù)兩次調(diào)用都失敗概率0.01%,可推得,一個(gè)簡(jiǎn)單的提高服務(wù)調(diào)用成功率的辦法-雙發(fā),每次服務(wù)消費(fèi)者要發(fā)起服務(wù)調(diào)用時(shí),都同時(shí)發(fā)起兩次服務(wù)調(diào)用:
可提高調(diào)用成功率
兩次服務(wù)調(diào)用哪個(gè)先返回,就采用哪次的返回結(jié)果,平均響應(yīng)時(shí)間也比一次調(diào)用更快
但這樣,一次調(diào)用會(huì)給后端服務(wù)兩倍壓力,所消耗資源也加倍,所以一般“魯莽”雙發(fā)不可取。
更聰明的雙發(fā),“備份請(qǐng)求”(Backup Requests)。服務(wù)消費(fèi)者發(fā)起一次服務(wù)調(diào)用后,在給定時(shí)間內(nèi),若沒返回請(qǐng)求結(jié)果,則Consumer就立刻發(fā)起另一次服務(wù)調(diào)用。
注意該設(shè)定時(shí)間通常比超時(shí)時(shí)間短得多,如超時(shí)時(shí)間取P999,則備份請(qǐng)求時(shí)間可能取P99或P90,因?yàn)槿粼赑99或P90時(shí)間內(nèi)調(diào)用還沒返回結(jié)果,大概率可認(rèn)為這次請(qǐng)求屬于慢請(qǐng)求,再次發(fā)起調(diào)用理論上返回要更快。
實(shí)際線上服務(wù)運(yùn)行時(shí),P999由于長(zhǎng)尾效應(yīng),可能遠(yuǎn)大于P99和P90。
如一個(gè)服務(wù)的P999=1s,而P99=200ms、P90=50ms,這樣,若備份請(qǐng)求時(shí)間取P90,則第二次請(qǐng)求等待的時(shí)間只有50ms。
不過注意,備份請(qǐng)求要設(shè)置一個(gè)最大重試比例,避免服務(wù)端異常時(shí),大部分請(qǐng)求的響應(yīng)時(shí)間都超過P90,導(dǎo)致請(qǐng)求量翻倍,給服務(wù)提供者造成更大壓力。
經(jīng)驗(yàn)之談,最大重試比例可設(shè)置成15%:
能盡量體現(xiàn)備份請(qǐng)求的優(yōu)勢(shì)
不會(huì)給服務(wù)提供者額外增加太大的壓力
4 熔斷
前面的手段在服務(wù)Provider偶發(fā)異常時(shí)很有效,但若Provider故障,短時(shí)間內(nèi)都無法恢復(fù),無論是超時(shí)重試還是雙發(fā):
無法提高服務(wù)調(diào)用成功率
由于重試,還給Provider帶來更大壓力,加劇故障
這時(shí),就需要服務(wù)Consumer能探測(cè)到Provider故障了,并短時(shí)間內(nèi)停止請(qǐng)求,給Provider故障恢復(fù)的時(shí)間,待Provider恢復(fù)后,再繼續(xù)請(qǐng)求。就如一條電路,電流負(fù)載過高,保險(xiǎn)絲就會(huì)熔斷。
4.1 熔斷原理
把客戶端的每次服務(wù)調(diào)用,通過斷路器封裝,使用斷路器來監(jiān)控每一次服務(wù)調(diào)用。若某段時(shí)間內(nèi),服務(wù)調(diào)用失敗次數(shù)達(dá)到一定閾值,則斷路器就會(huì)被觸發(fā),后續(xù)的服務(wù)調(diào)用就直接返回,也就不會(huì)再向Provider發(fā)起請(qǐng)求。
熔斷之后,一旦Provider恢復(fù),服務(wù)調(diào)用如何恢復(fù)呢?這牽扯到熔斷器的狀態(tài)轉(zhuǎn)換:
Closed狀態(tài):正常情況下,斷路器處關(guān)閉態(tài),偶發(fā)的調(diào)用失敗也不影響該狀態(tài)的變更
Open狀態(tài):當(dāng)服務(wù)調(diào)用失敗次數(shù)達(dá)到一定閾值,斷路器處開啟狀態(tài),后續(xù)服務(wù)調(diào)用直接返回,不會(huì)再向Provider發(fā)起請(qǐng)求
Half Open狀態(tài):斷路器開啟后,每隔一段時(shí)間,會(huì)進(jìn)入半打開狀態(tài),會(huì)向Provider發(fā)起探測(cè)性的調(diào)用,以確定Provider是否恢復(fù)。
若調(diào)用成功,斷路器就關(guān)閉
若未成功,斷路器繼續(xù)保持開啟狀態(tài),并等待下個(gè)周期重新進(jìn)入半打開狀態(tài)
斷路器的最經(jīng)典實(shí)現(xiàn)就是Hystrix。Hystrix就包含三種狀態(tài):關(guān)閉、打開、半打開。Hystrix會(huì)把每次服務(wù)調(diào)用都用HystrixCommand封裝,實(shí)時(shí)記錄每次服務(wù)調(diào)用的狀態(tài),包括成功、失敗、超時(shí)還是被線程拒絕。
當(dāng)一段時(shí)間內(nèi)服務(wù)調(diào)用失敗率>閾值,斷路器就會(huì)進(jìn)入打開狀態(tài),新的服務(wù)調(diào)用會(huì)直接返回,不會(huì)向 Provider發(fā)起調(diào)用。再等設(shè)定的時(shí)間間隔后,斷路器又會(huì)進(jìn)入半打開,新的服務(wù)調(diào)用又可重新發(fā)給Provider;若一段時(shí)間內(nèi)服務(wù)調(diào)用的失敗率依然>閾值,斷路器會(huì)重新打開,否則,斷路器被關(guān)閉。
決定斷路器是否打開的失敗率閾值通過如下參數(shù)設(shè)定:
HystrixCommandProperties.circuitBreakerErrorThresholdPercentage();
決定斷路器何時(shí)進(jìn)入半打開的時(shí)間間隔通過如下參數(shù)設(shè)定:
HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds()
滑動(dòng)窗口算法
統(tǒng)計(jì)指定時(shí)間段內(nèi)服務(wù)調(diào)用失敗率:
默認(rèn)情況下,滑動(dòng)窗口包含10個(gè)桶,每個(gè)桶時(shí)間寬度為1s,每個(gè)桶內(nèi)記錄這1s內(nèi)所有服務(wù)調(diào)用中成功的、失敗的、超時(shí)的以及被線程拒絕的次數(shù)。
當(dāng)新的1s到來時(shí),滑動(dòng)窗口就會(huì)往前滑動(dòng),丟棄掉最舊的1個(gè)桶,把最新1個(gè)桶包進(jìn)來。
任意時(shí)刻,Hystrix都會(huì)取滑動(dòng)窗口內(nèi)所有服務(wù)調(diào)用的失敗率作為斷路器開關(guān)狀態(tài)的判斷依據(jù),這10個(gè)桶內(nèi)記錄:
滑動(dòng)窗口內(nèi)所有服務(wù)的調(diào)用失敗率 =(失敗的+超時(shí)的+被線程拒絕的調(diào)用次數(shù))/總調(diào)用次數(shù)
5 總結(jié)
大部分服務(wù)調(diào)用都要設(shè)置超時(shí)時(shí)間及重試次數(shù),但對(duì)非冪等的不可以重試,如大部分上行請(qǐng)求都是非冪等。
雙發(fā)是在重試基礎(chǔ)上的優(yōu)化,減少超時(shí)等待的時(shí)間,對(duì)于長(zhǎng)尾請(qǐng)求很有效。采用雙發(fā)后,服務(wù)調(diào)用的P999能大幅減少,是提高服務(wù)調(diào)用成功率的有效手段。
熔斷能很好地解決依賴服務(wù)故障引起的連鎖反應(yīng),對(duì)于大規(guī)模服務(wù)調(diào)用的必不可少,尤其是對(duì)非關(guān)鍵路徑的調(diào)用,即使調(diào)用失敗也對(duì)最終結(jié)果影響不大的情況下,更應(yīng)該引入熔斷。
參考
https://martinfowler.com/bliki/CircuitBreaker.html
https://github.com/Netflix/Hystrix/wiki/How-To-Use
微服務(wù) 網(wǎng)絡(luò)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。