【轉(zhuǎn)載】扛住100億次請(qǐng)求?我們來試一試

1. 前言

前幾天,偶然看到了 《扛住100億次請(qǐng)求——如何做一個(gè)“有把握”的春晚紅包系統(tǒng)”》(url)一文,看完以后,感慨良多,收益很多。正所謂他山之石,可以攻玉,雖然此文發(fā)表于2015年,我看到時(shí)已經(jīng)是2016年末,但是其中的思想仍然是可以為很多后端設(shè)計(jì)借鑒,。同時(shí)作為一個(gè)工程師,看完以后又會(huì)思考,學(xué)習(xí)了這樣的文章以后,是否能給自己的工作帶來一些實(shí)際的經(jīng)驗(yàn)?zāi)兀克^紙上得來終覺淺,絕知此事要躬行,能否自己實(shí)踐一下100億次紅包請(qǐng)求呢?否則讀完以后腦子里能剩下的東西 不過就是100億 1400萬QPS整流 這樣的字眼,剩下的文章將展示作者是如何以此過程為目標(biāo),在本地環(huán)境的模擬了此過程。

實(shí)現(xiàn)的目標(biāo): 單機(jī)支持100萬連接,模擬了搖紅包和發(fā)紅包過程,單機(jī)峰值QPS 6萬,平穩(wěn)支持了業(yè)務(wù)。

注:本文以及作者所有內(nèi)容,僅代表個(gè)人理解和實(shí)踐,過程和微信團(tuán)隊(duì)沒有任何關(guān)系,真正的線上系統(tǒng)也不同,只是從一些技術(shù)點(diǎn)進(jìn)行了實(shí)踐,請(qǐng)讀者進(jìn)行區(qū)分。因作者水平有限,有任何問題都是作者的責(zé)任,有問題請(qǐng)聯(lián)系 ppmsn2005#gmail.com. 全文內(nèi)容 扛住100億次請(qǐng)求?我們來試一試

2. 背景知識(shí)

QPS: Queries per second 每秒的請(qǐng)求數(shù)目

PPS:Packets per second 每秒數(shù)據(jù)包數(shù)目

搖紅包:客戶端發(fā)出一個(gè)搖紅包的請(qǐng)求,如果系統(tǒng)有紅包就會(huì)返回,用戶獲得紅包

發(fā)紅包:產(chǎn)生一個(gè)紅包里面含有一定金額,紅包指定數(shù)個(gè)用戶,每個(gè)用戶會(huì)收到紅包信息,用戶可以發(fā)送拆紅包的請(qǐng)求,獲取其中的部分金額。

3. 確定目標(biāo)

在一切系統(tǒng)開始以前,我們應(yīng)該搞清楚我們的系統(tǒng)在完成以后,應(yīng)該有一個(gè)什么樣的負(fù)載能力。

3.1 用戶總數(shù):

通過文章我們可以了解到接入服務(wù)器638臺(tái), 服務(wù)上限大概是14.3億用戶, 所以單機(jī)負(fù)載的用戶上限大概是14.3億/638臺(tái)=228萬用戶/臺(tái)。但是目前中國肯定不會(huì)有14億用戶同時(shí)在線,參考 http://qiye.qianzhan.com/show/detail/160818-b8d1c700.html 的說法,2016年Q2 微信用戶大概是8億,月活在5.4 億左右。所以在2015年春節(jié)期間,雖然使用的用戶會(huì)很多,但是同時(shí)在線肯定不到5.4億。

3.2. 服務(wù)器數(shù)量:

一共有638臺(tái)服務(wù)器,按照正常運(yùn)維設(shè)計(jì),我相信所有服務(wù)器不會(huì)完全上線,會(huì)有一定的硬件冗余,來防止突發(fā)硬件故障。假設(shè)一共有600臺(tái)接入服務(wù)器。

3.3 單機(jī)需要支持的負(fù)載數(shù):

每臺(tái)服務(wù)器支持的用戶數(shù):5.4億/600 = 90萬。也就是平均單機(jī)支持90萬用戶。如果真實(shí)情況比90萬更多,則模擬的情況可能會(huì)有偏差,但是我認(rèn)為QPS在這個(gè)實(shí)驗(yàn)中更重要。

