美团点评酒店后台故障演练系统
隨著海量請求、節(jié)假日峰值流量和與日俱增的系統(tǒng)復(fù)雜度出現(xiàn)的,很有可能是各種故障。在分析以往案例時我們發(fā)現(xiàn),如果預(yù)案充分,即使出現(xiàn)故障,也能及時應(yīng)對。它能最大程度降低故障的平均恢復(fù)時間(MTTR),進而讓系統(tǒng)可用程度(SLA)維持在相對較高的水平,將故障損失保持在可控范圍內(nèi)。但是,經(jīng)過對2016全年酒店后臺研發(fā)組所有面向C端系統(tǒng)的線上事故分析后發(fā)現(xiàn),在許多情況下,由于事故處理預(yù)案的缺失或者預(yù)案本身的不可靠,以及開發(fā)人員故障處理經(jīng)驗的缺失,造成大家在各種報警之中自亂了陣腳,從而貽誤了最佳戰(zhàn)機。
正如上面所講,由“上游流量”和“依賴”導(dǎo)致的故障數(shù)量,占了全年故障的45%。
一個經(jīng)典的case:
2016年3月10日,Tair集群因流量過大掛掉,導(dǎo)致酒店后臺某組一個ID生成器的功能失效,無法獲取ID,插入數(shù)據(jù)庫失敗。
值班同學(xué)找到相應(yīng)的開發(fā)同學(xué),執(zhí)行之前的預(yù)案(切換到基于數(shù)據(jù)庫的ID生成器),發(fā)現(xiàn)不能解決當(dāng)前問題(有主鍵沖突)。
值班同學(xué)經(jīng)過分析,臨時修改數(shù)據(jù)庫中的字段值,修復(fù)問題。
從上面的例子可以看出,業(yè)務(wù)方針對系統(tǒng)可能出現(xiàn)的異常情況,雖然一般設(shè)有預(yù)案,但是缺乏在大流量、有故障情況下的演練,所以往往在故障來臨時,需要用一些臨時手段來彌補預(yù)案的不足。
綜上所述,我們要有一套常態(tài)化的“故障演練”機制與工具來反復(fù)驗證,從而確保我們的服務(wù)能在正常情形下表現(xiàn)出正常的行為,在異常狀況下,也要有正確、可控的表現(xiàn)。
這個服務(wù)或是工具能執(zhí)行:
- 容量與性能評估。
- 故障演練,進而進行依賴梳理、預(yù)案驗證,保證服務(wù)柔性可用。
這樣才能夠做到在節(jié)假日與大促時心中有數(shù),在提高系統(tǒng)服務(wù)能力的同時增加開發(fā)人員應(yīng)對與處理故障的經(jīng)驗。
下面,以酒店后臺switch研發(fā)組開發(fā)的“Faultdrill”系統(tǒng)為例,向大家介紹一下我們在這方面的經(jīng)驗。
在壓力測試(以下簡稱“壓測”)和故障演練方面,業(yè)界已有很多種實踐。
壓測
壓測有單模塊壓測和全鏈路壓測兩種模式。
阿里雙11、京東618和美團外賣都有過線上全鏈路壓測的分享(美團外賣的分享參見美團點評技術(shù)沙龍第6期回顧)。
全鏈路壓測有幾點明顯的優(yōu)勢:
- 基于線上環(huán)境,測出的性能數(shù)據(jù)準(zhǔn)確;
- 相較于線下,測試環(huán)境完備,不存在單點、低配置等問題;
- 線上環(huán)境有完備的監(jiān)控報警系統(tǒng)。
但與此同時,全鏈路壓測也有較高的實踐成本:
- 需要有明顯的波谷期;
- 需要清理壓測數(shù)據(jù),或者申請資源構(gòu)建影子存儲;
- 真實流量難構(gòu)造,需要準(zhǔn)備虛擬商家和虛擬用戶;
- 需要有完備的監(jiān)控報警系統(tǒng)。
酒店業(yè)務(wù)模式和外賣/購物類的業(yè)務(wù)模式不太一樣。首先,沒有明顯的波峰波谷(夜里也是訂房高峰期,你懂的),因為沒有明顯的波峰波谷,所以清理數(shù)據(jù)/影子表也會帶來額外的影響。真實流量的構(gòu)造也是一個老大難問題,需要準(zhǔn)備N多的虛擬商家和虛擬用戶。
所以酒店最早推的是單業(yè)務(wù)模塊級別的壓力測試和故障演練,大家先自掃門前雪。
美團點評內(nèi)部的通信協(xié)議以Thrift為主,業(yè)界的相關(guān)壓力測試工具也有很多:
- JMeter作為老牌的壓力測試工具,通常作為HTTP協(xié)議的測試,也可以通過自定義插件的方式實現(xiàn)Thrift協(xié)議的測試。
- TCPCopy的方式主要是關(guān)注“真實流量”。
- loading_test是美團點評內(nèi)部的壓力測試工具。
|工具|使用方式|支持Thrift協(xié)議|流量來源|最小粒度| |-|-|-|-|-|-| |loading_test|在代碼中依賴VCR包手動上傳參數(shù)日志。需要loading依賴服務(wù)方的jar后重新發(fā)布|支持|真實copy線上流量|method級別| |JMeter|編寫Thrift插件(針對于接口)|支持|需要自己構(gòu)造|method級別| |TCPCopy|安裝TCPCopy|支持|真實流量|端口級別,所有流量全copy過來|-|
這幾種方式都不滿足我們的要求,我們的要求是:真實流量、method級別控制、操作簡單。
所以我們準(zhǔn)備自己造個輪子 :)
需求:業(yè)務(wù)方低成本接入,流量在集群級別(AppKey級別,AppKey相當(dāng)于同樣功能集群的唯一標(biāo)識,比如訂單搜索集群的AppKey為xx.xx.xx.order.search)以最低成本進行復(fù)制、分發(fā),以及最重要的在這個過程中的安全可控等等都是對測試工具、框架的潛在要求。
基于以上,我們開發(fā)了流量復(fù)制分發(fā)服務(wù)。它的核心功能是對線上真實流量進行實時復(fù)制并按配置分發(fā)到指定的機器,來實現(xiàn)像異構(gòu)數(shù)據(jù)遷移一樣進行流量定制化的實時復(fù)制與遷移。
借助流量復(fù)制分發(fā)服務(wù)進行功能和系統(tǒng)級別的測試,以達到:
- 容量規(guī)劃。在穩(wěn)定與性能保證的基礎(chǔ)上盡可能的節(jié)約資源。
- 核心鏈路梳理,強弱依賴區(qū)分,并做到服務(wù)之間松耦合。
- 系統(tǒng)瓶頸。在真實請求流量加倍下暴露服務(wù)瓶頸點。
- 故障獨立,容災(zāi)降級等等。
故障演練
如果要演練故障,首先要模擬故障(我們不可能真跑去機房把服務(wù)器炸了)。自動化的故障模擬系統(tǒng)業(yè)界已有實踐,如Netflix的SimianAmy,阿里的MonkeyKing等。
美團點評內(nèi)部也有類似的工具,casekiller等等。
SimianAmy和casekiller設(shè)計思路相仿,都是通過Linux的一些“tc”、“iptables”等工具,模擬制造網(wǎng)絡(luò)延時、中斷等故障。這些工具都是需要root權(quán)限才可以執(zhí)行。美團點評的服務(wù)器都需要使用非root用戶來啟動進程,所以這種思路暫不可行。
這些工具都有一定要求,比如root權(quán)限,比如需要用Hystrix來包裝一下外部依賴。比如我想制造一個表的慢查詢、想制造Redis的某個操作網(wǎng)絡(luò)異常,就有些麻煩。
所以我們準(zhǔn)備自己造個輪子 :)
需求:業(yè)務(wù)方低成本接入,流量以最低成本進行故障的“制造”和“恢復(fù)”,無需發(fā)布、對代碼無侵入就可以在后臺界面上進行故障的場景配置、開啟與停止。
基于以上,我們開發(fā)了故障演練系統(tǒng)。它是一個可以針對集群級別(AppKey級別)的所有機器,隨意啟停“故障”的故障演練平臺。可以在無需root權(quán)限的前提下,構(gòu)造任意method級別的延時或者異常類故障。
我們的設(shè)計思路是:
流量復(fù)制系統(tǒng)
架構(gòu)設(shè)計中參考了DubboCopy的系統(tǒng)設(shè)計,增加了一個SDK,解除了對TCPCopy的依賴。
形成以下的流程:
① 需要壓測方先依賴我們的SDK包,在需要壓測的具體實現(xiàn)方法上打上注解@Copy,并注明采樣率simplingRate(默認采樣率為100%)。
@Copy(attribute = CopyMethodAttribute.READ_METHOD, simplingRate = 1.0f) public Result toCopiedMethod() { }② 正式流量來時,異步將流量發(fā)往copy-server。 ③ copy-server根據(jù)流量中的信息(interface、method、serverAppKey)來獲取壓測配置(影子集群的AppKey,需要放大幾倍)。 ④ 根據(jù)壓測配置,對影子集群按照放大倍數(shù)開始發(fā)包。
協(xié)議分析
Thrift原生協(xié)議情況下,如果你沒有IDL(或者注解式的定義),你根本無法知道這條消息的長度是多少,自然做不到在沒有IDL的情況下,對報文進行解析轉(zhuǎn)發(fā)。感謝基礎(chǔ)組件同學(xué)做的統(tǒng)一協(xié)議方面的努力,讓ThriftCopy這個事情有了可行性 :)
除了公網(wǎng)RPC接口使用HTTP協(xié)議以外,美團點評內(nèi)部RPC協(xié)議都統(tǒng)一為一種兼容原生Thrift協(xié)議的“統(tǒng)一協(xié)議”。
total length指定其后消息的總長度,包含2B的header length+消息頭的長度+消息體的長度+可能的4B的校驗碼的長度。header length指定其后消息頭的長度。
header里的內(nèi)容有TraceInfo和RequestInfo等信息,里面有clientAppKey、interfaceName、methodName等我們需要的信息。
client功能
應(yīng)用啟動時
RPC請求到來時
以上,便可進行流量的復(fù)制與分發(fā),在服務(wù)設(shè)計上,Client端盡量做到輕量高效,對接入方的影響最小,接入成本低,并且在整個流量復(fù)制的過程中安全可控。另外,在Client,當(dāng)前針對美團點評使用的Thrift協(xié)議,進行:
- 流量染色。對原請求在協(xié)議層重寫染色其中的clientAppKey和requestMethodName,分別重寫為”“和”${rawMethodName}_copy”在請求接收方可以調(diào)用特定方法即可判斷請求是否是由“流量復(fù)制分發(fā)服務(wù)”的轉(zhuǎn)發(fā)請求。
- 讀寫標(biāo)記。通過在注解上attribute屬性標(biāo)記轉(zhuǎn)發(fā)接口為讀還是寫接口,為后續(xù)的流量分發(fā)做好準(zhǔn)備。
- 負載均衡。支持服務(wù)端的橫向擴展。
- 采樣控制。對流量復(fù)制/采樣進行控制,最大限度的定制復(fù)制行為。
server功能
應(yīng)用啟動時
流量到來時
故障演練系統(tǒng)
我們的需求是,可以集群級別(AppKey級別)而不是單機級別輕松的模擬故障。
模擬什么樣的故障呢?
|類型|故障表現(xiàn)| |-|-| |Thrift RPC |延時xxx ms或者直接拋出Exception| |mybatis mapper中的任意method|延時xxx ms或者直接拋出Exception| |Redis/Tair中的任意method|延時xxx ms或者直接拋出exception| |Kafka消息控制|模擬環(huán)境可能需要關(guān)閉消息生產(chǎn)/消費| |ES|延時xxx ms或者直接拋出exception|
我們調(diào)研了很多種實現(xiàn)方式:
|方案|備注| |-|-| |基于各種Linux指令模擬故障(網(wǎng)絡(luò)/IO/Load)|無法精細化模擬故障,可操作性差,并且受限于root權(quán)限,很多操作無法進行或者無法自動化| |基于HystrixCommand|只能針對接入了Hystrix的接口,且無法精確控制,實現(xiàn)復(fù)雜| |基于AOP攔截|對象內(nèi)部調(diào)用無法攔截,非容器對象也無法攔截| |字節(jié)碼注入|可以對各種目標(biāo)進行注入,擴展性高,可以精細化模擬(實現(xiàn)方案有基于classloader替換/Spring LTW/javaagent)|
經(jīng)過調(diào)研對比,選定了基于javaagent進行字節(jié)碼注入,來實現(xiàn)對個目標(biāo)對象的攔截并注入演練邏輯。
client功能
應(yīng)用啟動時
需要修改啟動時的JVM參數(shù)-javaagent:WEB-INF/lib/hotel-switch-faultdrill-agent-1.0.2.jar
方法執(zhí)行時 1. 執(zhí)行之前查找當(dāng)前的策略(map中的對應(yīng)object),如果沒有就跳過。 2. 如果有就先執(zhí)行object中的invoke方法。起到“java.lang.Thread.sleep(2000L);”比如“throw new org.apache.thrift.TException(“rpc error”);”等作用。
server的功能
server的功能就比較簡單了,主要是存儲用戶的設(shè)置,以及提供給用戶操作故障啟停的界面。
舉個例子
|測試服務(wù)|sourceAppKey|targetAppKey|加壓倍數(shù)|采樣率| |-|-|-|-|-| |hotel-swtich-api|com.sankuai.hotel.sw.api.beta03|com.sankuai.hotel.sw.api.beta04|5|1.0|
本機單測調(diào)用beta03集群上的服務(wù)接口distributeGoodsService.queryPrepayList 5000次。
在目標(biāo)集群beta04上收到此接口的25000次轉(zhuǎn)發(fā)過來的請求。
多次請求,觀察CAT(美團點評開發(fā)的開源監(jiān)控系統(tǒng),參考之前的博客)報表,其中Receive為接收到的需要轉(zhuǎn)發(fā)的次數(shù),Dispatch為實際轉(zhuǎn)發(fā)數(shù)量。
開始模擬故障:Redis故障、MTThrift故障。
請求接口:控貨的filter接口(訪問緩存),故障前、后響應(yīng)時間對比圖:
客戶端設(shè)置超時1s,接收到請求都超。
開啟Thrift接口故障演練,接口:com.meituan.hotel.goods.service.IGoodsService.queryGoodsStrategyModel,延時3s,設(shè)置接口超時6s。
故障前后響應(yīng)時間對比:
這樣就完成了一次加壓情況下的故障演練過程,隨后就可以讓團隊成員按照既定預(yù)案,針對故障進行降級、切換等操作,觀察效果。定期演練,縮短操作時間,降低系統(tǒng)不可用時間。
“故障演練系統(tǒng)”目前具備了流量復(fù)制和故障演練兩方面的功能。希望能通過這個系統(tǒng),對酒店后臺的幾個關(guān)節(jié)模塊進行壓測和演練,提高整體的可用性,為消費者、商家做好服務(wù)。
后續(xù)“故障演練系統(tǒng)”還會繼續(xù)迭代,比如把忙時流量存起來,等閑時再回放;還有如何收集response流量,進而把抽樣的request和response和每天的daily build結(jié)合起來;如何在故障演練系統(tǒng)中,模擬更多更復(fù)雜的故障等等。會有更多的課題等待我們?nèi)スタ?#xff0c;希望感興趣的同學(xué)可以一起參與進來,和我們共同把系統(tǒng)做得更好。
分布式會話跟蹤系統(tǒng)架構(gòu)設(shè)計與實踐,美團點評技術(shù)博客.
基于TCPCopy的Dubbo服務(wù)引流工具-DubboCopy.
從0到1構(gòu)建美團壓測工具,美團點評技術(shù)博客.
javassit.
曾鋆,2013年加入美團點評,就職于美團點評酒旅事業(yè)群技術(shù)研發(fā)部酒店后臺研發(fā)組,之前曾在人人網(wǎng)、愛立信、摩托羅拉工作過。
海智,2015年校招加入美團點評,就職于美團點評酒旅事業(yè)群技術(shù)研發(fā)部酒店后臺研發(fā)組。
亞輝,2015年加入美團點評,就職于美團點評酒旅事業(yè)群技術(shù)研發(fā)部酒店后臺研發(fā)組。
孟瑩,2014年校招加入美團點評,就職于美團點評酒旅事業(yè)群技術(shù)研發(fā)部酒店后臺研發(fā)組。
最后發(fā)個廣告,美團點評酒旅事業(yè)群技術(shù)研發(fā)部酒店后臺研發(fā)組長期招聘Java后臺、架構(gòu)方面的人才,有興趣的同學(xué)可以發(fā)送簡歷到xuguanfei@meituan.com。
總結(jié)
以上是生活随笔為你收集整理的美团点评酒店后台故障演练系统的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring boot中使用log4j记
- 下一篇: 卫星系统——酒店后端全链路日志收集工具介