調(diào)研 gunicorn && uwsgi 性能

背景: 隨著業(yè)務(wù)增長荷腊,API 接口 499,502 的數(shù)量也呈現(xiàn)增長的趨勢较幌。當(dāng)下使用的 nginx + gunicorn + flask 的框架結(jié)構(gòu)看起來已經(jīng)到達了瓶頸妻味。
故探索使用 nginx + uwsgi + flask 的架構(gòu)來提示性能。

名詞解釋:gunicorn/uwsgi都是wsgi協(xié)議(python web server gateway interface)的實現(xiàn)瓷式,
它們做的事情是協(xié)議轉(zhuǎn)換替饿,協(xié)議的一頭是web app(如flask, django等framework的app),
另一頭是web server(如apache, nginx等)蒿往,gunicore/uwsgi在默認的情況下都是同步模型盛垦,
但都比通常的web framework實現(xiàn)得好湿弦。

使用的版本:

gunicorn==20.0.4
 
uWSGI==2.0.20

測試服務(wù)器信息:

CPU&內(nèi)存
8核16 GiB
操作系統(tǒng)
Ubuntu 16.04 64位更換操作系統(tǒng)
實例規(guī)格
ecs.t5-c1m2.2xlarge(性能約束實例)升降配
實例規(guī)格族
ecs.t5

開始測試:

uwsgi 配置詳情

# http 方式
[uwsgi]
http = :5001
chdir = /home/www/xxx/xxx/
wsgi-file = scripts/web.py
callable = app
processes = 1,4,8,16
threads = 1
 
# socket 方式
[uwsgi]
module = scripts.web:app
 
master = true
processes = 1,4,8,16
 
socket = hebe.sock
chmod-socket = 660
vacuum = true
 
die-on-term = true

gunicorn 配置詳情

./ve gunicorn --preload \
     --backlog 2 \
     -w 1, 4, 8, 16 \
     -b 10.111.1.180:8011 \
     -b 127.0.0.1:8011 \
     -c /home/www/xxx/xxx/scripts/gunicorn_config.py \
     scripts.server:app

測試工具 wrk

`[root@jerrik /]# wrk -t12 -c100 -d30s [http://www.baidu.com ](http://www.baidu.com%20/)`
`Running 30s test @ [http://www.baidu.com](http://www.baidu.com/)`
`12 threads and 100 connections`
`Thread Stats   Avg      Stdev     Max   +/- Stdev`
`Latency   211.76ms  304.92ms   1.97s    88.17%`
`Req/Sec    72.93     68.72   797.00     90.97%`
`23725 requests in 30.05s, 347.47MB read`
`Socket errors: connect 0, read 48, write 0, timeout 50`
`Requests/sec:    789.57`
`Transfer/sec:     11.56MB`
解釋說明
  • 12 threads and 100 connections:
    • 總共是12個線程,100個連接(不是一個線程對應(yīng)一個連接)
  • latency和Req/Sec:
    • 代表單個線程的統(tǒng)計數(shù)據(jù),latency代表延遲時間,Req/Sec代表單個線程每秒完成的請求數(shù)瓤漏,他們都具有平均值, 標(biāo)準(zhǔn)偏差, 最大值, 正負一個標(biāo)準(zhǔn)差占比。一般我們來說我們主要關(guān)注平均值和最大值. 標(biāo)準(zhǔn)差如果太大說明樣本本身離散程度比較高. 有可能系統(tǒng)性能波動很大.
  • 23725 requests in 30.05s, 347.47MB read
    • 在30秒之內(nèi)總共有23725個請求,總共讀取347.47MB的數(shù)據(jù)
  • Socket errors: connect 0, read 48, write 0, timeout 50
    • 總共有48個讀錯誤,50個超時.
  • Requests/sec和Transfer/sec
    • 所有線程平均每秒鐘完成了789.57個請求,每秒鐘讀取11.56MB數(shù)據(jù)量

