小程序前端刷新頁面,訪問服務(wù)端獲得取餐碼,然后用戶可以根據(jù)取餐碼到門店取餐或等待外賣。
高可用措施改造
我在前面也介紹了,這次活動(dòng)的促銷力度很大,高峰期流量將達(dá)到平時(shí)的數(shù)十倍,這就要求系統(tǒng)能夠在高并發(fā)的場景下,保證高可用性
所以,基于訪問量、日訂單量和可用性的指標(biāo),我們對(duì)原有系統(tǒng)進(jìn)行了一系列改造,最終順利地實(shí)現(xiàn)了首日 500 萬訂單,以及在大促期間,系統(tǒng) 4 個(gè) 9 的可用性目標(biāo)。這個(gè) 500 萬的訂單量,也創(chuàng)造了中國單商戶線上交易的歷史記錄。
在下面的系統(tǒng)架構(gòu)圖中,我標(biāo)出了具體的改造點(diǎn),主要有 10 處,接下來我就給你分別具體介紹一下,你可以通過這些具體的改造措施,來真正理解高可用系統(tǒng)的設(shè)計(jì)手段。
前端接入改造
這里的前端有兩個(gè),C 端的小程序和 B 端的門店收銀系統(tǒng)。前端部分主要是對(duì)三個(gè)點(diǎn)進(jìn)行改造,包括小程序端的 CDN 優(yōu)化、Nginx 負(fù)載均衡,以及收銀端的通信線路備份。
小程序端的 CDN 優(yōu)化
用戶點(diǎn)餐前,需要先瀏覽商品和菜單,這個(gè)用戶請(qǐng)求的頻率很高,數(shù)據(jù)流量大,會(huì)對(duì)服務(wù)端造成很大的壓力。所以,針對(duì)這一點(diǎn),我們通過 CDN 供應(yīng)商,在全國各地構(gòu)建了多個(gè) CDN 中心,儲(chǔ)存靜態(tài)的商品數(shù)據(jù),特別是圖片,這樣小程序前端可以就近訪問 CDN,流量無需通過小程序服務(wù)端,緩解了服務(wù)端的壓力。
Nginx 負(fù)載均衡
這個(gè)小程序點(diǎn)餐平臺(tái),之前是直接利用云服務(wù)商提供的 LB,它只有簡單的負(fù)載均衡能力。為了能應(yīng)對(duì)這次的高并發(fā)流量,現(xiàn)在我們獨(dú)立搭建了數(shù)十臺(tái)的 Nginx 集群,集群除了負(fù)載均衡,還提供限流支持,如果 QPS 總數(shù)超過了 10 萬,前端的訪問請(qǐng)求將會(huì)被丟棄掉。
另外,Nginx 在這里還有一個(gè)好處,就是可以實(shí)時(shí)提供每個(gè)接口的訪問頻率和網(wǎng)絡(luò)帶寬占用情況,能夠起到很好的接入層監(jiān)控功能
補(bǔ)充說明:一臺(tái) Nginx 一般可以支持?jǐn)?shù)萬的并發(fā),本來這里無需這么多臺(tái) Nginx,這是因?yàn)樵品?wù)商對(duì)單個(gè) LB 的接入有網(wǎng)絡(luò)帶寬的限制,所以我們要通過提升 Nginx 的數(shù)量,來保證接入有足夠的帶寬。
收銀端的通信線路備份
門店的收銀系統(tǒng)會(huì)通過前置代理服務(wù)器,來訪問云端的 OMS 系統(tǒng),這個(gè)代理服務(wù)器部署在商戶自己的 IDC 機(jī)房,原來只通過電信線路和云端機(jī)房打通。在這次改造中,我們?cè)黾恿艘苿?dòng)線路,這樣當(dāng)電信主線路出問題時(shí),系統(tǒng)就可以快速地切換到移動(dòng)線路。
應(yīng)用和服務(wù)的水平擴(kuò)展
首先,針對(duì)小程序服務(wù)端的部署,我們把實(shí)例數(shù)從十幾臺(tái)提升到了 100 臺(tái),水平擴(kuò)展它的處理能力。在上面的架構(gòu)圖中,你可以看到,小程序服務(wù)端依賴了 7 個(gè)基礎(chǔ)服務(wù),每個(gè)基礎(chǔ)服務(wù)也做了相應(yīng)的水平擴(kuò)展,由于應(yīng)用和基礎(chǔ)服務(wù)都是無狀態(tài)的,因此我們很容易擴(kuò)充。
這里的基礎(chǔ)服務(wù)是 Java 開發(fā)的,原來是用虛擬機(jī)方式部署的,現(xiàn)在我們把基礎(chǔ)服務(wù)全部遷移到了容器環(huán)境,這樣在提升資源利用率的同時(shí),也更好地支持了基礎(chǔ)服務(wù)的彈性擴(kuò)容。
訂單水平分庫
在大促情況下,下單高峰期,訂單主庫的寫訪問頻率很高,一個(gè)訂單會(huì)對(duì)應(yīng) 6~7 次的寫操作,包括了創(chuàng)建新訂單和訂單狀態(tài)變更;訂單的讀操作,我們之前通過一主多從部署和讀寫分離,已經(jīng)得到了支持。
但負(fù)責(zé)寫入的主庫只有一個(gè)實(shí)例,所以這次我們通過訂單的水平分庫,擴(kuò)充了訂單主庫的實(shí)例數(shù),改造后,我們有 4 個(gè)主庫來負(fù)責(zé)訂單數(shù)據(jù)寫入。數(shù)據(jù)庫的配置,也從原來的 8 核 16G 提升到了 16 核 32G,這樣我們通過硬件的垂直擴(kuò)展,進(jìn)一步提升了數(shù)據(jù)庫的處理能力。
這里的訂單水平分庫在實(shí)現(xiàn)上比較簡單,我們是通過訂單 ID 取模進(jìn)行分庫,基于進(jìn)程內(nèi)的 -JDBC 技術(shù),實(shí)現(xiàn)了數(shù)據(jù)庫的自動(dòng)路由。后面的課程中,我會(huì)專門介紹電商平臺(tái)的訂單水平分庫,它會(huì)更加復(fù)雜,到時(shí)你可以做個(gè)比較,如果有需要的話,也可以在實(shí)際項(xiàng)目參考落地。
異步化處理
你可以看到,在前臺(tái)訂單中心和后臺(tái) OMS 之間,我們需要同步訂單數(shù)據(jù),所以這兩者是緊密耦合的。不過這里,我們通過消息系統(tǒng)對(duì)它們進(jìn)行了解耦。 一方面,前臺(tái)下單要求比較快,后臺(tái) OMS 的訂單處理能力比較弱(OMS 庫沒有進(jìn)行水平分庫),通過消息的異步化處理,我們實(shí)現(xiàn)了對(duì)訂單流量的削峰;另一方面,如果 OMS 有問題,以異步的方式進(jìn)行數(shù)據(jù)同步,也不會(huì)影響前臺(tái)用戶下單。
還有在小程序服務(wù)端,在用戶支付完成或者后臺(tái)生成取餐碼后,我們會(huì)以微信消息的方式通知用戶,這個(gè)在代碼中,也是通過異步方式實(shí)現(xiàn)的,如果微信消息發(fā)送不成功,用戶還是可以在小程序上看到相關(guān)信息,不影響用戶取餐。
主動(dòng)通知,避免輪詢
在原來的架構(gòu)中,前臺(tái)小程序是通過輪詢服務(wù)端的方式,來獲取取餐碼;同樣,商戶的收銀系統(tǒng)也是通過輪詢 OMS 系統(tǒng)拉取新訂單,這樣的收銀系統(tǒng)有上萬個(gè),每隔 10s 就會(huì)拉取一次。這種盲目輪詢的方式,不但效率低,而且會(huì)對(duì)服務(wù)端造成很大的壓力。
經(jīng)過改造后,我們落地了消息推送中心,收銀系統(tǒng)通過 Socket 方式,和推送中心保持長連接。當(dāng) OMS 系統(tǒng)接收到前臺(tái)的新訂單后,會(huì)發(fā)送消息到消息推送中心;然后,收銀系統(tǒng)就可以實(shí)時(shí)地獲取新訂單的消息,再訪問 OMS 系統(tǒng)拉取新訂單。為了避免因消息推送中心出問題(比如消息中心掛掉了),導(dǎo)致收銀系統(tǒng)拿不到新訂單,收銀系統(tǒng)還保持對(duì) OMS 系統(tǒng)的輪詢,但頻率降低到了 1 分鐘一次。
同理,小程序前端會(huì)通過 Web Socket 方式,和消息推送中心保持長連接。當(dāng) OMS 系統(tǒng)在接收到收銀系統(tǒng)的取餐碼后,會(huì)發(fā)送消息到消息推送中心。這樣,小程序前端可以及時(shí)地獲取取餐碼信息。
緩存的使用
我們知道,緩存是提升性能十分有效的工具。這里的改造,就有兩個(gè)地方使用了緩存。
一體化監(jiān)控
在前面各個(gè)節(jié)點(diǎn)可用性優(yōu)化的基礎(chǔ)上,我們也在系統(tǒng)的監(jiān)控方面做了很多強(qiáng)化。除了常規(guī)的 Zabbix 做系統(tǒng)監(jiān)控、CAT 做應(yīng)用監(jiān)控、拉訂單曲線做業(yè)務(wù)監(jiān)控以外,我們還對(duì)系統(tǒng)實(shí)現(xiàn)了一體化的監(jiān)控。
在這里,所有的節(jié)點(diǎn)都在一個(gè)頁面里顯示,包括 Web 應(yīng)用、Redis、MQ 和數(shù)據(jù)庫,頁面也會(huì)體現(xiàn)節(jié)點(diǎn)之間的上下游關(guān)系。我們通過采集節(jié)點(diǎn)的狀態(tài)數(shù)據(jù),實(shí)時(shí)監(jiān)測每個(gè)節(jié)點(diǎn)的健康程度,并且用紅黃綠三種顏色,表示每個(gè)節(jié)點(diǎn)的健康狀況。這樣,我們就可以非常直觀地識(shí)別出,當(dāng)前的哪些節(jié)點(diǎn)有問題。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。