天天看點

轉轉遊戲MQ重構:思考與心得之旅

作者:閃念基因

1 背景

遊戲業務自 2017 年啟航,至今已近乎走過七個春秋,曆經漫長歲月的發展,不知不覺間背負起沉重的曆史包袱。猶如一棵大樹,既有繁茂精壯的枝桠,亦有諸多枯敗凋零的枝葉。此文主要聚焦于商品更新 MQ 消費這一細微子產品,詳述遊戲業務如何對原有代碼予以重構,令遊戲這棵大樹重煥蓬勃生機。

1.1 起始之由

一日,驟然收到線上對下遊接口 RPC 調用限流之警報,限流警報門檻值為600k/min。遂着手排查觸發限流警報之因由。追根溯源,發覺乃外部存有更新操作,而更新接口調用門檻值大約3K/min。明明更新流量不高,緣何觸發限流?于是開啟了對系統的調研與排查。

1.2 重構前現狀

經過對限流原因的初步探索,我們進一步對商品消費 MQ 進行了全面梳理,發現遊戲已有19個訂閱商品更新 MQ 的 Consumer,分布在不同叢集。這些 Consumer 各自存有内部的查詢與更新相關操作,因其部分更新操作會催生新的 Message,緻使接口調用進一步擴增。

調研還發現有的廢棄 Consumer 還線上上持續消費,有的相同的消費邏輯被多個 Consumer 在消費。

針對上面問題簡單梳理總結,問題如下:

轉轉遊戲MQ重構:思考與心得之旅
a. 邏輯分散,可維護性差
b. 服務調用量成倍放大
c. 存在并發更新和覆寫的情況
d. 存在廢棄或者重複消費情況
           

1.3 問題分析

為什麼會形成這樣的現狀?

作者認為:前期需求快速疊代,新增新的 Consumer 可迅速響應需求,且開發便捷。然而,伴随需求的演變與疊代,新增的 Consumer 漸多,需求與人員的變更,使得系統全貌愈發難以全面掌控。不斷變更的邏輯,緻使整個系統的維護愈發艱難,進而衍生出形形色色的問題。

若要降低 MQ 相關接口調用量,有兩個核心要點:其一,減少查詢,實作資料複用;其二,減少更新接口調用,抑制新的 Message 産生。但當下系統已然如此分散,于現有結構上極難擷取出色的解決方案。欲改變目前此種狀況,需要全新的結構,對原有 MQ 消費邏輯進行重構。借由新的結構,不但能夠化解當下的問題,還能夠建構新的限制,引導未來新的功能撰寫方式,使整個系統更為健康穩定。

2 重構

2.1 目标

在着手重構之前,最為關鍵的是明晰目标。目标能夠輔助我們拟定方案,明确範圍,指引項目落地而不偏離正軌。

a. 合理的結構
b. 優化重複無效消費邏輯
c. 提高消費能力
d. 邏輯優化
e. 建構新體系
           

期望通過合理的代碼架構,令消費商品 MQ 消息的邏輯高度内聚且低耦合、各個類及方法的職責清晰明确。重構并非對老系統的簡單複制,更肩負着為系統未來擴充定義新的限制規範。恰似于這棵遊戲大樹中萌生出新的枝幹與分支,決定着後續細枝的生長方向。

除了架構合理,還需優化解決此前的重複和無效消費的情況,提升整體消費能力,解決原先接口調用放大的問題。此外,在調研中發現系統存在一些已下線的廢棄邏輯和部分有問題的代碼,趁此次重構之機予以優化。(注:通常不建議在重構中修改邏輯,對于修改邏輯務必要進行充分測試,否則可能引入新的系統 Bug)

2.2 制定方案

重構的總體方案主要由三部分構成:架構設計、實施計劃、測試計劃。

2.2.1 架構設計

轉轉遊戲MQ重構:思考與心得之旅

總體架構主要運用享元設計模式和政策設計模式,整個架構自上而下由三部分組成。

a. 資料預處理
b. 按分類調用Handler進行消費
c. 收攏調用更新接口
           

a:資料預處理主要負責過濾和預查詢資料。包含批量消費 MQ 消息,濾除非遊戲的消息,調用批查詢接口,預處理後續可能重複處理的邏輯,減少重複查詢,提升接口效率。

b:主要是按分類抽取 Handler 和公共 Handler,以使職責清晰分明。抽取公共 Handler 以處理一些公共邏輯,例如記錄埋點日志等。各個分類的 Handler 僅處理本分類的業務邏輯,實作邏輯解耦,提升可維護性。為友善切面的使用以及增強相關功能的内聚性,在 Handler 之下額外抽取了一層 Manage 層。Manage 層主要負責實作具體的消費邏輯,并提供可複用元件,令邏輯更具内聚性。

c:對中台商品相關的更新邏輯予以收攏,其主要目的在于減少更新接口的調用。(由于這些更新會産生新的 Message,故而通過調用批量接口的方式,來降低更新接口的調用次數,進而有效解決接口調用頻率放大的問題)