3.4. 單機(jī)峰值QPS:

文章中明確表示為1400萬QPS.這個(gè)數(shù)值是非常高的,但是因?yàn)橛?00臺(tái)服務(wù)器存在,所以單機(jī)的QPS為 1400萬/600= 約為2.3萬QPS, 文章曾經(jīng)提及系統(tǒng)可以支持4000萬QPS,那么系統(tǒng)的QPS 至少要到4000萬/600 = 約為 6.6萬, 這個(gè)數(shù)值大約是目前的3倍,短期來看并不會(huì)被觸及。但是我相信應(yīng)該做過相應(yīng)的壓力測(cè)試。

3.5. 發(fā)放紅包:

文中提到系統(tǒng)以5萬個(gè)每秒的下發(fā)速度,那么單機(jī)每秒下發(fā)速度50000/600 =83個(gè)/秒,也就是單機(jī)系統(tǒng)應(yīng)該保證每秒以83個(gè)的速度下發(fā)即可。
??最后考慮到系統(tǒng)的真實(shí)性,還至少有用戶登錄的動(dòng)作,拿紅包這樣的業(yè)務(wù)。真實(shí)的系統(tǒng)還會(huì)包括聊天這樣的服務(wù)業(yè)務(wù)。

最后整體的看一下 100億次搖紅包這個(gè)需求,假設(shè)它是均勻地發(fā)生在春節(jié)聯(lián)歡晚會(huì)的4個(gè)小時(shí)里,那么服務(wù)器的QPS 應(yīng)該是10000000000/600/3600/4.0=1157. 也就是單機(jī)每秒1000多次,這個(gè)數(shù)值其實(shí)并不高。如果完全由峰值速度1400萬消化 10000000000/(1400*10000) = 714秒,也就是說只需要峰值堅(jiān)持11分鐘,就可以完成所有的請(qǐng)求。可見互聯(lián)網(wǎng)產(chǎn)品的一個(gè)特點(diǎn)就是峰值非常高,持續(xù)時(shí)間并不會(huì)很長。

總結(jié):

從單臺(tái)服務(wù)器看.它需要滿足下面一些條件
??1. 支持至少100萬連接用戶
??2. 每秒至少能處理2.3萬的QPS,這里我們把目標(biāo)定得更高一些 分別設(shè)定到了3萬和6萬。
??3. 搖紅包:支持每秒83個(gè)的速度下發(fā)放紅包,也就是說每秒有2.3萬次搖紅包的請(qǐng)求,其中83個(gè)請(qǐng)求能搖到紅包,其余的2.29萬次請(qǐng)求會(huì)知道自己沒搖到。當(dāng)然客戶端在收到紅包以后,也需要確保客戶端和服務(wù)器兩邊的紅包數(shù)目和紅包內(nèi)的金額要一致。因?yàn)闆]有支付模塊,所以我們也把要求提高一倍,達(dá)到200個(gè)紅包每秒的分發(fā)速度
??4. 支持用戶之間發(fā)紅包業(yè)務(wù),確保收發(fā)兩邊的紅包數(shù)目和紅包內(nèi)金額要一致。同樣也設(shè)定200個(gè)紅包每秒的分發(fā)速度為我們的目標(biāo)。

想完整模擬整個(gè)系統(tǒng)實(shí)在太難了,首先需要海量的服務(wù)器,其次需要上億的模擬客戶端。這對(duì)我來說是辦不到,但是有一點(diǎn)可以確定,整個(gè)系統(tǒng)是可以水平擴(kuò)展的,所以我們可以模擬100萬客戶端,在模擬一臺(tái)服務(wù)器 那么就完成了1/600的模擬。

和現(xiàn)有系統(tǒng)區(qū)別:
??和大部分高QPS測(cè)試的不同,本系統(tǒng)的側(cè)重點(diǎn)有所不同。我對(duì)2者做了一些對(duì)比。

|
| 常見高QPS系統(tǒng)壓力測(cè)試 | 本系統(tǒng)壓力測(cè)試 |
| :-: | :-: | :-: |
| 連接數(shù) | 一般<1000 (幾百以內(nèi)) | 1000000 (1百萬) |
| 單連接吞吐量 | 非常大 每個(gè)連接幾十M字節(jié)吞吐 | 非常小 每個(gè)連接每次幾十個(gè)字節(jié) |
| 需要的IO次數(shù) | 不多 | 非常多 |

