<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          微服務架構(gòu)下請求調(diào)用失敗了怎么辦?

          共 2967字,需瀏覽 6分鐘

           ·

          2021-01-07 19:55


          ? 點擊上方“JavaEdge”,關(guān)注公眾號

          設(shè)為“星標”,好文章不錯過!


          微服務帶來的不安因素


          相比單體架構(gòu),微服務架構(gòu)下的服務調(diào)用從同一機器內(nèi)的本地調(diào)用變成不同機器間遠程調(diào)用,由此也帶來如下不確定因素

          • 調(diào)用的執(zhí)行是服務提供者,即使服務消費者本身正常,服務提供者也可能因CPU、網(wǎng)絡I/O、磁盤、內(nèi)存、網(wǎng)卡等各種原因調(diào)用失敗,還可能因本身程序執(zhí)行問題比如GC暫停導致失敗

          • 調(diào)用發(fā)生在兩臺機器間,所以要經(jīng)過網(wǎng)絡傳輸,而網(wǎng)絡不可控,丟包、延遲或抖動都可能導致調(diào)用失敗。


          所以針對服務調(diào)用失敗需特殊處理。

          超時


          微服務下的一次用戶調(diào)用可能會被拆成多系統(tǒng)間服務調(diào)用,任一次服務調(diào)用若發(fā)生問題都可能導致用戶調(diào)用最終失敗。

          一個系統(tǒng)的問題會影響所有調(diào)用這個系統(tǒng)所提供服務的服務消費者,導致服務雪崩。

          所以針對服務調(diào)用都要設(shè)置超時時間,避免所依賴服務一直未返回結(jié)果,將服務消費者阻死。



          超時時間的設(shè)定


          • 太短,可能有些服務調(diào)用還未及時執(zhí)行完成就被丟棄

          • 太長,可能導致服務消費者被拖死

          按服務提供者線上真實的服務水平,取99.9%或99.99%的調(diào)用都在多少ms內(nèi)返回為準。

          重試


          雖設(shè)超時時間可及時止損,但服務調(diào)用結(jié)果畢竟失敗。大部分情況調(diào)用失敗都因網(wǎng)絡問題或個別服務提供者節(jié)點有問題,若能換個節(jié)點再次訪問說不定就成功。

          假如一次服務調(diào)用失敗概率1%,那連續(xù)兩次服務調(diào)用失敗概率0.01%,失敗率降低到原來1%。所以經(jīng)常還要設(shè)置一個服務調(diào)用超時后的重試次數(shù)。

          假如某服務調(diào)用超時時間設(shè)為100ms,重試次數(shù)設(shè)為1,當服務調(diào)用超過100ms后,服務消費者就會立即發(fā)起第二次服務調(diào)用,而不會再等待第一次調(diào)用返回結(jié)果。

          雙發(fā)


          假如一次調(diào)用不成功概率1%,那連續(xù)兩次調(diào)用都不成功的概率就是0.01%,一個簡單的提高服務調(diào)用成功率的辦法就是每次服務消費者要發(fā)起服務調(diào)用的時候,都同時發(fā)起兩次服務調(diào)用,可

          • 提高調(diào)用的成功率

          • 兩次服務調(diào)用,哪個先返回就采用哪次返回結(jié)果,平均響應時間也要比一次調(diào)用更快

          這就是雙發(fā)。

          但這樣一次調(diào)用會給后端服務兩倍壓力,要消耗的資源也加倍,所以“魯莽”雙發(fā)不可取。

          更為聰明的雙發(fā),即



          “備份請求”(Backup Requests)


          服務消費者發(fā)起一次服務調(diào)用后,在給定的時間內(nèi)如果沒有返回請求結(jié)果,那么服務消費者就立刻發(fā)起另一次服務調(diào)用。
          注意該設(shè)定時間通常要比超時時間短得多,比如超時時間取P999,那么備份請求時間取的可能是P99或P90,因為若在P99或者P90時間內(nèi)調(diào)用還沒有返回結(jié)果,那么大概率可以認為這次請求屬于慢請求,再次發(fā)起調(diào)用理論上返回要更快。

          在實際線上服務運行時,P999由于長尾請求時間較長的緣故,可能要遠遠大于P99和P90。
          比如一個服務的P999是1s,而P99只有200ms、P90只有50ms,這樣的話,如果備份請求時間取的是P90,那么第二次請求等待的時間只有50ms。

          備份請求要設(shè)置一個最大重試比例,以避免在服務端出現(xiàn)問題時,大部分請求響應時間都會超過P90,導致請求量幾乎翻倍,給服務提供者造成更大的壓力。
          可設(shè)置成15%

          • 盡量體現(xiàn)備份請求的優(yōu)勢

          • 不會給服務提供者額外增加太大的壓力

          熔斷


          前面手段在服務提供者偶發(fā)異常時很有效,但若服務提供者故障,短時間內(nèi)無法恢復,都不能提高服務調(diào)用成功率,還會因重試給服務提供者帶來更大的壓力而加劇故障。

          就需服務消費者能夠探測到服務提供者發(fā)生故障,短時間內(nèi)停止請求,給服務提供者故障恢復時間,待服務提供者恢復后,再繼續(xù)請求。



          原理


          把客戶端的每次服務調(diào)用用斷路器封裝,通過斷路器監(jiān)控每次服務調(diào)用。

          若某段時間內(nèi),服務調(diào)用失敗次數(shù)達到一定閾值,斷路器就會被觸發(fā),后續(xù)服務調(diào)用直接返回,不會再向服務提供者發(fā)起請求。

          熔斷后,一旦服務提供者恢復

          服務調(diào)用如何恢復


          Hystrix的斷路器包含三種狀態(tài):關(guān)閉、打開、半打開

          • Closed態(tài)

            正常情況下的斷路器處關(guān)閉狀態(tài),偶發(fā)的調(diào)用失敗也不影響

          • Open態(tài)

            當服務調(diào)用失敗次數(shù)達到閾值,斷路器就會處開啟狀態(tài),后續(xù)服務調(diào)用直接返回,不會向服務提供者發(fā)起請求

          • Half Open態(tài)

            當斷路器開啟,每隔一段時間,會進入半打開態(tài),這時會向服務提供者發(fā)起探測調(diào)用,以確定服務提供者是否恢復正常。

            調(diào)用成功,斷路器就關(guān)閉

            若失敗,斷路器繼續(xù)保持開啟態(tài),并等待下個周期重新進入半打開態(tài)。

          Hystrix會把每次服務調(diào)用都用HystrixCommand封裝,實時記錄每次服務調(diào)用狀態(tài),包括成功、失敗、超時還是被線程拒絕。


          當一段時間內(nèi)服務調(diào)用的失敗率高于閾值,Hystrix的斷路器就會進入進入打開態(tài),新的服務調(diào)用直接返回,不會向服務提供者發(fā)起調(diào)用。

          再等待設(shè)定時間間隔后,Hystrix的斷路器又會進入半打,新的服務調(diào)用又可重新發(fā)給服務提供者。若一段時間內(nèi)服務調(diào)用失敗率依然高于閾值,斷路器會重新進入打開態(tài),否則,重置為關(guān)閉態(tài)。


          決定斷路器是否打開失敗率閾值通過如下參數(shù):

          HystrixCommandProperties.circuitBreakerErrorThresholdPercentage()

          斷路器何時進入半打開態(tài)時間間隔通過如下參數(shù):

          HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds()

          斷路器關(guān)鍵在于


          統(tǒng)計一段時間內(nèi)服務調(diào)用的失敗率


          滑動窗口算法

          默認情況下,滑動窗口包含10個桶,每個桶時間寬度1s,每桶記錄這1s所有服務調(diào)用成功、失敗、超時的及被線程拒絕的次數(shù)。當新1s到來動窗口就往前滑動,丟棄最舊桶,把最新桶包進來。

          任意時刻,Hystrix都會取滑動窗口內(nèi)所有服務調(diào)用的失敗率作為斷路器開關(guān)狀態(tài)的判斷依據(jù),這10個桶內(nèi)記錄的所有失敗的、超時的、被線程拒絕的調(diào)用次數(shù)之和除以總的調(diào)用次數(shù)就是滑動窗口內(nèi)所有服務的調(diào)用的失敗率。

          總結(jié)


          對非冪等,即同一服務調(diào)用重復多次返回結(jié)果不同的,不可重試,比如大部分上行請求都是非冪等。

          雙發(fā)是在重試基礎(chǔ)上進行一定優(yōu)化,減少超時等待時間,對于長尾請求場景很有效。采用雙發(fā)后,服務調(diào)用的P999能大幅減少,是提高服務調(diào)用成功率的有效手段。

          熔斷能很好解決依賴服務故障引起的連鎖反應,對于線上存在大規(guī)模服務調(diào)用尤其是對非關(guān)鍵路徑的調(diào)用,即使調(diào)用失敗也對最終結(jié)果影響不大的情況下,更應引入熔斷。

          參考

          • https://martinfowler.com/bliki/CircuitBreaker.html

          • https://github.com/Netflix/Hystrix/wiki/How-To-Use

          往期推薦


          大廠如何解決數(shù)值精度/舍入/溢出問題

          硬核干貨:HTTP超時、重復請求必見坑點及解決方案

          由于不知線程池的bug,某Java程序員叕被祭天

          程序員因重復記錄日志撐爆ELK被辭退!

          擁抱Kubernetes,再見了Spring Cloud




          目前交流群已有?800+人,旨在促進技術(shù)交流,可關(guān)注公眾號添加筆者微信邀請進群


          喜歡文章,點個“在看、點贊、分享”素質(zhì)三連支持一下~

          瀏覽 32
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩黄色一级视频 | 香蕉女人毛片 | 黄色片网站在线免费观看视频 | 在线亚洲免费视频二 | 99re99爱视频 |