之前設計過一個 百萬級QPS的公共配置中心設計方案个束,主要是用于服務端配置枯冈,但是對于APP端拳昌,其實不太適用磕仅,因為我們想要實時觸達APP端搅吁,目前業(yè)界主流的觸達技術(shù)方案主要有以下幾種方案:
- push推送:push消息當前已經(jīng)成為實時推送營銷信息、重要通知的最主要手段之一诫龙,push消息擁有較強的實時性析显,而實際的移動端的應用場景中,push消息多用于營銷方案或重要信息的通知签赃,很少使用此通道來作為研發(fā)配置信息的觸達通道谷异,其會產(chǎn)生UI交互的變化。另外push消息依賴于用戶打開通知權(quán)限開關(guān)锦聊,而業(yè)內(nèi)普遍打開通知開關(guān)權(quán)限的比例低于50%晰绎,因此大部分用戶無法觸達;
- netty 長連接:通過建立一條客戶端到服務端之間的長連接通道括丁,此方案可以在發(fā)生配置信息變更后實時的將信息傳遞至客戶端荞下,但是需要耗費較大的服務器資源,來維護一條長連接通道史飞;
- C端輪詢:客戶端以一定的時間間隔向服務端發(fā)出請求尖昏,通過頻繁請求的方式來保持客戶端和服務器端的信息同步,這種同步方案的最大問題是當客戶端以固定頻率向服務器發(fā)起請求的時候构资,服務器端的數(shù)據(jù)可能并沒有更新抽诉,這樣會帶來很多無效的網(wǎng)絡傳輸。
總結(jié):推送push消息方案存在觸達比例低的問題吐绵,長鏈接存在耗費服務器資源的缺點迹淌,同時輪詢的方案也存在很多無效的網(wǎng)絡傳輸?shù)缺锥?/p>
實現(xiàn)方案
先搭建一個信息配置管理CMS平臺河绽,同時構(gòu)建一個客戶端獲取配置信息的客戶端組件,由用戶在CMS配置信息唉窃,然后由CMS后臺將配置信息的版本號信息同步至統(tǒng)一網(wǎng)關(guān)耙饰,所有客戶端請求到達統(tǒng)一網(wǎng)關(guān),并在返回的接口數(shù)據(jù)的header內(nèi)都會攜帶最新的版本號至客戶端纹份,客戶端對比發(fā)現(xiàn)新的版本號比緩存的版本大則請求配置信息拉取Switchquery配置接口苟跪,這樣只要App打開就會存在接口攜帶變化標志返回,這樣就會觸發(fā)客戶端主動發(fā)起請求更新配置信息蔓涧,提高了實時性件已,不受push開關(guān)權(quán)限控制和影響,不需要額外打造長連接通道元暴,具有低成本篷扩,實時性高等優(yōu)點。
時序圖
1茉盏、用戶在CMS 后臺配置相關(guān)信息鉴未,可支持配置布爾類型、整型援岩、字符串等類型的配置信息歼狼,可以配置App版本生效區(qū)間,按設備號灰度比例享怀,iOS或者安卓平臺的設定羽峰,生效白名單等相關(guān)信息;
2添瓷、配置信息持久化到數(shù)據(jù)庫梅屉;
3、配置后臺完成信息配置后鳞贷,后臺會基于當前時間戳坯汤,生成一個新的配置信息版本號,同時將這些配置的靜態(tài)數(shù)據(jù)寫入到服務端內(nèi)存緩存內(nèi)搀愧;
4惰聂、CMS配置后臺將配置信息數(shù)據(jù)寫入和保存一份靜態(tài)數(shù)據(jù)json到CDN(主動預熱),防止接口降級或者失敗以后可以降級從CDN拉取配置信息數(shù)據(jù)咱筛;
5搓幌、CMS后臺配置信息并提交和保存完成后,由CMS配置后臺將新的版本號寫入到統(tǒng)一網(wǎng)關(guān)后臺(所有客戶端到服務端的http請求都會經(jīng)過統(tǒng)一網(wǎng)關(guān)迅箩,所有服務端返回到客戶的http請求響應都會經(jīng)過統(tǒng)一網(wǎng)關(guān))溉愁,統(tǒng)一網(wǎng)關(guān)記錄下數(shù)據(jù)版本號,客戶端的所有接口請求的響應header增加一個字段x-switch-config饲趋,此字段會攜帶回配置信息的版本號至客戶端拐揭;
6撤蟆、 網(wǎng)關(guān)會將版本號下發(fā)至客戶端網(wǎng)絡組件,網(wǎng)絡組件在接受到網(wǎng)絡請求返回后堂污,首先會解析網(wǎng)絡請求的響應header家肯,如果解析到關(guān)鍵字將其對應的value一起解析封裝后發(fā)起一個全局通知;
7敷鸦、終端組件在監(jiān)聽到通知后息楔,與本地已經(jīng)緩存的配置信息數(shù)據(jù)版本號進行比對寝贡,相同則不處理扒披,大于本地版本號則發(fā)起配置信息拉取請求,這樣即可獲取到最新的開關(guān)配置信息并緩存在磁盤圃泡;
8碟案、如果CDN節(jié)點上的配置信息過期或不存在時,從CMC 服務端拉取最新的配置信息
此種觸達方式只要客戶端打開即會觸發(fā)請求至統(tǒng)一網(wǎng)關(guān)颇蜡,隨即就可以根據(jù)變化情況來決定是否更新最新的配置接口數(shù)據(jù)价说,無需push通知,無需建立長連接通道风秤,成本低鳖目,實時性高。
流程架構(gòu)設計
1缤弦、用戶在CMS配置平臺進行信息配置后领迈,配置后臺接口對配置信息進行對比,如果沒發(fā)生變化碍沐,則結(jié)束狸捅;發(fā)生變化則判斷此次變更距離上一次變更是否到了n秒,距離n秒內(nèi)則不會觸發(fā)配置信息變更同步累提,距離n秒外則觸發(fā)配置信息同步尘喝,觸發(fā)網(wǎng)關(guān)和后臺服務端內(nèi)存數(shù)據(jù)發(fā)生變化;也會同步寫入一份json靜態(tài)數(shù)據(jù)到CDN斋陪,這個是為了考慮靜態(tài)數(shù)據(jù)走CDN加速和洪峰流量
2朽褪、CMS觸發(fā)變化將新的版本號傳遞至統(tǒng)一網(wǎng)關(guān),統(tǒng)一網(wǎng)關(guān)會做數(shù)據(jù)版本號的存儲无虚,同時會將統(tǒng)一網(wǎng)關(guān)的所有機器內(nèi)存里都存儲一份最新的版本號缔赠;
3、 客戶端任意接口請求都會經(jīng)過統(tǒng)一網(wǎng)關(guān)骑科,所有請求的返回也會通過統(tǒng)一網(wǎng)關(guān)返回橡淑,在返回的響應header內(nèi)新增一個x-terminal-config字段,其value是一段字符串咆爽,由下劃線隔開梁棠,格式如:switch_namespace_version_randomtime置森,第一個字段switch=0/1,其中0表示此能力統(tǒng)一降級關(guān)閉符糊,1表示此能力打開凫海;第二個字段namespace表示命名空間,用于區(qū)分不同業(yè)務男娄; 第三個字段version就是配置信息的數(shù)據(jù)版本號行贪,按時間戳的形式標識版本號;第四個字段randomtime表示客戶端獲取到版本號變化差異后并非立刻請求模闲,會延遲[0,randomtime]之間的一個隨機時間后才發(fā)起請求建瘫,這個是為了降低瞬間尖峰流量的產(chǎn)生;
4尸折、客戶端網(wǎng)絡框架在客戶端會不間斷隨機廣播全局通知啰脚, 開關(guān)客戶端組件收到通知后,獲取到統(tǒng)一網(wǎng)關(guān)的返回數(shù)據(jù)实夹,解析網(wǎng)絡接口返回的header部分橄浓,獲取x-terminal-config字段,解析字段中的value亮航,如果是降級荸实,則結(jié)束,如果版本號沒有發(fā)生變化缴淋,則結(jié)束准给,如果非限流同時 switch=1,并且本地的緩存的開關(guān)version小于解析后的version宴猾,則根據(jù)randomtime隨機數(shù)發(fā)起客戶端請求圆存,獲取到配置數(shù)據(jù)后更新本地緩存。
技術(shù)優(yōu)化
在CMC 配置平臺的設計開發(fā)中仇哆,從實時性沦辙,性能,成本讹剔,穩(wěn)健等多維度進行了優(yōu)化油讯,具體的優(yōu)化措施如下:
- 考慮到實時性與機器成本的平衡,我們在CMS配置端做了聚合n秒后才將配置變更同步至統(tǒng)一網(wǎng)關(guān)延欠,主要為了防止多個用戶在很近的時間內(nèi)做了多個修改陌兑,會導致統(tǒng)一網(wǎng)關(guān)側(cè)頻繁的接收到不同的版本號,進而引起客戶端頻繁的發(fā)起請求由捎,導致配置信息服務端的流量陡增兔综,目前的經(jīng)驗值是n=5秒。
- 考慮性能與機器成本的平衡,客戶端會根據(jù)randomtime來隨機發(fā)起請求软驰,是為了打散請求發(fā)起時機涧窒,實際經(jīng)驗我們發(fā)現(xiàn)5s會增日常2倍左右的QPS,10s會增加日常1.5倍左右锭亏,實際各個場景可以根據(jù)自身的服務器機器數(shù)量與成本來動態(tài)決定選擇設置多長時間纠吴。
- 為了保障在大促或者特殊促銷場景下的穩(wěn)定性和健壯性,我們在配置信息產(chǎn)生后慧瘤,首先寫入數(shù)據(jù)到服務器的內(nèi)存里戴已,這樣每次客戶端的請求就直接讀取內(nèi)存性能很高,另外也會寫入一份json數(shù)據(jù)到CDN锅减,當服務端出問題后或在大促主動降級后可以通過CDN來兜底糖儡。