4. 基礎(chǔ)軟件和硬件

4.1軟件:

Golang 1.8r3 , shell, python (開發(fā)沒有使用c++ 而是使用了golang, 是因?yàn)槭褂胓olang 的最初原型達(dá)到了系統(tǒng)要求。雖然golang 還存在一定的問題,但是和開發(fā)效率比,這點(diǎn)損失可以接受)
??服務(wù)器操作系統(tǒng):
??Ubuntu 12.04
??客戶端操作系統(tǒng):
??debian 5.0

4.2硬件環(huán)境 ??服務(wù)端: dell R2950。 8核物理機(jī),非獨(dú)占有其他業(yè)務(wù)在工作,16G內(nèi)存。這臺(tái)硬件大概是7年前的產(chǎn)品,性能應(yīng)該不是很高要求。

服務(wù)器硬件版本:


image

服務(wù)器CPU信息:


image

客戶端: esxi 5.0 虛擬機(jī),配置為4核 5G內(nèi)存。一共17臺(tái),每臺(tái)和服務(wù)器建立6萬個(gè)連接。完成100萬客戶端模擬

5. 技術(shù)分析和實(shí)現(xiàn)

5.1) 單機(jī)實(shí)現(xiàn)100萬用戶連接 ??這一點(diǎn)來說相對(duì)簡(jiǎn)單,筆者在幾年前就早完成了單機(jī)百萬用戶的開發(fā)以及操作。現(xiàn)代的服務(wù)器都可以支持百萬用戶。相關(guān)內(nèi)容可以查看 ??github代碼以及相關(guān)文檔。

https://github.com/xiaojiaqi/C1000kPracticeGuide
??系統(tǒng)配置以及優(yōu)化文檔:
https://github.com/xiaojiaqi/C1000kPracticeGuide/tree/master/docs/cn

5.2) 3萬QPS

這個(gè)問題需要分2個(gè)部分來看客戶端方面和服務(wù)器方面。

客戶端QPS

因?yàn)橛?00萬連接連在服務(wù)器上,QPS為3萬。這就意味著每個(gè)連接每33秒,就需要向服務(wù)器發(fā)一個(gè)搖紅包的請(qǐng)求。因?yàn)閱蜪P可以建立的連接數(shù)為6萬左右, 有17臺(tái)服務(wù)器同時(shí)模擬客戶端行為。我們要做的就保證在每一秒都有這么多的請(qǐng)求發(fā)往服務(wù)器即可。
其中技術(shù)要點(diǎn)就是客戶端協(xié)同。但是各個(gè)客戶端的啟動(dòng)時(shí)間,建立連接的時(shí)間都不一致,還存在網(wǎng)絡(luò)斷開重連這樣的情況,各個(gè)客戶端如何判斷何時(shí)自己需要發(fā)送請(qǐng)求,各自該發(fā)送多少請(qǐng)求呢?

我是這樣解決的:利用NTP服務(wù),同步所有的服務(wù)器時(shí)間,客戶端利用時(shí)間戳來判斷自己的此時(shí)需要發(fā)送多少請(qǐng)求。
??算法很容易實(shí)現(xiàn):
??假設(shè)有100萬用戶,則用戶id 為0-999999.要求的QPS為5萬, 客戶端得知QPS為5萬,總用戶數(shù)為100萬,它計(jì)算 100萬/5萬=20,所有的用戶應(yīng)該分為20組,如果 time() % 20 == 用戶id % 20,那么這個(gè)id的用戶就該在這一秒發(fā)出請(qǐng)求,如此實(shí)現(xiàn)了多客戶端協(xié)同工作。每個(gè)客戶端只需要知道 總用戶數(shù)和QPS 就能自行準(zhǔn)確發(fā)出請(qǐng)求了。
(擴(kuò)展思考:如果QPS是3萬 這樣不能被整除的數(shù)目,該如何辦?如何保證每臺(tái)客戶端發(fā)出的請(qǐng)求數(shù)目盡量的均衡呢?)