CPU 密集型測試:

@app.route('/py.cpu')
def python_cpu():
    """
    測試 cpu 性能
    :return:
    """
    def double_fact(x):
        ans = 1
        for i in range(1, x + 1):
            if i % 2 == x % 2:
                ans *= i
        return ans
 
    def asin(x, t):
        answer = 0
        for k in range(0, t + 1):
            a = (double_fact(2 * k - 1) / double_fact(2 * k)) * (pow(x, 2 * k + 1) / (2 * k + 1))
            print("k=%d,a=%s" % (k, a))
            answer += a
 
        return answer
    app.logger.info(asin(1, 100) * 2)
    return success(dict(version=sys.version))

IO 密集型測試:

@app.route("/py.io")
def python_io():
    """
    測試網(wǎng)絡(luò) io 性能
    :return:
    """
    import requests
 
    url = "https://www.idejian.com/"
    requests.get(url)  # 發(fā)get請求
    app.logger.info(sys.version)
 
    return success(dict(version=sys.version))

結(jié)果比較: ./wrk -t 16 -c 100 -d 10 https://xxxx.com/py.cpu

CPU 密集型API

20211217182527.jpg

結(jié)果比較: ./wrk -t 16 -c 100 -d 10 https://xxxx.com/py.io

IO 密集型API

20211217182648.jpg

結(jié)論:同步調(diào)用下,uwsgi 并沒有比 gunicorn 更高性能蔬充。和預(yù)期不符蝶俱,不知道是否是測量的方式有問題。 暫時不考慮使用 uwsgi 饥漫,繼續(xù)優(yōu)化 gunicorn

gunicorn 優(yōu)化項目

  • 調(diào)整進程數(shù)據(jù)為 cpu *2 + 1
  • gunicorn worker_class = "eventlet"
  • gunicorn preload 關(guān)掉
  • gunicorn backlog 調(diào)整為 2048
在測試環(huán)境中測下來榨呆,上面的四項調(diào)整有明顯的性能提升,但也帶來了新的問題庸队。
  • 異步的為每個連接創(chuàng)建一個“綠色”線程积蜻,在處理IO機密型程序時,有明顯的性能提升彻消。
  • 弊端是為每個連接創(chuàng)建一個“綠色”線程竿拆,在高峰期的時候,mysql 等其他有連接池的工具宾尚,不能提供足夠的鏈接丙笋。導(dǎo)致程序報錯。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末煌贴,一起剝皮案震驚了整個濱河市御板,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌牛郑,老刑警劉巖怠肋,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異淹朋,居然都是意外死亡灶似,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門瑞你,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酪惭,“玉大人,你說我怎么就攤上這事者甲〈焊校” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵虏缸,是天一觀的道長鲫懒。 經(jīng)常有香客問我,道長刽辙,這世上最難降的妖魔是什么窥岩? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮宰缤,結(jié)果婚禮上颂翼,老公的妹妹穿的比我還像新娘晃洒。我一直安慰自己,他們只是感情好朦乏,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布球及。 她就那樣靜靜地躺著,像睡著了一般呻疹。 火紅的嫁衣襯著肌膚如雪吃引。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天刽锤,我揣著相機與錄音镊尺,去河邊找鬼。 笑死并思,一個胖子當(dāng)著我的面吹牛鹅心,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纺荧,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼旭愧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宙暇?” 一聲冷哼從身側(cè)響起输枯,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎占贫,沒想到半個月后桃熄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡型奥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年瞳收,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厢汹。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡螟深,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出烫葬,到底是詐尸還是另有隱情界弧,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布搭综,位于F島的核電站垢箕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏兑巾。R本人自食惡果不足惜条获,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蒋歌。 院中可真熱鬧帅掘,春花似錦委煤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽称诗。三九已至萍悴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寓免,已是汗流浹背癣诱。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留袜香,地道東北人撕予。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像蜈首,于是被迫代替她去往敵國和親实抡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容