2.2.2 實施計劃

我們将整個重構劃分為以下三期來實作。

轉轉遊戲MQ重構:思考與心得之旅

第一期和第二期

第一期:主要針對非核心業務 MQ 邏輯進行遷移重構。非核心業務灰階上線,控制影響範圍,迅速驗證架構的可行性與穩定性。

第二期:核心業務相關 MQ 遷移重構。灰階上線,關注對核心業務的影響。完成此步基本完成全部業務邏輯遷移。

轉轉遊戲MQ重構:思考與心得之旅

第三期

第三期:對結構進行微調,主要是對相關功能進一步拆解、重構,使功能内部更為内聚,降低耦合,令整個系統最終達成設計之初的預期效果。

分多步進行重構的益處主要在于控制影響範圍,能夠迅速見到成效。每次改動範圍有限,更易于定位問題,也能夠極為便利地支援産品需求。

2.2.3 測試計劃

每次上線之前,核心主要通過三種測試,即白盒測試、黑盒測試、日志對比。

a:黑盒測試,校驗新老流程處理後的資料是否一緻。
b:白盒測試。測試每一行代碼的覆寫率,并觀察新老流程資料是否一緻。
c:調用接口前資料對比。在調用更新接口之處列印日志,對比新老流程調用更新接口的傳參是否一緻。
           

測試僅是一方面,上線後皆需關注整個系統的運作狀況,并做好關鍵方面的報警。此外,會同步一線客服人員,收集是否存在使用者回報的問題,依照原來Consumer的顆粒度進行灰階。

2.3 部分細節設計

統一幂等灰階切面處理

此系統乃是一個與 MQ 消費相關的重構項目,在每個消費子產品皆需確定消費的幂等性,然而遷移而來的 Consumer 衆多,若在每個地方皆書寫一遍幂等相關處理,極為不便。我主要借助了 Spring 的 AOP 能力來達成。

轉轉遊戲MQ重構:思考與心得之旅

主要是定義規範,定義幂等注解、統一傳回值(泛型)以及撰寫注解處理類。通過環繞注解來實作,處理類在處理之前會進行規範檢測,不規範則直接放過(相當于使用注解失效),消費成功後我們會将傳回結果通過緩存存儲起來,下次再來時,直接消費成功,無需重複處理,達成處理幂等性和減少重複消費的情況。幂等緩存的顆粒度為msgId。(灰階控制方案原理相同,此處不再贅述)

異常失敗應對

轉轉遊戲MQ重構:思考與心得之旅

我們在設計下遊商品更新時進行了收攏處理,以友善操作,但也帶來一個問題,即可能我們的業務資訊已更新,而下遊可能處理失敗,對此我們使用轉轉封裝的基于 RocketMQ 的消費重試元件來實作。(簡單來講,同步消費失敗,就會利用 RocketMQ,建立一個MQ消費資訊來異步處理)。未更新成功的資料,通過 MQ 重試來保障消費成功。

轉轉遊戲MQ重構:思考與心得之旅

更新失敗報警

我們還設有報警機制,未更新商品的資訊,通過企業微信發送報警,以提示技術人員,并提供商品資料資訊,友善在出現特殊異常情況時,人工兜底補足來處理此類情形。

資料隔離

新的Consumer在消費時提供了單獨的線程池處理,便于監控邏輯處理消費情況,提升整體邏輯處理能力的并發度。

轉轉遊戲MQ重構:思考與心得之旅

線程池監控

資料監控

建立豐富的監控名額和報警通知機制。通過日志查詢平台、資料看闆、異常企業微信報警通知,輔助我們在上線後實時觀察新流程的具體狀況,迅速定位問題。

轉轉遊戲MQ重構:思考與心得之旅

MQ生成消費監控

轉轉遊戲MQ重構:思考與心得之旅

上遊查詢失敗報警

3 總結

資料效果

項目上線後,下遊核心接口的調用量顯著降低,降幅 50%至80% 之間。其中,更新類接口的調用量降低了 80%,查詢類接口的調用量減少了 50%。

思考與總結

  1. 明确系統重構的緣由,主要涵蓋兩方面。(現有系統存在問題需解決,或者現有系統限制了新的業務發展)
  2. 務必要充分了解自身的系統。在重構之前,對于具體的業務邏輯和影響範圍等資訊需進行直接評估與确定。唯有明晰系統的原貌,方能依據系統的現狀設計全新的技術方案。
  3. 考慮未來發展,定義好的規範。好的規範和結構,在未來系統疊代發展起一個引導作用。引導大家按相同的思路開發,更好的協作和支援業務需求。
關于作者

許志芳,轉轉訂單業務後端研發工程師

來源-微信公衆号:轉轉技術

出處:https://mp.weixin.qq.com/s/bSFQVcLPFqOi5uKLxvAXUA

繼續閱讀