服務(wù)器QPS ??服務(wù)器端的QPS相對(duì)簡(jiǎn)單,它只需要處理客戶端的請(qǐng)求即可。但是為了客觀了解處理情況,我們還需要做2件事情。

第一: 需要記錄每秒處理的請(qǐng)求數(shù)目,這需要在代碼里埋入計(jì)數(shù)器。
??第二: 我們需要監(jiān)控網(wǎng)絡(luò),因?yàn)榫W(wǎng)絡(luò)的吞吐情況,可以客觀的反映出QPS的真實(shí)數(shù)據(jù)。為此,我利用python腳本 結(jié)合ethtool 工具編寫了一個(gè)簡(jiǎn)單的工具,通過它我們可以直觀的監(jiān)視到網(wǎng)絡(luò)的數(shù)據(jù)包通過情況如何。它可以客觀的顯示出我們的網(wǎng)絡(luò)有如此多的數(shù)據(jù)傳輸在發(fā)生。

工具截圖:
image

5.3) 搖紅包業(yè)務(wù)

搖紅包的業(yè)務(wù)非常簡(jiǎn)單,首先服務(wù)器按照一定的速度生產(chǎn)紅包。紅包沒有被取走的話,就堆積在里面。服務(wù)器接收一個(gè)客戶端的請(qǐng)求,如果服務(wù)器里現(xiàn)在有紅包就會(huì)告訴客戶端有,否則就提示沒有紅包。
??因?yàn)閱螜C(jī)每秒有3萬的請(qǐng)求,所以大部分的請(qǐng)求會(huì)失敗。只需要處理好鎖的問題即可。
??我為了減少競(jìng)爭(zhēng),將所有的用戶分在了不同的桶里。這樣可以減少對(duì)鎖的競(jìng)爭(zhēng)。如果以后還有更高的性能要求,還可以使用 高性能隊(duì)列——Disruptor來進(jìn)一步提高性能。

注意,在我的測(cè)試環(huán)境里是缺少支付這個(gè)核心服務(wù)的,所以實(shí)現(xiàn)的難度是大大的減輕了。另外提供一組數(shù)字:2016年淘寶的雙11的交易峰值僅僅為12萬/秒,微信紅包分發(fā)速度是5萬/秒,要做到這點(diǎn)是非常困難的。(http://mt.sohu.com/20161111/n472951708.shtml

5.4) 發(fā)紅包業(yè)務(wù) ??發(fā)紅包的業(yè)務(wù)很簡(jiǎn)單,系統(tǒng)隨機(jī)產(chǎn)生一些紅包,并且隨機(jī)選擇一些用戶,系統(tǒng)向這些用戶提示有紅包。這些用戶只需要發(fā)出拆紅包的請(qǐng)求,系統(tǒng)就可以隨機(jī)從紅包中拆分出部分金額,分給用戶,完成這個(gè)業(yè)務(wù)。同樣這里也沒有支付這個(gè)核心服務(wù)。

5.5)監(jiān)控

最后 我們需要一套監(jiān)控系統(tǒng)來了解系統(tǒng)的狀況,我借用了我另一個(gè)項(xiàng)目(https://github.com/xiaojiaqi/fakewechat) 里的部分代碼完成了這個(gè)監(jiān)控模塊,利用這個(gè)監(jiān)控,服務(wù)器和客戶端會(huì)把當(dāng)前的計(jì)數(shù)器內(nèi)容發(fā)往監(jiān)控,監(jiān)控需要把各個(gè)客戶端的數(shù)據(jù)做一個(gè)整合和展示。同時(shí)還會(huì)把日志記錄下來,給以后的分析提供原始數(shù)據(jù)。 線上系統(tǒng)更多使用opentsdb這樣的時(shí)序數(shù)據(jù)庫,這里資源有限,所以用了一個(gè)原始的方案

監(jiān)控顯示日志大概這樣


image

6. 代碼實(shí)現(xiàn)及分析

在代碼方面,使用到的技巧實(shí)在不多,主要是設(shè)計(jì)思想和golang本身的一些問題需要考慮。
首先golang的goroutine 的數(shù)目控制,因?yàn)橹辽儆?00萬以上的連接,所以按照普通的設(shè)計(jì)方案,至少需要200萬或者300萬的goroutine在工作。這會(huì)造成系統(tǒng)本身的負(fù)擔(dān)很重。
其次就是100萬個(gè)連接的管理,無論是連接還是業(yè)務(wù)都會(huì)造成一些心智的負(fù)擔(dān)。
我的設(shè)計(jì)是這樣的:

