作者簡介:叢磊 白山合伙人兼工程副總裁 叢磊先生2016年加入白山,主要負責云鏈體系的設(shè)計與落實等工作。 叢磊先生2006年至2015年就職于新浪,原SAE(SinaAppEngine)創(chuàng)始人,曾任總負責人兼首席架構(gòu)師,2010年起,帶領(lǐng)新浪云計算團隊從事云相關(guān)領(lǐng)域的技術(shù)研發(fā)工作。(注:SAE是國內(nèi)最大的公有云PaaS平臺,擁有70萬用戶。) 叢磊先生擁有兩項發(fā)明專利,現(xiàn)任工信部可信云服務(wù)認證評委。
一天清晨,我被一個客戶電話驚醒,客戶異常焦急,尋問CDN能不能幫助他們解決“秒殺”的問題,他們昨天剛剛進行了“整點秒殺活動”,結(jié)果并發(fā)量過大,導致服務(wù)宕機,用戶投訴。 為了理清思路,我問了對方三個問題: (1)服務(wù)宕機的表現(xiàn)是什么? (2)業(yè)務(wù)的基本架構(gòu)什么樣? (3)秒殺的峰值并發(fā)到多少? 順著這些線索,我們先一起還原了應(yīng)用場景:
1.png (38.53 KB, 下載次數(shù): 172)
下載附件
某電商業(yè)務(wù)架構(gòu)圖
2017-03-24 20:38 上傳
該公司是一家P2P理財網(wǎng)站,常有用戶在整點搶購高利率理財產(chǎn)品的“整點秒殺活動”。如上圖所示,終端用戶請求先通過前端負載均衡,然后到達運行實際電商邏輯的Web Server;再下層是運行在VM上的8臺Redis,負責存儲與業(yè)務(wù)相關(guān)的Cache數(shù)據(jù),如用戶Profile、理財產(chǎn)品信息、用戶賬單信息等。實際落地數(shù)據(jù)存儲在MySQL中,該MySQL只進行了簡單的分庫分表及讀寫分離。 進行“秒殺”時,先由風控和運營人員選好理財產(chǎn)品,然后標記到數(shù)據(jù)庫中;活動開始由產(chǎn)品人員放開,終端用戶搶購。 該公司的業(yè)務(wù)主要來自移動端,平時流量較少,但“秒殺”活動時會瞬間產(chǎn)生大量流量,峰值并發(fā)達到10萬以上(其中可能包括bot),如此大的并發(fā)主要是集中在以下兩類接口: - 對于理財產(chǎn)品的刷新接口,類似GET /get_fprod.php?uid={$1}&pid={$2}&sid={$3},此類接口的請求量最多,占比90%。 - 對于理財產(chǎn)品的下單接口,類似 GET /order_fprod?uid={$1}&pid={$2}&oid={$3}&sid={$4},此類接口的請求量較少,占比不到1%,但存在大量504超時。 其中uid是用戶ID,pid是理財產(chǎn)品ID,oid是訂單號,sid是隨著客戶端用戶變化的隨機token標識。 場景解讀 根據(jù)與客戶溝通得到的場景,初步得到了以下結(jié)論:
(1)客戶以移動業(yè)務(wù)為主,產(chǎn)品通過API在客戶端渲染UI,產(chǎn)品中幾乎沒有靜態(tài)資源,帶寬流量不高,傳統(tǒng)CDN無法達到卸載壓力的作用; (2)秒殺時,產(chǎn)生大量502/504超時請求,說明此時用戶請求已超過服務(wù)端的業(yè)務(wù)承載能力,急需擴容。 基于以上兩點,我沒有建議該公司采購CDN服務(wù),而是推薦服務(wù)擴容,但隨著我方對于業(yè)務(wù)更深層次的分析,逐漸發(fā)現(xiàn)了一些詭異的事情。 “詭異”現(xiàn)象 (1)數(shù)據(jù)庫主從負載極不均衡,通過MySQL管理工具,發(fā)現(xiàn)主庫的Query量高達80%; (2)Redis Cache節(jié)點負載極不均衡,通過查看redis info發(fā)現(xiàn),秒殺時,其中一臺Redis請求量極大,占比達90%以上,其他Redis請求量卻很低。 上述反常現(xiàn)象激起了雙方技術(shù)人員的興趣,這也許就是問題的關(guān)鍵!隨著分析深入,第一個現(xiàn)象的原因浮出水面:該公司在使用數(shù)據(jù)庫時,并未如某些大型電商平臺一樣使用數(shù)據(jù)庫中間件層進行MySQL請求的路由分發(fā),而是在業(yè)務(wù)代碼端,使用語言層面的框架完成讀寫分離工作。這帶來了兩個弊端: - 程序員繞過語言層框架開發(fā),并未真正實施讀寫分離; - 產(chǎn)品人員要求展現(xiàn)效果實時,倒逼開發(fā)人員修改業(yè)務(wù)邏輯,會犧牲讀寫分離,使數(shù)據(jù)都在主庫讀寫。
2.png (35.97 KB, 下載次數(shù): 168)
下載附件
2017-03-24 20:39 上傳
接著,第二個現(xiàn)象的原因也逐漸清晰:秒殺時,大量用戶訪問極少數(shù)理財產(chǎn)品,當這幾個產(chǎn)品的pid恰好被hash到同一個Redis上,就會導致Cache節(jié)點熱點失衡,所有請求最終集中在一個Redis,而這個Redis就是業(yè)務(wù)的瓶頸! 對癥下藥 1. 使用數(shù)據(jù)庫中間件進行讀寫分離以及橫向擴展控制 使用數(shù)據(jù)庫中間件可以帶來諸多好處,其中最重要的是可對業(yè)務(wù)層隱藏部分數(shù)據(jù)庫細節(jié),更好地控制業(yè)務(wù)。當然,引入數(shù)據(jù)庫中間層也存在明顯缺點,在業(yè)務(wù)整體架構(gòu)中增加一層組件,違反了“簡單有效”的設(shè)計原則。對于很多互聯(lián)網(wǎng)公司,在早期甚至中期沒有數(shù)據(jù)庫中間層也很正常。 但當業(yè)務(wù)發(fā)展到一定階段,引入數(shù)據(jù)庫中間層是利大于弊的。 基于經(jīng)驗,我方推薦客戶使用MySQL Route,基本可以滿足簡單需求,如:連接復用;負載均衡;讀寫分離。
3.png (120.09 KB, 下載次數(shù): 174)
下載附件
2017-03-24 20:41 上傳
上圖是MySQL Router官方架構(gòu)圖,可以看到,MySQL Router優(yōu)勢在于插件化設(shè)計,官方提供了一系列插件供使用。 除MySQL Router,國內(nèi)還有很多開源數(shù)據(jù)庫中間件可以采用,如阿里、美團等。
使用數(shù)據(jù)庫中間層,不僅可以解決性能問題,還能在安全方面起到作用,如審計、流量限制等,甚至攔截SQL注入、劣質(zhì)SQL語句等。 2、使用API加速服務(wù)緩解服務(wù)端壓力 Cache服務(wù)失衡是比較棘手的問題。“秒殺”時,用戶高頻訪問少數(shù)幾個理財產(chǎn)品信息,當其Cache數(shù)據(jù)恰巧分配在同一節(jié)點,大量請求會瞬間集中到一臺或少數(shù)幾臺節(jié)點,這就是Cache服務(wù)失衡的本質(zhì)原因。不僅在電商“秒殺”場景中,其他有瞬間熱點訪問的業(yè)務(wù)類型也會存在這個問題。以微博為例,曾因明星熱點事件導致接口緩慢甚至服務(wù)宕機,歸根到底也是這個原因!氨稀钡乃查g,一個微博會在短時間內(nèi)海量傳播,該微博ID被同時打開,所有流量會集中到一個Redis節(jié)點。 這個問題如何解決?首先,Cache通常以某個數(shù)據(jù)結(jié)構(gòu)的key為維度進行hash存儲,大量用戶只訪問一個或幾個key時,將導致Redis Cache節(jié)點負載不均衡,這是否一定對服務(wù)產(chǎn)生影響,則視并發(fā)情況而定,但這是一個巨大隱患。針對這個問題,客戶提出了一種解決方案:把一個理財產(chǎn)品的Cache數(shù)據(jù)再拆散,1個key變成多個,降低key被分配到同一Cache節(jié)點的概率。但這種方法存在很大弊端: (1)需要修改代碼,原本一條get請求就可以完成的邏輯,要換成多條才能拼成;
(2)日常所有get/set操作的時間消耗都將成倍增加,因為1%的熱點事件增加99%常規(guī)操作的時間,嚴重違背二八法則。 基于以上問題,我們推薦客戶使用白山云聚合CLN-X的“API加速”來解決這個問題。 API加速 API加速完全不同于傳統(tǒng)CDN的鏈路加速,通過緩存API返回內(nèi)容并結(jié)合TCP廣域網(wǎng)優(yōu)化技術(shù),對API請求進行優(yōu)化。白山API加速將每個API的response數(shù)據(jù)毫秒級緩存在全網(wǎng)邊緣節(jié)點,節(jié)點內(nèi)存中的response數(shù)據(jù)以LRU(Least Recently Used)算法交換。在“熱點事件”時,最熱的信息持續(xù)保存在邊緣節(jié)點,當客戶端訪問該API時,邊緣節(jié)點可直接返回結(jié)果,不必返回源站。整個架構(gòu)如下:
4(2).png (48.89 KB, 下載次數(shù): 183)
下載附件
2017-03-24 20:41 上傳
API加速服務(wù)在網(wǎng)絡(luò)邊緣節(jié)點提供對API的加速能力,包括:API返回結(jié)果緩存能力、API請求回源網(wǎng)絡(luò)加速能力。 傳統(tǒng)觀點認為,動態(tài)資源(API)無法緩存,但白山提出“任何資源都可以被緩存,只是過期時間不同”。對于常見的靜態(tài)資源,緩存過期時間較長;而API并非不能被緩存,只是過期時間很短。如一個查詢股價的API,可設(shè)定過期時間為50毫秒;百米運動員起跑反應(yīng)時間為100-200毫秒,50毫秒對于PC端或移動端的用戶體驗并不會造成影響。 沒有緩存時,1秒內(nèi)如有10000個用戶同時訪問,后端承受10000個并發(fā);如果設(shè)置50毫秒的緩存時間,理論上可將后端并發(fā)降低到20個(1秒/50毫秒=20),后端負載降低至五百分之一,其他請求由緩存服務(wù)器直接返回給用戶。 綜上所述,白山API加速為客戶提供毫秒級緩存,在不影響用戶體驗的前提下提高終端用戶響應(yīng)速度,同時降低服務(wù)端的業(yè)務(wù)負載壓力。 API加速還支持自定義緩存規(guī)則,使其更貼近業(yè)務(wù),包括QueryString、Header、Path三種類型,針對場景,設(shè)定如下規(guī)則: GET /get_fprod.php?uid={$1}&pid={$2}&sid={$3},每個理財產(chǎn)品都有獨立ID,產(chǎn)品信息不隨用戶ID和客戶端隨機信息變化,因此Cache key可忽略URI中參數(shù)的{$1}和{$3},/get_fprod.php?pid={$2}就是在邊緣節(jié)點存儲毫秒級的Cache key。 緩存的過期時間如何確定呢?與業(yè)務(wù)相關(guān),這需要對客戶提供的脫敏日志進行分析,可初步設(shè)定過期時間為500毫秒,最后還需考慮RTT修正值,以適應(yīng)廣域網(wǎng)環(huán)境;RTT則由API加速服務(wù)自動捕捉并實時更新。 實際效果 通過為客戶主要的瓶頸接口配置API加速服務(wù),并在峰值時間,從以下兩個維度對比API加速服務(wù)開啟與關(guān)閉時的效果: - 終端用戶請求平均響應(yīng)時間和響應(yīng)碼200比例 - 服務(wù)集群平均負載 最終效果如下:
5.png (97.6 KB, 下載次數(shù): 179)
下載附件
2017-03-24 20:42 上傳
6.png (88.57 KB, 下載次數(shù): 161)
下載附件
2017-03-24 20:42 上傳
7.png (83.77 KB, 下載次數(shù): 169)
下載附件
2017-03-24 20:42 上傳
如圖A所示,峰值期間終端用戶請求平均響應(yīng)時間,從3秒左右壓縮至40毫秒以內(nèi);如圖B所示,峰值期間所有請求響應(yīng)碼200的比例從70%左右提升至100%;圖C表示,峰值期間,后端CPU Idle從10%左右提高至97%左右。實測對比數(shù)據(jù)表明,API加速對降低平均響應(yīng)時間、提升用戶體驗效果十分顯著,在降低后端服務(wù)器負載方面效果更加明顯,使用API加速的后端CPU Idle可保持在91%以上。 后續(xù)建議 數(shù)據(jù)庫失衡和緩存Redis失衡問題已經(jīng)解決,但除上述問題,還有很多環(huán)節(jié)可以改善: 1、隊列服務(wù)異步化請求 目前客戶最終落地數(shù)據(jù)庫請求直接請求到MySQL,未經(jīng)隊列緩沖,建議使用隊列服務(wù)排隊處理峰值請求,其好處在于能在大訪問量時對請求進行調(diào)度,并可控制實際到達數(shù)據(jù)庫的并發(fā),從而有效保護數(shù)據(jù)庫后端。 2、API防火墻屏蔽惡意Bot 用戶日志中含有大量明顯且規(guī)律的掃描軟件痕跡,如sqlmap、fimap等,雖然尚未對業(yè)務(wù)造成較大影響,但卻使服務(wù)端資源被占用。建議在負載均衡最前端對掃描行為予以屏蔽,以提高安全性,同時提升服務(wù)效率。除惡意Bot,搶單、刷單等行為也會對服務(wù)產(chǎn)生影響,建議使用API防護服務(wù)識別與攔截。 3、產(chǎn)品層考慮服務(wù)降級設(shè)計 該客戶在整體業(yè)務(wù)上,沒有服務(wù)降級設(shè)計,產(chǎn)品功能優(yōu)先級未做劃分,導致重要的數(shù)據(jù)庫、Cache等眾多基礎(chǔ)服務(wù)混雜。一旦“秒殺”導致數(shù)據(jù)庫穿透等嚴重問題時,整體服務(wù)將不可用。這種情況應(yīng)重新梳理業(yè)務(wù)單元,按照優(yōu)先級切分基礎(chǔ)服務(wù),首屏、產(chǎn)品列表、購買、訂單等信息優(yōu)先級最高;其次是非重要功能,如評論、賬單等;如果后端負載較大,必要時可直接舍棄次要功能,從而降低后端負載,保證服務(wù)穩(wěn)定。 總結(jié) 解決類似“整點秒殺活動”的情景,是一個系統(tǒng)復雜的工程,就文中客戶暴露出來的數(shù)據(jù)庫負載不均勻、Cache緩存負載不均勻等問題,可通過采用數(shù)據(jù)庫中間層和API加速等技術(shù)解決,最終可取得理想效果。 上述“秒殺”案例,只是API加速的一個典型應(yīng)用場景,接下來我還會撰文對API加速問題進行更為系統(tǒng)的剖析。也歡迎業(yè)界同仁通過微信后臺(baishancloud)與我們?nèi)〉寐?lián)系,一起探討API相關(guān)話題。
|