服務(wù)架構(gòu)請(qǐng)求調(diào)用失敗的解決方案

      網(wǎng)友投稿 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)用理論上返回要更快。

      微服務(wù)架構(gòu)下請(qǐng)求調(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)容。

      上一篇:2020 年最全 Python 面試題匯總 (四)
      下一篇:Android之Launcher分析和修改1——Launcher默認(rèn)界面配置(default_workspace)
      相關(guān)文章
      亚洲伊人色欲综合网| 一区二区三区亚洲视频| 亚洲香蕉成人AV网站在线观看| 亚洲国产精品无码久久久秋霞1 | 免费在线观看亚洲| 亚洲高清乱码午夜电影网| 亚洲高清中文字幕免费| 亚洲专区一路线二| 日韩亚洲国产高清免费视频| 中文文字幕文字幕亚洲色| 亚洲Av无码一区二区二三区| 亚洲一本之道高清乱码| ww亚洲ww在线观看国产| 久久久久亚洲国产| 亚洲日本天堂在线| 日韩亚洲人成在线综合| 亚洲A丁香五香天堂网| 国产福利电影一区二区三区,亚洲国模精品一区 | 男人的天堂亚洲一区二区三区| 亚洲av无码片vr一区二区三区| 亚洲av日韩专区在线观看| 理论亚洲区美一区二区三区| 国产精品亚洲一区二区三区| 亚洲日本中文字幕一区二区三区| 中文字幕亚洲综合久久男男| 国产亚洲无线码一区二区| 亚洲国产高清在线| 亚洲成a人片在线观看中文app| 亚洲av成人综合网| 亚洲大尺度无码无码专线一区| 国产亚洲精品91| 亚洲精品字幕在线观看| 亚洲av丰满熟妇在线播放| 亚洲精品第一国产综合精品| 亚洲一区二区三区播放在线| 亚洲国产午夜精品理论片在线播放| 日产国产精品亚洲系列| 亚洲香蕉网久久综合影视| 久久亚洲中文字幕精品有坂深雪 | 亚洲AV无码国产精品麻豆天美 | 亚洲一区二区三区AV无码|