image

首先將100萬連接分成多個(gè)不同的SET,每個(gè)SET是一個(gè)獨(dú)立,平行的對(duì)象。每個(gè)SET 只管理幾千個(gè)連接,如果單個(gè)SET 工作正常,我只需要添加SET就能提高系統(tǒng)處理能力。按照SET分還有一個(gè)好處,可以將一個(gè)SET作為一個(gè)業(yè)務(wù)單元,在不同性能服務(wù)器上可以負(fù)載不同的壓力,比如8核機(jī)器管理10個(gè)SET,4核機(jī)器管理5個(gè)SET 可以細(xì)粒度的分流壓力,并容易遷移處理
??其次謹(jǐn)慎的設(shè)計(jì)了每個(gè)SET里數(shù)據(jù)結(jié)構(gòu)的大小,保證每個(gè)SET的壓力不會(huì)太大,不會(huì)出現(xiàn)消息的堆積。
??再次減少了gcroutine的數(shù)目,每個(gè)連接只使用一個(gè)goroutine,發(fā)送消息在一個(gè)SET里只有一個(gè)gcroutine負(fù)責(zé),這樣節(jié)省了100萬個(gè)goroutine。這樣整個(gè)系統(tǒng)只需要保留 100萬零幾百個(gè)gcroutine就能完成業(yè)務(wù)。大量的節(jié)省了cpu 和內(nèi)存
??系統(tǒng)的工作流程大概如下:
??每個(gè)客戶端連接成功后,系統(tǒng)會(huì)分配一個(gè)goroutine讀取客戶端的消息,當(dāng)消息讀取完成,將它轉(zhuǎn)化為消息對(duì)象放至在SET的接收消息隊(duì)列,然后返回獲取下一個(gè)消息
??在SET內(nèi)部,有一個(gè)工作goroutine,它只做非常簡(jiǎn)單而高效的事情,它做的事情如下,檢查SET的接受消息,它會(huì)收到3類消息

1, 客戶端的搖紅包請(qǐng)求消息

2, 客戶端的其他消息 比如聊天 好友這一類

3, 服務(wù)器端對(duì)客戶端消息的回應(yīng)

對(duì)于 第1種消息 客戶端的搖紅包請(qǐng)求消息 是這樣處理的,從客戶端拿到搖紅包請(qǐng)求消息,試圖從SET的紅包隊(duì)列里 獲取一個(gè)紅包,如果拿到了就把紅包信息 返回給客戶端,否則構(gòu)造一個(gè)沒有搖到的消息,返回給對(duì)應(yīng)的客戶端。
??對(duì)于第2種消息 客戶端的其他消息 比如聊天 好友這一類,只需簡(jiǎn)單地從隊(duì)列里拿走消息,轉(zhuǎn)發(fā)給后端的聊天服務(wù)隊(duì)列即可,其他服務(wù)會(huì)把消息轉(zhuǎn)發(fā)出去。
??對(duì)于第3種消息 服務(wù)器端對(duì)客戶端消息的回應(yīng)。SET 只需要根據(jù)消息里的用戶id,找到SET里保留的用戶連接對(duì)象,發(fā)回去就可以了。

對(duì)于紅包產(chǎn)生服務(wù),它的工作很簡(jiǎn)單,只需要按照順序在輪流在每個(gè)SET的紅包產(chǎn)生對(duì)列里放至紅包對(duì)象就可以了。這樣可以保證每個(gè)SET里都是公平的,其次它的工作強(qiáng)度很低,可以保證業(yè)務(wù)穩(wěn)定。

見代碼
https://github.com/xiaojiaqi/10billionhongbaos

7實(shí)踐

實(shí)踐的過程分為3個(gè)階段

