主頁 > 後端開發 > 混沌演練狀態下,如何降低應用的 MTTR(平均恢復時間)

混沌演練狀態下,如何降低應用的 MTTR(平均恢復時間)

2023-06-14 08:15:05 後端開發

在企業業務領域,錦禮是針對福利、營銷、激勵等員工采購場景的一站式解決方案,包含面向員工、會員等彈性激勵SAAS平臺,由于其直接面向公司全體員工,其服務的高可用尤其重要,本文將介紹錦禮商城大促前夕,通過混沌工程實戰演習,降低應用的MTTR,

MTTR(平均恢復時間)是從產品或系統故障中恢復所需的平均時間, 這包括整個中斷時間——從系統或產品出現故障到其恢復完全運行為止,

如何在混沌演練的場景中降低應用的MTTR,必須需要根據監控定位,然后人工進行反饋進行處理嗎?是否可以自動化,是否有方案可以降低混沌演練程序中的影響?以此達到快速止血,進一步提高系統的穩定性,

本篇文章將根據一些思考和實踐來解答以上問題,

故障無處不在,而且無法避免,

我們將從宿主機重啟問題以及底層服務混沌演練的排查與舉措說起,

背景

【客戶端視角】:出現大量介面(包括提單)超時報錯、可用率跳點,部分客戶命中,產生客訴,

通過定位發現大促備戰前期宿主機重啟及底層服務混沌演練原因,較長時間影響我側系統可用率及性能,尤其是核心介面的部署應用,會大范圍的影響到多個介面的可用率,進一步影響采購端客戶的體驗問題,

特別在TOB領域,本身就存在大客戶的口碑效應,如果恰好頭部客戶碰到該問題,那么極易被放大和激化,

image-20230531224953524.png

臨時舉措

一方面協同運維組確認宿主機重啟未及時通知的情況,另一方面與底層服務提供者同步演練影響,建議其遵守演練原則最小化爆炸半徑,控制影響范圍,保證演練是可控的,

除了以上協同外部的情況外,我們內部也產生了思考,首先情況故障本身就是不可控的,無論宿主機還是混沌演練,真實場景也是有概率發生的(并且已發生),那么我們只能通過監控定位,然后手動摘除機器或者通知服務提供者處理嗎?是否可以自動化,是否有方案可以降低影響?以此達到快速止血,進一步提高系統的穩定性,

長期方案——JSF中間件能力實踐

既然無法避免故障,那么就擁抱故障,通過一些技術手段來構建獲取應用故障的能力,從而保證應用的高可用,

由于內部的呼叫90+%為(JSF)RPC呼叫,所以我們還是把目光放到了JSF中間件的容錯能力上,以下主要介紹通過JSF中間件的超時與重試、自適應負載均衡、服務熔斷來進行故障轉移的理論與實踐,

實踐是檢驗真理的唯一標準,

關于超時和重試

實際開發程序中,相信大家也見過太多由于超時未設定、設定有誤導致的故障,當超時未設定或者設定不合理,會導致請求回應變慢,慢請求的不斷累計疊加,就會引起連鎖反應,甚至產生應用雪崩,

不僅我們自身的服務,還有外部的依賴服務,不僅HTTP服務,還是中間件服務,都應該設定合理的超時重試策略,并且重視起來,

首先讀寫服務的超時重試策略也是大不相同的,讀服務天生適合重試(如設定合理超時時間后重試兩次),但是寫服務大多是不能重試的,不過如果均是冪等設計,也是可以的,

另外設定呼叫方的超時時間之前,需要先了解清楚依賴服務的TP99回應時間是多少(如果依賴服務性能波動大,也可以看TP95),呼叫方的超時時間可以在此基礎上加50%Buff,當然服務的回應時間并不是恒定的,在某些長尾條件下可能需要更多的計算時間,所以為了有足夠的時間等待這種長尾請求回應,我們需要把超時設定足夠合理,

