从技术角度谈一谈,我参与设计开发的手Q春节红包项目--转
原文地址:http://chuansong.me/n/1608115051125
作者|吳逸翔編輯|唐聰
今年春節(jié)期間,QQ以AR技術(shù)為支撐、娛樂體驗(yàn)為導(dǎo)向在春節(jié)期間推出系列紅包并成功刷屏,系列紅包包括三大玩法+年初一彩蛋,分別是“LBS+AR天降紅包”、刷一刷紅包和“面對(duì)面”紅包,加上“娛樂紅包”(明星刷臉紅包),共計(jì)在春節(jié)期間派發(fā)了2.5億現(xiàn)金紅包和價(jià)值30億的卡券禮包。根據(jù)企鵝智酷提供的數(shù)據(jù),手機(jī)QQ的用戶滲透率在全平臺(tái)排名第二,為52.9%(第一是微信)。本文將會(huì)詳細(xì)介紹手Q春節(jié)紅包項(xiàng)目的設(shè)計(jì)、容災(zāi)、運(yùn)維、架構(gòu)以及總結(jié)。
先來介紹下整個(gè)過程中,手Q紅包的玩法,以方便不了解的同學(xué)理解。2017年的手Q春節(jié)游戲紅包共有刷一刷/AR地圖/掃福三種,如下圖所示:
雖然紅包分三種,但在游戲業(yè)務(wù)側(cè)這邊的體驗(yàn)都是一樣:用戶得到一個(gè)紅包卡券,打開后展示一個(gè)(刷一刷紅包)或者多個(gè)(AR地圖紅包)游戲的禮包列表,用戶選擇一個(gè)禮包后彈出區(qū)服組件,用戶確認(rèn)對(duì)應(yīng)的區(qū)服角色信息后會(huì)禮包會(huì)在48個(gè)小時(shí)內(nèi)發(fā)放到賬。體驗(yàn)如下:
游戲紅包的設(shè)計(jì)容量為入口卡券頁流量80k/s,以上體驗(yàn)流程一共涉及三個(gè)后臺(tái)接口:
-
禮包列表:用戶界面的禮包內(nèi)容需要根據(jù)后臺(tái)接口返回禮包列表進(jìn)行排序和過濾展示。
-
區(qū)服選擇:用戶界面彈出的區(qū)服組件需要后臺(tái)接口返回用戶區(qū)服角色信息。
-
領(lǐng)取禮包:用戶點(diǎn)擊“確認(rèn)”按鈕領(lǐng)取禮包,后臺(tái)進(jìn)行游戲道具發(fā)貨。
需求分析?禮包列表
這個(gè)功能使用現(xiàn)有能力比較容易解決。活動(dòng)共有十種游戲,每個(gè)游戲有兩種禮包:拉新(面向非注冊(cè)用戶,價(jià)值80元)/拉活躍(面向注冊(cè)用戶,價(jià)值20元),一個(gè)用戶只能獲得這兩種禮包中的一種,產(chǎn)品策略允許拉新的用戶獲得價(jià)值較低的拉活躍禮包,反之則不允許。頁面展示按用戶偏好排序十個(gè)游戲,每個(gè)游戲展示一個(gè)拉新禮包或者一個(gè)拉活躍禮包。
出于降低除夕當(dāng)前流量負(fù)載和柔性考慮,在紅包活動(dòng)前,十種游戲的禮包內(nèi)容作為前端靜態(tài)數(shù)據(jù)已經(jīng)預(yù)先通過離線包/CDN下發(fā);紅包活動(dòng)時(shí),后臺(tái)接口根據(jù)用戶偏好返回的游戲禮包列表,只是提供前端禮包內(nèi)容進(jìn)行過濾和排序,失敗了也有前端默認(rèn)的游戲禮包列表,保障用戶體驗(yàn)。
過濾:讀取存儲(chǔ),用戶有注冊(cè)的游戲返回活躍禮包,用戶沒有注冊(cè)的游戲返回拉新禮包
排序:一個(gè)兩層排序,第一層排序讀取存儲(chǔ)(key為用戶,value為用戶所注冊(cè)的游戲列表),用戶注冊(cè)的游戲(拉活躍)排在用戶沒有注冊(cè)的游戲(拉新)前面;第二層排序,對(duì)于拉新游戲列表和拉活躍游戲列表內(nèi)部,使用神盾算法對(duì)用戶這10款游戲的偏好再進(jìn)行二次排序。對(duì)于外部接口的依賴只有CMEM存儲(chǔ)和神盾算法接口,這兩個(gè)接口以及合并這兩種數(shù)據(jù)給出最終的個(gè)性化推薦禮包列表接口都可以平行擴(kuò)容以支持100k級(jí)別的QPS。
?區(qū)服信息
這個(gè)功能是現(xiàn)有能力。這個(gè)角色信息的來源是IDIP,但由于該接口較緩慢(2s左右)且容量較低(低于10k/s),故后臺(tái)做了一層緩存,將IDIP的區(qū)服信息永久性緩存到CMEM中,前臺(tái)也有本地緩存,在實(shí)踐中,前臺(tái)緩存命中率為60%,后臺(tái)為35%,多級(jí)緩存后走到IDIP的請(qǐng)求量只有5%,對(duì)IDIP影響不大,只需要擴(kuò)容現(xiàn)有的區(qū)服server和CMEM即可。
?領(lǐng)取禮包
這個(gè)功能使用現(xiàn)有能力解決存在困難。游戲中心日常發(fā)貨的道具和平臺(tái)比較多,平臺(tái)分為IEG-AMS/MP兩種,MP發(fā)貨對(duì)于發(fā)游戲道具和發(fā)Q幣又是兩種接口,故我們?cè)诩軜?gòu)上使用Facade模式,使用AMS作為發(fā)貨proxy,屏蔽了底層發(fā)貨的復(fù)雜性,向游戲中心提供統(tǒng)一的發(fā)貨接口,但比較遺憾的是從AMS到游戲的發(fā)貨接口都是同步接口,發(fā)貨能力較低,發(fā)貨能力最高的王者榮耀也只承諾了3k/s的發(fā)貨速度,明顯不足以直接承受100k/s級(jí)別的紅包發(fā)貨,故這里的核心問題是需要有一個(gè)隊(duì)列來解決生產(chǎn)/消費(fèi)速度不對(duì)等的問題。
去年的紅包是后臺(tái)收到發(fā)貨請(qǐng)求后落地到本地文件返回用戶成功,再由一個(gè)本機(jī)的daemon跑落地文件按游戲方所能提供的發(fā)貨速度進(jìn)行實(shí)際發(fā)貨,相當(dāng)于使用本地隊(duì)列緩沖。但這個(gè)方案存在某臺(tái)機(jī)器掛掉后如果不能恢復(fù)會(huì)丟失一部分本地的發(fā)貨數(shù)據(jù)造成漏發(fā),以及每個(gè)高并發(fā)業(yè)務(wù)都要重新做這一套東西不方便通用的問題。
從架構(gòu)上思考,其實(shí)最合理的方案是作為發(fā)貨proxy的AMS提供異步發(fā)貨的能力,將用來解決生成/消費(fèi)速度不匹配的MQ做在AMS內(nèi)部,為業(yè)務(wù)提供通用的異步發(fā)貨能力,業(yè)務(wù)側(cè)就不需要考慮發(fā)貨超過游戲方能力的問題,新業(yè)務(wù)有類似的場(chǎng)景也不需要重新開發(fā)。
游戲中心是業(yè)務(wù)側(cè),AMS是平臺(tái)側(cè)的能力,屬于另一個(gè)中心的業(yè)務(wù),于是一開始我們準(zhǔn)備推動(dòng)AMS做異步發(fā)貨的能力,這樣業(yè)務(wù)就只要調(diào)用發(fā)貨接口就可以了,很是方便。但事情并沒有想象中順利,與AMS的開發(fā)和PM開會(huì)溝通了幾次,異步發(fā)貨的能力他們也有做技術(shù)規(guī)劃,但年前他們有其它需求要做,沒有時(shí)間支持。和leader討論了一下這個(gè)能力最好還是放在AMS做成通用以便以后有同樣場(chǎng)景的業(yè)務(wù)使用,前臺(tái)也有同學(xué)開發(fā)過AMS功能,可以由游戲中心業(yè)務(wù)側(cè)的前后臺(tái)同學(xué)合作完成AMS異步發(fā)貨功能的開發(fā),在春節(jié)紅包中應(yīng)用,再將這個(gè)功能交接給平臺(tái)側(cè)的同學(xué)維護(hù),達(dá)到雙贏的效果。
整體方案與項(xiàng)目分解
整體方案圖如上圖所示,由于整個(gè)項(xiàng)目涉及多方開發(fā),而且模塊較多,整個(gè)模塊的開發(fā)周期較長,作為一期開發(fā)的話無法跟上基礎(chǔ)側(cè)卡券的驗(yàn)收和安排的幾次演習(xí)/壓測(cè),故按“大系統(tǒng)小做”的原則,根據(jù)模塊的重要和緊急程度分為幾期迭代完成,每一期有獨(dú)立的里程碑目標(biāo)并達(dá)到對(duì)應(yīng)的驗(yàn)收/演習(xí)/壓測(cè)要求:
-
第一期(方案圖左側(cè)部分)為功能需求,在12月9號(hào)上線通過卡券方面功能驗(yàn)收,先使用當(dāng)前的同步發(fā)貨接口,對(duì)性能無特別要求。
-
第二期(方案圖右側(cè)偏左部分)為性能需求,在12月20號(hào)上線參加第一次演習(xí),對(duì)發(fā)貨進(jìn)行異步化改造,要求直接面向用戶的外網(wǎng)發(fā)貨接口能支持100k QPS的峰值流量。
-
第三期(方案圖右側(cè)偏右部分)為容錯(cuò)需求,在12月27號(hào)上線參加第二次演習(xí),對(duì)發(fā)貨進(jìn)行對(duì)賬補(bǔ)送改造,保證發(fā)貨的可靠性。
-
第四期為監(jiān)控需求,在1月6號(hào)上線參加第三次演習(xí),確認(rèn)各項(xiàng)關(guān)鍵數(shù)據(jù)的采集,并將采集到的數(shù)據(jù)展現(xiàn)到一個(gè)統(tǒng)一視圖上,以便除夕期間值班人員實(shí)時(shí)了解紅包系統(tǒng)的整體運(yùn)行情況和出數(shù)據(jù)報(bào)表。
需求開發(fā)?功能需求開發(fā)
核心問題:不同場(chǎng)景的數(shù)據(jù)一致性
為用戶推薦禮包,用戶領(lǐng)取時(shí)需要經(jīng)過{4.1AMS外網(wǎng)發(fā)貨新OP}校驗(yàn)領(lǐng)取資格,后臺(tái)的推薦數(shù)據(jù)必須能和AMS的資格校驗(yàn)數(shù)據(jù)能夠?qū)ι?#xff0c;否則會(huì)出現(xiàn)后臺(tái)推薦的禮包用戶領(lǐng)取時(shí)卻通不過AMS的資格校驗(yàn)導(dǎo)致領(lǐng)取不了的問題。
接口處理的是單個(gè)游戲的領(lǐng)取禮包的請(qǐng)求,資格校驗(yàn)操作判斷一個(gè)用戶是否注冊(cè)了某個(gè)游戲。這個(gè)是AMS現(xiàn)有的通用功能,數(shù)據(jù)存儲(chǔ)在AMS的CMEM中,簡(jiǎn)化描述就是一個(gè)key-value模型,key為uin+appid,value如果有注冊(cè)則為1,沒有則為0(實(shí)際為了節(jié)省存儲(chǔ)空間,使用bitmap桶實(shí)現(xiàn),具體參見號(hào)碼包系統(tǒng)使用文檔),導(dǎo)入的數(shù)據(jù)源是產(chǎn)品在除夕前一周提供10款游戲的全量注冊(cè)號(hào)碼包,每個(gè)游戲一個(gè)文件,文件內(nèi)容是注冊(cè)用戶的QQ號(hào)。
但{3.1后臺(tái)禮包推薦接口}接口返回的是多個(gè)游戲的禮包列表,需要獲取十個(gè)游戲的用戶注冊(cè)狀態(tài)。如果讀取AMS現(xiàn)有的接口/存儲(chǔ),會(huì)有兩個(gè)問題:
-
AMS號(hào)碼包服務(wù)也要承受等同于推薦列表接口48k/s的流量,需要進(jìn)行擴(kuò)容
-
AMS號(hào)碼包服務(wù)調(diào)用CMEM雖然可以一次請(qǐng)求合并10個(gè)key進(jìn)行批量讀取,但請(qǐng)求到了CMEM的Access機(jī)還是要讀取多個(gè)Cache塊,性能并不如單請(qǐng)求單key讀取。
解決方案:同質(zhì)異構(gòu)的數(shù)據(jù)冗余
后臺(tái)將號(hào)碼包數(shù)據(jù)進(jìn)行重新組織存儲(chǔ)到后臺(tái)申請(qǐng)的另外一個(gè)CMEM中,key為uin,value為用戶已注冊(cè)的appid列表,已注冊(cè)的游戲推薦拉活躍禮包,沒注冊(cè)的游戲推薦拉新禮包,這樣只需要查詢一次CMEM就可以得到十個(gè)游戲每個(gè)游戲的禮包推薦類型是拉新還是拉活躍。
由于AMS和后臺(tái)使用的是同一份號(hào)碼包數(shù)據(jù),只是應(yīng)用場(chǎng)景不同,數(shù)據(jù)組織形式不同,兩份CMEM數(shù)據(jù)同質(zhì)異構(gòu),故后臺(tái)推薦的禮包可以通過AMS的資格校驗(yàn)。
?性能需求開發(fā)
核心問題:用戶領(lǐng)取禮包流量遠(yuǎn)超游戲發(fā)貨能力
紅包活動(dòng)具有時(shí)間短(單場(chǎng)5~30分鐘)、大用戶量參與(1.5億+)參與的特性,請(qǐng)求并發(fā)高,游戲紅包入口流量設(shè)計(jì)為80k/s,流經(jīng)各個(gè)模塊有衰減也有增幅,最終用戶領(lǐng)取禮包請(qǐng)求預(yù)估為96k/s,而游戲方提供的十款游戲總發(fā)貨能力只有5k/s(單款游戲最大為王者榮耀3k/s),請(qǐng)求峰值接近處理能力的20倍,同步調(diào)用會(huì)導(dǎo)致游戲方發(fā)貨接口過載,造成大面積發(fā)貨失敗,這個(gè)問題如何處理?
解決方案:發(fā)貨異步化
使用一個(gè)緩沖隊(duì)列來解決生產(chǎn)消費(fèi)能力不對(duì)等的問題。用戶領(lǐng)取請(qǐng)求到達(dá)AMS進(jìn)行基礎(chǔ)的資格校驗(yàn)后將請(qǐng)求放入MQ中,返回用戶成功并告知會(huì)在48小時(shí)內(nèi)到賬。再由后臺(tái)發(fā)貨Daemon從MQ中讀取請(qǐng)求,通過限速組件控制保證以不超過游戲方發(fā)貨能力的速率進(jìn)行發(fā)貨操作。使用的MQ是部門近來建設(shè)的RocketMQ,具體參見會(huì)員消息隊(duì)列(RocketMQ)接入指南。
?容錯(cuò)需求開發(fā)
核心問題:安全發(fā)貨
三場(chǎng)活動(dòng)發(fā)放的禮包總數(shù)預(yù)計(jì)將近4億,如何保障這些禮包對(duì)于合法用戶能都發(fā)貨到賬,不少發(fā)也不多發(fā)?如何防范高價(jià)值道具被惡意用戶刷走?有沒有可能內(nèi)部開發(fā)人員自己調(diào)用接口給自己發(fā)禮包?
解決方案:對(duì)賬補(bǔ)送/訂單號(hào)/安全打擊/權(quán)限控制
1. 訂單號(hào)解決不多發(fā)的問題
用戶領(lǐng)取禮包的接口{4.1AMS外網(wǎng)發(fā)貨新OP}調(diào)用成功,會(huì)為這個(gè)請(qǐng)求附帶一個(gè)UUID生成的一個(gè)全局唯一的訂單號(hào),再放進(jìn)MQ中,{4.3AMS內(nèi)網(wǎng)發(fā)貨OP}從MQ中取出消息,調(diào)用游戲方發(fā)貨接口前都會(huì)先校驗(yàn)這個(gè)訂單號(hào)是否用過,沒用過則將訂單號(hào)以key的形式寫入CMEM,再進(jìn)行發(fā)貨操作。如果出現(xiàn)對(duì)同一個(gè)發(fā)貨消息進(jìn)行重復(fù)發(fā)貨,則會(huì)發(fā)現(xiàn)訂單號(hào)已經(jīng)用過了不會(huì)進(jìn)行實(shí)際的發(fā)貨操作,保證以訂單號(hào)為標(biāo)識(shí)的同一個(gè)發(fā)貨請(qǐng)求只會(huì)進(jìn)行一次發(fā)貨操作。
2. 對(duì)賬補(bǔ)送解決不少發(fā)的問題
發(fā)貨失敗是不可避免的,諸如網(wǎng)絡(luò)波動(dòng)/游戲方發(fā)貨接口故障之類的問題都可能導(dǎo)致調(diào)用發(fā)貨接口失敗。在同步領(lǐng)取環(huán)境下,用戶可以通過重試在一定程度上解決這個(gè)問題。但是對(duì)于異步發(fā)貨,用戶點(diǎn)擊領(lǐng)取后發(fā)貨請(qǐng)求由{4.1AMS外網(wǎng)發(fā)貨新OP}放入MQ中就算成功了,即使后臺(tái)調(diào)用游戲的實(shí)際發(fā)貨接口失敗了沒有實(shí)際到賬,用戶對(duì)此也無感知不能進(jìn)行重試但是會(huì)投訴,后臺(tái)發(fā)貨系統(tǒng)必須通過自身的容錯(cuò)保證即使游戲方的發(fā)貨接口不穩(wěn)定偶爾會(huì)失敗,用戶所領(lǐng)的禮包能最終到。這里我們使用了對(duì)賬補(bǔ)送方案。
對(duì)賬:用戶領(lǐng)取禮包調(diào)用的接口{4.1AMS外網(wǎng)發(fā)貨新OP}成功寫應(yīng)發(fā)流水,{4.3AMS內(nèi)網(wǎng)發(fā)貨OP}調(diào)用游戲方發(fā)貨接口的寫實(shí)發(fā)流水,由于部分消息會(huì)堆積在消息隊(duì)列中,這部分稱為隊(duì)列堆積流水。故實(shí)際要進(jìn)行補(bǔ)發(fā)操作的流水由以下公式可得:
失敗補(bǔ)發(fā)流水= 應(yīng)發(fā)流水 - 實(shí)發(fā)流水 - 隊(duì)列堆積流水。
由于訂單號(hào)的存在,可以保證同一個(gè)發(fā)貨請(qǐng)求重復(fù)發(fā)送也不會(huì)多發(fā),對(duì)隊(duì)列中堆積的消息提前進(jìn)行補(bǔ)發(fā)操作也不會(huì)導(dǎo)致多發(fā)。故當(dāng)隊(duì)列中堆積的流水較少的時(shí)候,采用應(yīng)發(fā)流水與實(shí)發(fā)流水的差集作為失敗補(bǔ)發(fā)流水是合理,只是每個(gè)對(duì)賬周期會(huì)對(duì)隊(duì)列中堆積的消息進(jìn)行兩次發(fā)貨操作,對(duì)性能略有損耗。
后臺(tái)每個(gè)小時(shí)運(yùn)行一次增量對(duì)賬功能,檢測(cè)MQ消息堆積量量低于某個(gè)閾值,則進(jìn)行對(duì)賬操作,截取上次對(duì)賬到此時(shí)的應(yīng)發(fā)流水/實(shí)發(fā)流水,兩者相減得到補(bǔ)發(fā)流水。
補(bǔ)送:對(duì)對(duì)賬操作得到的補(bǔ)發(fā)流水調(diào)用游戲方發(fā)貨接口進(jìn)行發(fā)貨補(bǔ)送操作。
3. 安全打擊解決高價(jià)值道具防刷的問題
對(duì)于領(lǐng)獎(jiǎng)的請(qǐng)求,都要求都要求帶上登錄態(tài),對(duì)用戶進(jìn)行身份驗(yàn)證,同時(shí)對(duì)于高價(jià)值的道具開啟安全打擊,上報(bào)安全中心進(jìn)行惡意用戶校驗(yàn),防止被惡意用戶刷走。
4. 權(quán)限控制解決內(nèi)部人員監(jiān)守自盜的問題
對(duì)于發(fā)貨的機(jī)器都要安裝鐵將軍,用戶需要使用RTX名和token才能登錄機(jī)器,審計(jì)用戶在機(jī)器上的操作行為;
發(fā)貨模塊對(duì)于調(diào)用方是需要嚴(yán)格授權(quán),調(diào)用方需要申請(qǐng)key,包含程序路徑、程序MD5、部署模塊等信息,保證發(fā)貨功能不被隨意調(diào)用。
?監(jiān)控需求開發(fā)
核心問題:紅包涉及多個(gè)系統(tǒng)的自有監(jiān)控,數(shù)據(jù)收集困難
在監(jiān)控方面有兩個(gè)主要訴求:
我們對(duì)外提供的服務(wù)是否正常?如果有問題,如何快速地發(fā)現(xiàn)問題、分析問題?
實(shí)時(shí)知道用戶在整個(gè)系統(tǒng)的行為漏斗模型,每一步的轉(zhuǎn)化率是多少?
游戲紅包涉及紅包基礎(chǔ)側(cè)/業(yè)務(wù)前臺(tái)/業(yè)務(wù)后臺(tái)/AMS/MQ平臺(tái)等多個(gè)合作方,各個(gè)系統(tǒng)有自己的監(jiān)控系統(tǒng),數(shù)據(jù)來源不一致,活動(dòng)當(dāng)天一個(gè)系統(tǒng)一個(gè)系統(tǒng)地收集的話效率太低。
解決方案:匯總各個(gè)系統(tǒng)的關(guān)鍵數(shù)據(jù)到一個(gè)視圖
紅包作為一個(gè)涉及多個(gè)子系統(tǒng)的聚合系統(tǒng),我們需要一個(gè)匯總了各個(gè)子系統(tǒng)關(guān)鍵數(shù)據(jù)的整體視圖,才能夠較全面地監(jiān)控業(yè)務(wù)核心指標(biāo),對(duì)系統(tǒng)和業(yè)務(wù)有較全面把控,避免在監(jiān)控系統(tǒng)中跳轉(zhuǎn)檢索而耗費(fèi)有限的時(shí)間,為迅速響應(yīng)解決問題提供保證。
接口封裝:雖然紅包涉及的多個(gè)子系統(tǒng),各自有各自的上報(bào)方式和監(jiān)控系統(tǒng),但是對(duì)于關(guān)鍵數(shù)據(jù)大都有提供HTTP形式的查詢接口,我們通過封裝,將接口的定義統(tǒng)一為key-value形式,以(監(jiān)控項(xiàng)id,開始時(shí)間,結(jié)束時(shí)間)為key,value為(開始時(shí)間,結(jié)束時(shí)間)段內(nèi)監(jiān)控id的值之和。
配置化:一場(chǎng)紅包活動(dòng)的監(jiān)控,可以由一個(gè)時(shí)間段加若干個(gè)監(jiān)控項(xiàng)定義。比如刷一刷紅包,時(shí)間段為除夕當(dāng)天20:00~20:30,監(jiān)控項(xiàng)為若干頁面的點(diǎn)擊量,若干禮包的發(fā)放量,若干后臺(tái)接口的請(qǐng)求量,若干MQ的堆積量等等。
通過對(duì)接口的封裝和配置化,新增一場(chǎng)紅包活動(dòng),只需要增加一個(gè)時(shí)間段和若干個(gè)監(jiān)控項(xiàng)的配置文件,比如下圖的AR/刷一刷混場(chǎng)/刷一刷專場(chǎng)就是通過3個(gè)配置文件定義3場(chǎng)活動(dòng),新增一場(chǎng)活動(dòng)也只需要增加一個(gè)配置文件,并可以在一個(gè)視圖上靈活切換,相當(dāng)方便。
從上圖中我們就可以實(shí)時(shí)看到實(shí)發(fā)和應(yīng)發(fā)是大致相等的,隊(duì)列沒有出現(xiàn)堆積,用戶在各級(jí)頁面的轉(zhuǎn)化率,可以很方便地判斷系統(tǒng)的健康狀態(tài)和分析定位問題。
系統(tǒng)保障
第四部分講述了業(yè)務(wù)需求的開發(fā),但是否功能開發(fā)完成后我們就這樣就可放到線上安心睡大覺了呢?
-
如果出現(xiàn)一部分機(jī)器乃至整個(gè)機(jī)房掛了,服務(wù)是否可用?
-
外部的服務(wù)突然故障了,比如MQ突然掛了,不能寫入消息了,服務(wù)是否可用?
-
說是紅包入口流量8W/s,萬一來了20W/s呢?系統(tǒng)會(huì)不會(huì)掛掉?服務(wù)是否可用?
以下從系統(tǒng)容災(zāi)/過載保護(hù)/柔性可用/立體監(jiān)控來講我們這方面做的一些工作,我們對(duì)于除夕當(dāng)天出現(xiàn)各種問題系統(tǒng)還能正常運(yùn)行,用戶能正常體驗(yàn)服務(wù)的信心從何而來?
系統(tǒng)容災(zāi)
容災(zāi)就是在整體服務(wù)一部分出現(xiàn)異常時(shí),另一部分能頂上,不影響整體服務(wù)的使用,保障業(yè)務(wù)可用、數(shù)據(jù)安全。但容災(zāi)設(shè)計(jì)會(huì)使得系統(tǒng)復(fù)雜度增加,成本和代價(jià)也增加,需要額外的開銷和資源,應(yīng)該在合理的范圍內(nèi)考慮容災(zāi)。
容災(zāi)級(jí)別一般劃分為多機(jī)容災(zāi)、多機(jī)房容災(zāi),多地容災(zāi),紅包的后臺(tái)服務(wù)主要使用公用組件的均衡負(fù)載和系統(tǒng)容災(zāi)能力,服務(wù)無單點(diǎn)問題,采用同地多機(jī)房部署,按多機(jī)房容災(zāi)標(biāo)準(zhǔn)設(shè)計(jì)。
?接入層
典型的GSLB+TGW+QZHTTP接入,GSLB解析域名把請(qǐng)求帶到離用戶最近的IDC的TGW接入機(jī),TGW再通過內(nèi)網(wǎng)專線,把請(qǐng)求轉(zhuǎn)發(fā)到實(shí)際提供WEB服務(wù)的QZHTTP服務(wù)器上。
-
GSLB:Global Server Load Balance的首字母縮寫,意為全局負(fù)載均衡,主要提供提供域名解析的就近接入和流量調(diào)度。實(shí)現(xiàn)在廣域網(wǎng)(包括互聯(lián)網(wǎng))上不同地域的服務(wù)器間的流量調(diào)配,保證使用最佳的離自己最近的客戶服務(wù)器服務(wù),從而確保訪問質(zhì)量;它對(duì)服務(wù)器和鏈路進(jìn)行綜合判斷來決定由哪個(gè)地點(diǎn)的服務(wù)器來提供服務(wù),實(shí)現(xiàn)異地服務(wù)器群服務(wù)質(zhì)量的保證。紅包使用獨(dú)立的sh.vip.hongbao.qq.com域名。
-
TGW:Tencent Gateway,是一套實(shí)現(xiàn)多網(wǎng)統(tǒng)一接入,支持自動(dòng)負(fù)載均衡的系統(tǒng),TGW把外網(wǎng)不同運(yùn)營商的請(qǐng)求,通過內(nèi)網(wǎng)隧道轉(zhuǎn)發(fā)給server,server返回?cái)?shù)據(jù)時(shí),再把數(shù)據(jù)通過內(nèi)網(wǎng)隧道返回給TGW,再由TGW發(fā)送給不同的運(yùn)營商。紅包TGW外網(wǎng)部署了上海電信聯(lián)通雙VIP+香港CAP VIP。
-
QZHTTP:Web服務(wù)器,負(fù)責(zé)將HTTP請(qǐng)求轉(zhuǎn)成邏輯層使用的WUP協(xié)議,采用同地多機(jī)房部署部署。QZHTTP作為TGW的RS,TGW會(huì)周期性的探測(cè)RS的狀態(tài),在1分鐘內(nèi)自動(dòng)把故障RS從可服務(wù)列表中踢除,當(dāng)TGW檢測(cè)到RS恢復(fù)正常后,自動(dòng)把它加回可服務(wù)列表中。由TGW提供負(fù)載均衡和容災(zāi)。
?邏輯層
邏輯層使用SPP容器開發(fā),禮包列表/區(qū)服選擇/禮包發(fā)貨三個(gè)功能均是無狀態(tài)服務(wù),多個(gè)服務(wù)器在服務(wù)容量足夠的情況下任意踢掉一部分都不會(huì)影響正常服務(wù),使用L5進(jìn)行負(fù)載均衡/容災(zāi)/過載保護(hù)。
L5:機(jī)器級(jí)別容災(zāi),業(yè)務(wù)程序調(diào)用L5 API從L5 Agent獲取后臺(tái)服務(wù)器的(IP, Port),使用該(IP, Port)對(duì)應(yīng)的后臺(tái)服務(wù)器進(jìn)行通信,訪問結(jié)束時(shí)調(diào)用L5 API上報(bào)訪問接口和處理時(shí)延,L5 Agent對(duì)L5 API 上報(bào)的訪問結(jié)果和處理時(shí)延進(jìn)行統(tǒng)計(jì)和上報(bào),當(dāng)服務(wù)器出現(xiàn)故障,L5一般在1到2分鐘內(nèi)就會(huì)自動(dòng)剔除故障服務(wù)器。
?數(shù)據(jù)層
數(shù)據(jù)層主要使用了作為K-V存儲(chǔ)的CMEM和作為分布式消息隊(duì)列的RocketMQ,這兩種服務(wù)都采用接入層-存儲(chǔ)層劃分,邏輯層訪問數(shù)據(jù)層的接入層使用L5進(jìn)行負(fù)載均衡/容災(zāi),數(shù)據(jù)層的存儲(chǔ)層都采用一主一備雙機(jī)熱備容災(zāi),并落地磁盤支持掉電重啟后重建內(nèi)存數(shù)據(jù),支持多機(jī)容災(zāi)但是不支持多機(jī)房多地容災(zāi)。
?過載保護(hù)
紅包入口流量說是8W/s,萬一基礎(chǔ)側(cè)有問題發(fā)到了20W/s怎么辦?
每個(gè)模塊的容量都是從入口流量按照用戶行為漏斗模型推算轉(zhuǎn)化率設(shè)計(jì)的,萬一評(píng)估有誤轉(zhuǎn)化率偏高超過了設(shè)計(jì)容量怎么辦?
對(duì)于可能出現(xiàn)的超過了設(shè)計(jì)容量的流量尖峰,就要應(yīng)用過載保護(hù)方法,保障系統(tǒng)能拒絕超過容量的部分請(qǐng)求,保障設(shè)計(jì)容量內(nèi)的請(qǐng)求還能正常響應(yīng),實(shí)施的時(shí)候有四個(gè)要注意的地方:
-
從源頭上減少無效請(qǐng)求;
-
從接入層開始拒絕;
-
各層互相不信任;
-
要照顧用戶的情緒。
?流量預(yù)加載
CDN做為頁面訪問的關(guān)鍵路徑,前端頁面制作離線包,預(yù)先下發(fā)到客戶端,減少除夕當(dāng)天CDN的流量壓力。
?頻率限制
前臺(tái)對(duì)用戶發(fā)起請(qǐng)求的頻率進(jìn)行限制,超出頻率的請(qǐng)求提示用戶失敗而不走到后臺(tái)(每5秒只允許請(qǐng)求一次到后臺(tái)),前臺(tái)保護(hù)后臺(tái)。
后臺(tái)接入層根據(jù)壓測(cè)數(shù)據(jù)配置CGI接口的每分鐘接受的請(qǐng)求數(shù),超出接口處理能力的請(qǐng)求丟棄并進(jìn)行告警。接入門神系統(tǒng),配置IP/uin/refer等規(guī)則限制惡意用戶刷請(qǐng)求,保障服務(wù)的正常運(yùn)行。
?降級(jí)開關(guān)
前臺(tái)調(diào)用后臺(tái)的接口,設(shè)置開關(guān)以一定概率丟棄請(qǐng)求,對(duì)于關(guān)鍵路徑返回錯(cuò)誤提示用戶稍后重試,對(duì)于非關(guān)鍵路徑提供降級(jí)體驗(yàn),結(jié)合頻率限制功能,可以限制前臺(tái)的流量傳遞到后臺(tái)的比例,當(dāng)比例設(shè)為0的時(shí)候則關(guān)閉該模塊,實(shí)現(xiàn)前臺(tái)保護(hù)后臺(tái)。
?隊(duì)列堆積丟棄
后臺(tái)邏輯層使用SPP框架,worker處理消息前先檢查消息在SPP消息隊(duì)列中等待時(shí)間是否超出了預(yù)設(shè)閾值(500ms),在隊(duì)列中堆積過久的消息前端已經(jīng)超時(shí),對(duì)于用戶已經(jīng)無意義,服務(wù)丟棄請(qǐng)求并進(jìn)行告警,預(yù)防隊(duì)列式過載雪崩。
?柔性可用
柔性可用,柔性是為了保護(hù)系統(tǒng),保證系統(tǒng)整體的穩(wěn)定性,可用性。可用是為了用戶,盡最大努力為用戶提供優(yōu)質(zhì)的體驗(yàn)(可能是部分服務(wù)體驗(yàn))。一個(gè)是從系統(tǒng)本身角度出發(fā),一個(gè)是從用戶角度看,在真正實(shí)施過程中只有將兩者分析清,并融合在一起才能真正做到系統(tǒng)的柔性可用。關(guān)鍵問題是找準(zhǔn)用戶的核心訴求,找出符合求場(chǎng)景的核心訴求作為關(guān)鍵路徑,出現(xiàn)異常可以放棄的訴求作為非關(guān)鍵路徑。
?找準(zhǔn)用戶的核心訴求
春節(jié)游戲紅包用戶的核心訴求有三個(gè):
-
看到禮包列表
-
選擇區(qū)服角色
-
領(lǐng)取禮包到賬
其他的都可以作為非關(guān)鍵路徑,有可以提高用戶體驗(yàn),沒有也不影響用戶的核心訴求。
?保障關(guān)鍵路徑的可用
看到禮包列表:作為頁面關(guān)鍵模塊的禮包列表,在紅包活動(dòng)前,十種游戲的禮包內(nèi)容作為前端靜態(tài)數(shù)據(jù)已經(jīng)預(yù)先通過離線包/CDN下發(fā)。紅包活動(dòng)時(shí),后臺(tái)接口根據(jù)用戶偏好返回的游戲禮包列表,只是提供前端禮包內(nèi)容進(jìn)行過濾和排序,失敗了也有前端默認(rèn)的游戲禮包列表,用戶依舊能看到禮包列表,只是排序不夠智能化。
選擇區(qū)服角色:除夕前一周游戲中心的主站頁面和運(yùn)營活動(dòng)增加一個(gè)后臺(tái)接口請(qǐng)求,預(yù)先請(qǐng)求用戶的區(qū)服角色信息緩存到本地,既降低了除夕當(dāng)天的區(qū)服接口請(qǐng)求量又保證了游戲中心核心用戶的區(qū)服信息是有效的。
領(lǐng)取禮包到賬:RocketMQ對(duì)于領(lǐng)取操作是關(guān)鍵路徑服務(wù),用戶領(lǐng)取禮包后需要寫入RocketMQ才能算成功。故業(yè)務(wù)對(duì)消息隊(duì)列做了邏輯層面的容災(zāi),當(dāng)RocketMQ出現(xiàn)故障時(shí),可以打開容災(zāi)開關(guān),領(lǐng)取操作寫完應(yīng)發(fā)流水后直接返回成功,不再往RocketMQ寫入消息,采用分時(shí)段對(duì)賬的方法替代實(shí)時(shí)發(fā)貨,達(dá)到消息隊(duì)列容災(zāi)效果,參見容錯(cuò)需求開發(fā)。
?放棄異常的非關(guān)鍵路徑
-
前端頁面展示模塊化,對(duì)于請(qǐng)求數(shù)據(jù)不成功的非關(guān)鍵模塊進(jìn)行隱藏。
-
紅包頁面導(dǎo)流到游戲中心,游戲中心展示按紅點(diǎn)邏輯展示,只顯示第一屏的數(shù)據(jù),默認(rèn)不加載第二屏數(shù)據(jù),用戶往下滾動(dòng)時(shí)再加載,犧牲用戶往下滾動(dòng)會(huì)短暫卡頓的體驗(yàn)減少后臺(tái)的請(qǐng)求壓力。
-
后臺(tái)讀取算法接口返回的推薦排序失敗時(shí)使用默認(rèn)的禮包排序。
-
后臺(tái)讀取CMEM接口返回的禮包是拉活躍還是拉新失敗的時(shí)每款游戲默認(rèn)返回低價(jià)值的拉活躍禮包。
?立體監(jiān)控
“我們對(duì)外提供的服務(wù)是否正常的么?怎么證明我們的服務(wù)是沒有問題的?”,是監(jiān)控告警首先要回答的根本問題。有效的監(jiān)控告警需要保證能完備地監(jiān)測(cè)業(yè)務(wù)指標(biāo),當(dāng)發(fā)現(xiàn)問題時(shí)能有效通知負(fù)責(zé)人并幫助分析問題,強(qiáng)調(diào)的是“完備性”和“有效通知”,兩者缺一不可。春節(jié)紅包的監(jiān)控告警從用戶、業(yè)務(wù)和機(jī)器三個(gè)層面上描述。
?用戶層面
從用戶的角度監(jiān)控系統(tǒng)是否有問題,模擬用戶行為從系統(tǒng)外部發(fā)起請(qǐng)求,判斷請(qǐng)求結(jié)果和時(shí)延是否符合預(yù)期,使用的是ATT的自動(dòng)化用例。
ATT,autotest,是社交、開放平臺(tái)測(cè)試組使用的測(cè)試管理工具,它是功能用例、自動(dòng)化用例管理的平臺(tái)。通過模擬真實(shí)的用戶訪問并校驗(yàn)返回?cái)?shù)據(jù),確認(rèn)訪問延時(shí)、功能正確性的用戶層的監(jiān)控手段,從業(yè)務(wù)側(cè)進(jìn)行實(shí)施監(jiān)控功能的正常運(yùn)行狀態(tài)的工具。
?業(yè)務(wù)層面
監(jiān)控紅包系統(tǒng)內(nèi)部的各個(gè)子業(yè)務(wù)模塊是否運(yùn)行正常,分為兩種:
1. 模塊間的調(diào)用監(jiān)控
監(jiān)控系統(tǒng)內(nèi)部各個(gè)模塊間的調(diào)用是否正常,使用的是模調(diào)系統(tǒng)。
2. 模塊內(nèi)的狀態(tài)監(jiān)控
監(jiān)控某個(gè)業(yè)務(wù)模塊當(dāng)前的狀態(tài)是否正常,使用的是各個(gè)子系統(tǒng)自建的監(jiān)控告警系統(tǒng),春節(jié)紅包這方面的監(jiān)控主要有兩個(gè):AMS禮包領(lǐng)取剩余數(shù)量和消息隊(duì)列消息堆積數(shù)量。春節(jié)紅包由于準(zhǔn)備的禮包數(shù)量較為充足,故沒有引起告警;隊(duì)列由于生成速度遠(yuǎn)超消費(fèi)速度,設(shè)置的告警閾值是100W,但實(shí)際最終堆積超過了1200W,引發(fā)了告警。
?機(jī)器層面
監(jiān)控機(jī)器的CPU/內(nèi)存/磁盤/網(wǎng)絡(luò)是否正常,使用的是網(wǎng)管系統(tǒng)。
網(wǎng)管系統(tǒng)(TNM2)是一個(gè)功能非常強(qiáng)大的采集服務(wù)器CPU、內(nèi)存、網(wǎng)絡(luò)、IO等指標(biāo)的監(jiān)控系統(tǒng),同時(shí)還能對(duì)設(shè)備的進(jìn)程和端口異常、磁盤使用率、硬件故障等進(jìn)行告警,同時(shí)對(duì)外部系統(tǒng)提供功能豐富的調(diào)用接口,關(guān)于網(wǎng)管系統(tǒng)的監(jiān)控能力,請(qǐng)參考其網(wǎng)站首頁的TMP監(jiān)控能力白皮書 。
演習(xí)驗(yàn)證
演習(xí)是一種將被動(dòng)相應(yīng)轉(zhuǎn)換為主動(dòng)服務(wù)的手段,在演習(xí)前設(shè)定演習(xí)目標(biāo)和演習(xí)方法,在演習(xí)過程中進(jìn)行驗(yàn)證并收集數(shù)據(jù),在演習(xí)后進(jìn)行總結(jié)并提出改進(jìn)方案。通過演習(xí),可以實(shí)際驗(yàn)證用戶行為與評(píng)估預(yù)期是否一致(灰度演習(xí)),系統(tǒng)各個(gè)模塊的容量是否符合預(yù)期(壓測(cè)演習(xí)),各類容災(zāi)和柔性的措施是否生效(異常演習(xí)),提前發(fā)現(xiàn)架構(gòu)中存在的問題。
?壓測(cè)演習(xí)
核心問題:系統(tǒng)能否抗住壓力
細(xì)分又可以劃為兩個(gè)問題:
-
對(duì)于系統(tǒng)容量內(nèi)的合理請(qǐng)求,系統(tǒng)能否正常處理
-
對(duì)于系統(tǒng)容量外的超額請(qǐng)求,系統(tǒng)能否成功丟棄
解決方案:全鏈路壓測(cè)和單模塊壓測(cè)
最理想的情況是先紅包各個(gè)模塊的進(jìn)行壓測(cè)后評(píng)估沒有問題,再灰度用戶使用現(xiàn)網(wǎng)流量進(jìn)入紅包系統(tǒng)進(jìn)行全鏈路壓測(cè),但由于使用現(xiàn)網(wǎng)流量進(jìn)行演習(xí)需要實(shí)際地發(fā)送紅包,成本較高,灰度500萬用戶紅包入口峰值僅為5k/s,遠(yuǎn)低于設(shè)計(jì)的80k/s。故對(duì)系統(tǒng)的壓力測(cè)試驗(yàn)證主要以單模塊壓測(cè)結(jié)合灰度演習(xí)得到的用戶行為數(shù)據(jù)評(píng)估系統(tǒng)的整體能力。
對(duì)于未上線的接口的CGI Server和SPP Server,采用ApachBenchmark模擬請(qǐng)求壓測(cè)。
對(duì)于已經(jīng)上線的接口,除了隔離現(xiàn)網(wǎng)機(jī)器用ApachBenchmark模擬請(qǐng)求壓測(cè)外,還使用了小組自研的壓測(cè)系統(tǒng),通過調(diào)整L5權(quán)重把現(xiàn)網(wǎng)流量逐步導(dǎo)到一臺(tái)機(jī)器上來進(jìn)行壓測(cè)。
經(jīng)驗(yàn)證,在V8的機(jī)器上,禮包列表/區(qū)服接口CGI/Server的QPS在5k/s~8k/s之間,禮包領(lǐng)取接口達(dá)到2k/s的QPS。在部署足夠的機(jī)器后,對(duì)于系統(tǒng)80k/s的請(qǐng)求量,是可以正常處理的。
在配置了接入層CGI的限速選項(xiàng)后,超出限速(8k/s)的超額請(qǐng)求會(huì)被CGI直接返回錯(cuò)誤而不傳遞到后端處理;在配置了邏輯層SPP的超時(shí)丟棄后,在隊(duì)列中堆積超過超時(shí)時(shí)間(500ms)的堆積請(qǐng)求會(huì)被框架丟棄而不進(jìn)行實(shí)際處理。對(duì)于超出系統(tǒng)容量的請(qǐng)求,系統(tǒng)是可以成功丟棄的。
?異常演習(xí)
核心問題:系統(tǒng)發(fā)生異常時(shí)各種柔性邏輯/容災(zāi)措施能否生效
系統(tǒng)中的柔性/容災(zāi)措施,往往只有系統(tǒng)異常時(shí)才會(huì)生效,導(dǎo)致在實(shí)際現(xiàn)網(wǎng)服務(wù)運(yùn)行中,柔性邏輯經(jīng)常無法測(cè)試到,容災(zāi)措施一般也不會(huì)啟用。這樣,當(dāng)運(yùn)營環(huán)境真正異常時(shí),柔性邏輯/容災(zāi)措施是否有效還是個(gè)未知數(shù)。
解決方案:驗(yàn)證柔性邏輯和容災(zāi)措施
在紅包正式上線前,通過模擬故障發(fā)生的真實(shí)異常場(chǎng)景,列出重點(diǎn)可能發(fā)生的故障問題,驗(yàn)證柔性邏輯和容災(zāi)錯(cuò)誤是否真實(shí)有效。
-
后臺(tái)SPP修改神盾的L5為錯(cuò)誤的L5,SPP調(diào)用神盾出錯(cuò),預(yù)期后臺(tái)依舊能按默認(rèn)排序返回禮包列表
-
后臺(tái)SPP修改CMEM的L5為錯(cuò)誤的L5,SPP調(diào)用CMEM出錯(cuò),預(yù)期后臺(tái)依舊能按全部游戲推薦拉活躍禮包返回禮包列表
-
后臺(tái)隨機(jī)停掉一臺(tái)SPP,CGI調(diào)用SPP出錯(cuò),預(yù)期服務(wù)短時(shí)間內(nèi)有部分失敗,L5能在1~2分鐘內(nèi)踢掉該出錯(cuò)機(jī)器,服務(wù)恢復(fù)正常
-
打開MQ容災(zāi)開關(guān),用戶領(lǐng)取成功消息不再放入MQ,而是直接走流水對(duì)賬,預(yù)期游戲能夠成功到賬
-
前臺(tái)用戶操作頻率超過了限制(5次/秒),預(yù)期前臺(tái)直接返回領(lǐng)取失敗,抓包看到請(qǐng)求不走到后臺(tái)
-
前臺(tái)調(diào)用后臺(tái)接口通過設(shè)置host指向錯(cuò)誤IP,前臺(tái)調(diào)用后臺(tái)推薦接口出錯(cuò),預(yù)期前端頁面依然能正確顯示作為關(guān)鍵路徑的禮包列表
-
前臺(tái)調(diào)用后臺(tái)接口通過設(shè)置host指向錯(cuò)誤IP,前臺(tái)調(diào)用后臺(tái)非關(guān)鍵信息接口出錯(cuò),預(yù)期前端頁面對(duì)非關(guān)鍵模塊進(jìn)行隱藏
經(jīng)測(cè)試同學(xué)驗(yàn)證,checklist中的柔性邏輯和容災(zāi)措施確切有效,符合預(yù)期。
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/6544418.html
總結(jié)
以上是生活随笔為你收集整理的从技术角度谈一谈,我参与设计开发的手Q春节红包项目--转的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 历经8年双11流量洗礼,淘宝开放平台如何
- 下一篇: 一个创业公司的API网关落地实践--转