階段1: 分別啟動(dòng)服務(wù)器端和監(jiān)控端,然后逐一啟動(dòng)17臺(tái)客戶端,讓它們建立起100萬的鏈接。在服務(wù)器端,利用ss 命令 統(tǒng)計(jì)出每個(gè)客戶端和服務(wù)器建立了多少連接。

命令如下:
Alias ss2=Ss –ant | grep 1025 | grep EST | awk –F: “{print $8}” | sort | uniq –c’

結(jié)果如下:
image

階段2: 利用客戶端的http接口,將所有的客戶端QPS 調(diào)整到3萬,讓客戶端發(fā)出3W QPS強(qiáng)度的請(qǐng)求。

運(yùn)行如下命令:


image

觀察網(wǎng)絡(luò)監(jiān)控和監(jiān)控端反饋,發(fā)現(xiàn)QPS 達(dá)到預(yù)期數(shù)據(jù)
網(wǎng)絡(luò)監(jiān)控截圖


image

在服務(wù)器端啟動(dòng)一個(gè)產(chǎn)生紅包的服務(wù),這個(gè)服務(wù)會(huì)以200個(gè)每秒的速度下發(fā)紅包,總共4萬個(gè)。此時(shí)觀察客戶端在監(jiān)控上的日志,會(huì)發(fā)現(xiàn)基本上以200個(gè)每秒的速度獲取到紅包。

![搖紅包] (https://raw.githubusercontent.com/xiaojiaqi/10billionhongbaos/master/images/yao.png)

等到所有紅包下發(fā)完成后,再啟動(dòng)一個(gè)發(fā)紅包的服務(wù),這個(gè)服務(wù)系統(tǒng)會(huì)生成2萬個(gè)紅包,每秒也是200個(gè),每個(gè)紅包隨機(jī)指定3位用戶,并向這3個(gè)用戶發(fā)出消息,客戶端會(huì)自動(dòng)來拿紅包,最后所有的紅包都被拿走。

image

階段3

利用客戶端的http接口,將所有的客戶端QPS 調(diào)整到6萬,讓客戶端發(fā)出6W QPS強(qiáng)度的請(qǐng)求。

image

如法炮制,在服務(wù)器端,啟動(dòng)一個(gè)產(chǎn)生紅包的服務(wù),這個(gè)服務(wù)會(huì)以200個(gè)每秒的速度下發(fā)紅包??偣?萬個(gè)。此時(shí)觀察客戶端在監(jiān)控上的日志,會(huì)發(fā)現(xiàn)基本上以200個(gè)每秒的速度獲取到紅包。
等到所有紅包下發(fā)完成后,再啟動(dòng)一個(gè)發(fā)紅包的服務(wù),這個(gè)服務(wù)系統(tǒng)會(huì)生成2萬個(gè)紅包,每秒也是200個(gè),每個(gè)紅包隨機(jī)指定3位用戶,并向這3個(gè)用戶發(fā)出消息,客戶端會(huì)自動(dòng)來拿紅包,最后所有的紅包都被拿走。

最后,實(shí)踐完成。

8 分析數(shù)據(jù)

在實(shí)踐過程中,服務(wù)器和客戶端都將自己內(nèi)部的計(jì)數(shù)器記錄發(fā)往監(jiān)控端,成為了日志。我們利用簡(jiǎn)單python 腳本和gnuplt 繪圖工具,將實(shí)踐的過程可視化,由此來驗(yàn)證運(yùn)行過程。

第一張是 客戶端的QPS發(fā)送數(shù)據(jù)


image

這張圖的橫坐標(biāo)是時(shí)間,單位是秒,縱坐標(biāo)是QPS,表示這時(shí)刻所有客戶端發(fā)送的請(qǐng)求的QPS。
圖的第一區(qū)間,幾個(gè)小的峰值,是100萬客戶端建立連接的, 圖的第二區(qū)間是3萬QPS 區(qū)間,我們可以看到數(shù)據(jù) 比較穩(wěn)定的保持在3萬這個(gè)區(qū)間。最后是6萬QPS區(qū)間。但是從整張圖可以看到QPS不是完美地保持在我們希望的直線上。這主要是以下幾個(gè)原因造成的

  1. 當(dāng)非常多goroutine 同時(shí)運(yùn)行的時(shí)候,依靠sleep 定時(shí)并不準(zhǔn)確,發(fā)生了偏移。我覺得這是golang本身調(diào)度導(dǎo)致的。當(dāng)然如果cpu比較強(qiáng)勁,這個(gè)現(xiàn)象會(huì)消失。

  2. 因?yàn)榫W(wǎng)絡(luò)的影響,客戶端在發(fā)起連接時(shí),可能發(fā)生延遲,導(dǎo)致在前1秒沒有完成連接。

  3. 服務(wù)器負(fù)載較大時(shí),1000M網(wǎng)絡(luò)已經(jīng)出現(xiàn)了丟包現(xiàn)象,可以通過ifconfig 命令觀察到這個(gè)現(xiàn)象,所以會(huì)有QPS的波動(dòng)。