最后重試次數不宜太多(高并發時可能引發一系列問題(一般2次,最多3次),雖然重試次數越大,服務可用性越高,但是高并發情況下會導致多倍的請求流量,類似模擬DDOS攻擊,嚴重情況下甚至于加速故障的連鎖發生,因此超時重試最好是和熔斷、快速失敗等機制配合使用,效果更佳,這個后面會提到,

除了引入手段,重要的是驗證手段的有效性,

模擬場景(后續另兩個手段也是用該場景)

方案:采用故障注入(50%機器網路延遲3000-5000ms)的方式模擬類似場景,并驗證,

機器部署如下

image-20230601101805966.png

壓測介面(QPS-300)及故障介面監控Key值

1、壓測介面:jdos_b2b2cplatform.B2b2cProductProviderImpl.queryProductBpMap

2、服務消費:jdos_b2b2cplatform.ActivityConfigServiceRPCImpl.queryActivityConfig

3、服務提供:jdos_b2b2cshop.com.jd.ka.b2b2c.shop.service.impl.sdk.ActivityConfigServiceImpl.queryActivityConfig

【注意】

網路場景不支持如下情形:

1、應用容器所在機房:lf04, lf05, lf07, ht01, ht02, ht05, ht07, htmysql, lfmysql02, yn02, hk02, hk03

2、物理機的內核版本:2.6x, 3.8x, 3.10x

正常情況(未注入故障)

image.png

image.png

注入故障——超時設定不合理情況下(超時2000ms,重試2)

image.png

image.png

注入故障——超時設定合理情況下(超時10ms,重試2)

該介面TP99在6ms,設定超時10ms,重試2,即:jsf:methodname="queryActivityConfig"timeout="10"retries="2"/

image.png

image.png

超時重試小結

通過合理的超時重試,整體請求平穩,重試后的故障轉移,大幅提升介面可用率,

超時重試補充

在介面維度拆分不合理的情況下,我們可以更細粒度的使用方法維度的超時重試配置,不過這里有一個注意項JSF當前注解方式不支持方法維度的超時重試設定,僅支持介面維度,如已使用注解類,可進行遷移XML方式進行配置使用,

關于自適應負載均衡

對于shortestresponse自適應負載均衡設計目的是解決在 provider 節點能力不均的場景下,讓處理能力較弱的provider少接受些流量,不會因個別性能較差的 provider 影響到 consumer 整體呼叫的請求耗時和可用率,

能者多勞拙者閑,智者多憂愚者無所慮,

但是該策略下也是存在一些問題的:

  1. 流量的過度集中高性能實體,服務提供者的單機限流或成為瓶頸,
  2. response的時間長短有時也并不能代表機器的吞吐能力,
  3. 大多數的場景下,不同provider的response時長在沒有非常明顯的區別時,shortestresponse同random(隨機),

現有的shortestresponse的實作機制,類似P2C(Power of Two Choice)演算法,不過計算方式不是采用當前正在處理的連接數,而是默認隨機選擇兩個服務提供者參與最快回應比較計算,即:統計請求每個provider的請求耗時、訪問量、例外量、請求并發數,比較平均回應時間 * 當前請求數,用于最快回應負載計算,選取優勝者來避免羊群效應,以此自適應的衡量 provider 端機器的吞吐能力,然后將流量盡可能分配到吞吐能力高的機器上,提高系統整體服務的性能,

    <jsf:consumer id="activityConfigService"
                  interface="com.jd.ka.b2b2c.shop.sdk.service.ActivityConfigService"
                  alias="${jsf.activityConfigService.alias}" timeout = "3000" filter="jsfLogFilter,jsfSwitchFilter"
                  loadbalance="shortestresponse">
        <jsf:method name="queryActivityConfig" timeout="10" retries="2"/>
    </jsf:consumer>

注入故障(設定自適應負載均衡)

image.png

image.png

image.png

自適應負載均衡小結

通過引入自適應負載均衡,從介面最初呼叫就開始了”能者多勞“模式,選舉出的機器承載著更高的流量,故障注入后,介面可用率短時間視窗消失,變成可用率跳點,進一步保障了服務的高可用及性能,

關于服務熔斷

當電路發生短路或嚴重過載時,熔斷器中的熔斷體將自動熔斷,對電路進行保護,避免對設備產生重大影響,甚至火災,

服務熔斷是面向不穩定服務場景的一種鏈路保護機制,

其背后的基本思想非常簡單,將受保護的函式呼叫包裝在熔斷物件中,該物件會監視故障,當呼叫鏈路的某個服務不可用或者回應時間太長導致故障達到設定閾值時,會進行服務熔斷,熔斷視窗內不再有該節點服務的呼叫,以此來最大限度避免下游服務不穩定對上游服務帶來的影響,

<!-- 服務熔斷策略配置 -->
<jsf:reduceCircuitBreakerStrategy id="demoReduceCircuitBreakerStrategy"
    enable="true"   <!-- 熔斷策略是否開啟 -->
    rollingStatsTime="1000" <!-- 熔斷器指標采樣滾動視窗時長,單位 ms,默認 5000ms -->
    triggerOpenMinRequestCount="10" <!-- 單位時間內觸發熔斷的最小訪問量,默認 20 -->
    triggerOpenErrorCount="0"   <!-- 單位時間內的請求例外數達到閥值,默認 0,小于等于0 代表不通過例外數判斷是否開啟熔斷  -->
    triggerOpenErrorPercentage="50" <!-- 單位時間內的請求例外比例達到閥值,默認 50,即 默認 50% 錯誤率  -->
    <!-- triggerOpenSlowRT="0" 判定請求為慢呼叫的請求耗時,單位 ms,請求耗時超過 triggerOpenSlowRT 則認為是慢呼叫 (默認為 0,即默認不判定)-->
    <!-- triggerOpenSlowRequestPercentage="0"  采樣滾動周期內觸發熔斷的慢呼叫率(默認為 0,即默認不觸發慢呼叫熔斷 -->
    openedDuration="10000"   <!-- 熔斷開啟狀態持續時間,單位 ms,默認  5000ms -->
    halfOpenPassRequestPercentage="30"  <!-- 半閉合狀態,單位時間內放行流量百分比,默認 40-->
    halfOpenedDuration="3000"   <!-- 半閉合狀態持續時間設定,需要大于等于 rollingStatsTime ,默認為 rollingStatsTime  -->
    <!-- failBackType="FAIL_BACK_EXCEPTION" failBack策略, 取值:FAIL_BACK_EXCEPTION拋出例外、FAIL_BACK_NULL回傳null、FAIL_BACK_CUSTOM配置自定義策略,配合 failBackRef 屬性 -->
    <!-- failBackRef="ref" 如果 failBackStrategy 配置為 FAIL_BACK_CUSTOM 則必填,用戶自定義的failback策略com.jd.jsf.gd.circuitbreaker.failback.FailBack<Invocation> 介面實作類 -->
/>

<jsf:consumerid="activityConfigService"interface="com.jd.ka.b2b2c.shop.sdk.service.ActivityConfigService"
                alias="${consumer.alias.com.jd.ka.b2b2c.shop.sdk.service.ActivityConfigService}" timeout="2000"check="false"
                serialization="hessian"loadbalance="shortestresponse"
                connCircuitBreakerStrategy="demoCircuitBreakerStrategy">
      <jsf:methodname="queryActivityConfig"timeout="10"retries="2"/>
</jsf:consumer>

這里來了一個小插曲,由于JSF本身的心跳機制,檢測故障后,自動(30s檢測一次,三次均例外則摘除)摘除了對應的機器,我們自身設定的熔斷機制并不明顯,因此重新設定故障(網路延遲800-1500ms)進行重新演練,

注入故障(服務熔斷)

image.png

服務熔斷小結

從可用率上看,確實在視窗內會關閉對例外機器節點的訪問,不過由于并沒有實作failback策略以及熔斷開啟視窗時間較短,可用率還是會在視窗打開后,直接回傳了呼叫失敗資訊,因此影響了可用率,所以相比于熔斷后失敗,最好的方式是配合服務降級能力,通過呼叫預先設定好的服務降級邏輯,以降級邏輯的結果作為最終呼叫結果,以更優雅的回傳給服務呼叫方,

服務熔斷補充

  1. 集團已搭建了統一的熔斷組件,并且在泰山上建立了對應的平臺能力,如果團隊需要引入熔斷能力,可以直接接入使用,避免重復建設,詳情見:http://taishan.jd.com/flowControl/limitIndex
> 一種機制可能會擊敗另一種機制,

其實為了增強系統的彈性和魯棒性,以應對各種故障和不可預測的情況,在分布式系統中,通常會設計成能夠部分故障(partially fail),即使不能滿足全量客戶,但是仍然可以向某些客戶提供服務,但是熔斷旨在將部分故障轉化為完全故障,以此防止故障進一步擴散,因此服務熔斷和分布式系統的設計原則中存在一種相互制約的關系,所以,在使用前,要進行仔細的分析和思考,以及后續的調優,

結論

能力只是手段,穩定性才是目的,

無論采用什么手段,進行穩定性建設,我們需要時刻思考的是如何在業務需求和穩定性建設中尋找平衡,以建設支持業務長期增長的高可用架構,


本次就寫到這,如有問題,歡迎交流,希望文章中的一些經驗,給大家帶來一些識訓,或者說,大家不妨思考一下你們會采用何種技術方案和手段來解決類似問題,歡迎留言交流,也希望能和更多志同道合的伙伴溝通交流,

參考檔案

外部檔案

The power of two random choices :  https://brooker.co.za/blog/2012/01/17/two-random.html

負載均衡:https://cn.dubbo.apache.org/zh-cn/overview/core-features/load-balance/#shortestresponse

作者:京東零售 李孟冬

內容來源:京東云開發者社區

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/555071.html

標籤:其他

上一篇:爬取豆瓣Top250圖書資料

下一篇:返回列表

標籤雲
其他(160904) Python(38226) JavaScript(25493) Java(18235) C(15237) 區塊鏈(8270) C#(7972) AI(7469) 爪哇(7425) MySQL(7248) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5875) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4591) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2435) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1984) 功能(1967) HtmlCss(1964) Web開發(1951) C++(1939) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • 混沌演練狀態下,如何降低應用的 MTTR(平均恢復時間)

    如何在混沌演練的場景中降低應用的MTTR,必須需要根據監控定位,然后人工進行反饋進行處理嗎?是否可以自動化,是否有方案可以降低混沌演練程序中的影響?以此達到快速止血,進一步提高系統的穩定性。本篇文章將根據一些思考和實踐來解答以上問題。 ......

    uj5u.com 2023-06-14 08:15:05 more
  • 爬取豆瓣Top250圖書資料

    #爬取豆瓣Top250圖書資料 專案的實作步驟 1.專案結構 2.獲取網頁資料 3.提取網頁中的關鍵資訊 4.保存資料 **1.專案結構** ![image](https://img2023.cnblogs.com/blog/3047082/202306/3047082-20230613170853 ......

    uj5u.com 2023-06-14 08:14:56 more
  • [ARM匯編]計算機原理與數制基礎—1.1.2 二進制與十進制數制轉換

    在計算機中,我們通常使用二進制數制來表示資料,因為計算機的基本電平只有兩種狀態:高電平(通常表示為 1)和低電平(通常表示為 0)。而在我們的日常生活中,我們習慣使用十進制數制。為了方便理解,我們需要掌握二進制與十進制之間的轉換方法。 #### 二進制轉十進制 將二進制數轉換為十進制數時,我們需要將 ......

    uj5u.com 2023-06-14 08:14:48 more
  • Go 語言之 sqlx 庫使用

    # Go 語言之 sqlx 庫使用 ## 一、sqlx 庫安裝與連接 ### sqlx 介紹 sqlx is a library which provides a set of extensions on go's standard `database/sql` library. The sqlx ......

    uj5u.com 2023-06-14 08:14:39 more
  • 【python基礎】復雜資料型別-字典(嵌套)

    有時候,需要將一系列字典存盤在串列中,或將串列作為值存盤在字典中,這稱為**嵌套**。我們可以在串列中嵌套字典、在字典中嵌套串列、在字典中嵌套字典。 # 1.串列嵌套字典 我們可以把一個人的資訊放在字典中,但是多個人的資訊我們無法放在同一個字典中,所以就需要字典串列。 其語法格式: [字典1,字典2 ......

    uj5u.com 2023-06-14 08:09:16 more
  • 搭建springbootweb環境

    #搭建springboot環境(idea環境) 實作步驟: 1.基礎環境配置 2.maven配置 3.撰寫第一個程式helloworld(可能有兩個小問題) 4.運行(jar包運行,命令列運行) 一.基礎環境配置 進入idea,點擊file->new->project,在彈出的頁面上,選擇sprin ......

    uj5u.com 2023-06-14 07:58:44 more
  • 每天一道面試題:Spring的Bean生命周期

    Spring的Bean生命周期包括以下步驟: 1、實體化(Instantiation):當Spring容器接收到創建Bean的請求時,它會先實體化Bean物件。這個程序可以通過建構式、工廠方法或者反序列化等方式完成; 2、屬性賦值(Populate Properties):在實體化Bean物件后, ......

    uj5u.com 2023-06-14 07:53:30 more
  • Axure RP教程_編程入門自學教程_菜鳥教程-免費教程分享

    ## 教程簡介 Axure RP是一款專業的快速原型設計工具。Axure(發音:Ack-sure),代表美國Axure公司;RP則是Rapid Prototyping(快速原型)的縮寫。 Axure RP是美國Axure Software Solution公司旗艦產品,是一個專業的快速原型設計工具, ......

    uj5u.com 2023-06-14 07:53:25 more
  • celery筆記三之task和task的呼叫

    > 本文首發于公眾號:Hunter后端 > 原文鏈接:[celery筆記三之task和task的呼叫](https://mp.weixin.qq.com/s/AIobDZVDWV3r_XauvmkVKA) 這一篇筆記介紹 task 和 task 的呼叫。 以下是本篇筆記目錄: 1. 基礎的 task ......

    uj5u.com 2023-06-14 07:52:40 more
  • 爬取豆瓣Top250圖書資料

    #爬取豆瓣Top250圖書資料 專案的實作步驟 1.專案結構 2.獲取網頁資料 3.提取網頁中的關鍵資訊 4.保存資料 **1.專案結構** ![image](https://img2023.cnblogs.com/blog/3047082/202306/3047082-20230613170853 ......

    uj5u.com 2023-06-14 07:52:29 more