第二張是 服務(wù)器處理的QPS圖


image

和客戶端的向?qū)?yīng)的,服務(wù)器也存在3個(gè)區(qū)間,和客戶端的情況很接近。但是我們看到了在大概22:57分,系統(tǒng)的處理能力就有一個(gè)明顯的下降,隨后又提高的尖狀。這說明代碼還需要優(yōu)化。

整體觀察在3萬QPS區(qū)間,服務(wù)器的QPS比較穩(wěn)定,在6萬QSP時(shí)候,服務(wù)器的處理就不穩(wěn)定了。我相信這和我的代碼有關(guān),如果繼續(xù)優(yōu)化的話,還應(yīng)該能有更好的效果。

將2張圖合并起來
image

基本是吻合的,這也證明系統(tǒng)是符合預(yù)期設(shè)計(jì)的。

這是紅包生成數(shù)量的狀態(tài)變化圖


image

非常的穩(wěn)定。

這是客戶端每秒獲取的搖紅包狀態(tài)


image

可以發(fā)現(xiàn)3萬QPS區(qū)間,客戶端每秒獲取的紅包數(shù)基本在200左右,在6萬QPS的時(shí)候,以及出現(xiàn)劇烈的抖動(dòng),不能保證在200這個(gè)數(shù)值了。我覺得主要是6萬QPS時(shí)候,網(wǎng)絡(luò)的抖動(dòng)加劇了,造成了紅包數(shù)目也在抖動(dòng)。

最后是golang 自帶的pprof 信息,其中有g(shù)c 時(shí)間超過了10ms, 考慮到這是一個(gè)7年前的硬件,而且非獨(dú)占模式,所以還是可以接受。


image

總結(jié):

按照設(shè)計(jì)目標(biāo),我們模擬和設(shè)計(jì)了一個(gè)支持100萬用戶,并且每秒至少可以支持3萬QPS,最多6萬QPS的系統(tǒng),簡(jiǎn)單模擬了微信的搖紅包和發(fā)紅包的過程??梢哉f達(dá)到了預(yù)期的目的。
如果600臺(tái)主機(jī)每臺(tái)主機(jī)可以支持6萬QPS,只需要7分鐘就可以完成 100億次搖紅包請(qǐng)求。

雖然這個(gè)原型簡(jiǎn)單地完成了預(yù)設(shè)的業(yè)務(wù),但是它和真正的服務(wù)會(huì)有哪些差別呢?我羅列了一下

區(qū)別 真正服務(wù) 本次模擬
業(yè)務(wù)復(fù)雜 更復(fù)雜 非常簡(jiǎn)單
協(xié)議 Protobuf 以及加密 簡(jiǎn)單的協(xié)議
支付 復(fù)雜
日志 復(fù)雜
性能 更高
用戶分布 用戶id分散在不同服務(wù)器,需要hash以后統(tǒng)一, 復(fù)雜。 用戶id 連續(xù),很多優(yōu)化使代碼簡(jiǎn)單 非常高效
安全控制 復(fù)雜
熱更新及版本控制 復(fù)雜
監(jiān)控 細(xì)致 簡(jiǎn)單

Refers:

作者:ppmsn2005#gmail.com
項(xiàng)目: https://github.com/xiaojiaqi/10billionhongbaos
wiki: https://github.com/xiaojiaqi/10billionhongbaos/wiki/扛住100億次請(qǐng)求?我們來試一試

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容