新猿0基礎(chǔ)python教程 Python項目高并發(fā)異步部署實戰(zhàn)+壓測

## 1 前言

由于Python有把大鎖GIL,會將多個線程在同一時刻,只能有一個線程執(zhí)行,變成'串行',所以一個多線程python進(jìn)程,并不能充分使用多核CPU資源,所以對于Python進(jìn)程,可采用多進(jìn)程部署方式比較有利于充分利用多核的CPU資源,而uWSGI服務(wù)器就是這么一個東西,可以以多進(jìn)程方式執(zhí)行WSGI app,其工作模式為 1 master進(jìn)程 + N worker進(jìn)程+m個線程(N*m線程),主進(jìn)程負(fù)責(zé)接收客戶端請求,然后將請求轉(zhuǎn)發(fā)給worker進(jìn)程,因此最終是worker進(jìn)程負(fù)責(zé)處理客戶端請求,這樣很方便的將WSGI app以多進(jìn)程方式進(jìn)行部署**此方式是企業(yè)常用部署方式**

**但是存在一個問題**

客戶端向uwsgi的一個master發(fā)起一個HTTP請求,master分發(fā)給不同的worker進(jìn)程,worker進(jìn)程拉起線程處理請求,進(jìn)入web框架,直到該請求處理完,這個線程才能處理其他請求,所以wsgi app是同步的。假如一個請求處理花費時間比較久,客戶端請求數(shù)量又比較多的情況下,所有的線程都會被占滿,所以就處理不了更多的請求(最大連接數(shù)取決于進(jìn)程N(yùn)*線程M)

**我們的處理方案**

1)增大N,即worker的數(shù)量:在增加進(jìn)程的數(shù)量的時候,進(jìn)程是要消耗內(nèi)存的,并且如果進(jìn)程數(shù)量太多的情況下(并且進(jìn)程均處于活躍狀態(tài)),進(jìn)程間的切換會消耗系統(tǒng)資源的,所以N并不是越大越好。一般情況下,可能將進(jìn)程數(shù)目設(shè)置為CPU數(shù)量的2倍

2)增大m,即worker的線程數(shù)量:線程創(chuàng)建也是有限度的,由于線程棧是要消耗內(nèi)存的,線程數(shù)量太多也不行

于是我們想,一條線程能不能同時處理多個請求呢?可以使用IO多路復(fù)用的模型

**于是,gevent登場了**

gevent是用戶態(tài)的'線程',也就是協(xié)程,單線程下實現(xiàn)并發(fā)

gevent的好處就是無需等待I/O,當(dāng)發(fā)生I/O調(diào)用是,gevent會主動切換到另一gevent進(jìn)行運行,這樣可以充分利用CPU資源

同時gevent通過monkey patch(猴子補(bǔ)?。┨鎿Q掉了標(biāo)準(zhǔn)庫中阻塞的模塊

## 2 以flask項目為例,使用uwsgi+gevent部署高并發(fā)實戰(zhàn)

### 2.1 新建flask項目 (s1.py)

```python

from flask import Flask

import time

app = Flask(__name__)

@app.route('/')

def hello_world():

????time.sleep(1) # 引入io操作

????return 'Hello World!'

if __name__ == '__main__':

????app.run()

```

## 2.2 新建uwsgi.py

```python

[uwsgi]

http = 0.0.0.0:5000

chdir = /root/20210318/

wsgi-file = /root/20210318/s1.py

processes = 2

threads = 8

buffer-size = 32768

master = true

pidfile = uwsgi.pid

daemonize = uwsgi.log

callable = app

---------------------------

[uwsgi]

http = 0.0.0.0:5000 # 監(jiān)聽地址和端口

chdir = /root/test/ # 項目路徑

wsgi-file = /root/test/s1.py # py文件路徑

processes = 1 # 進(jìn)程數(shù)

threads = 1???# 線程數(shù)

buffer-size = 32768 # 緩存大小

master = true???????#允許主進(jìn)程存在

pidfile = uwsgi.pid # pid位置

daemonize = uwsgi.log#日志文件

callable = app???#flask中flask對象的名字,flask部署需要配置它

-----------uwsgi其他參數(shù)------------------

socket : 地址和端口號,例如:socket = 127.0.0.1:50000

processes : 開啟的進(jìn)程數(shù)量

workers : 開啟的進(jìn)程數(shù)量,等同于processes(官網(wǎng)的說法是spawn the specified number of??workers / processes)

chdir : 指定運行目錄,項目根路徑(chdir to specified directory before apps loading)

wsgi-file : 載入wsgi-file,wsgi文件,flask就是app.py(load .wsgi file)

stats : 在指定的地址上,開啟狀態(tài)服務(wù)(enable the stats server on the specified address)

threads : 運行線程。(run each worker in prethreaded mode with the specified number of threads)

master : 允許主進(jìn)程存在(enable master process)

daemonize : 使進(jìn)程在后臺運行,并將日志打到指定的日志文件或者udp服務(wù)器(daemonize uWSGI)。實際上最常用的,還是把運行記錄輸出到一個本地文件上。

log-maxsize :以固定的文件大小(單位KB),切割日志文件。 例如:log-maxsize = 50000000??就是50M一個日志文件。

pidfile : 指定pid文件的位置,記錄主進(jìn)程的pid號。

vacuum : 當(dāng)服務(wù)器退出的時候自動清理環(huán)境,刪除unix socket文件和pid文件(try to remove all of the generated file/sockets)

disable-logging : 不記錄請求信息的日志。只記錄錯誤以及uWSGI內(nèi)部消息到日志中。如果不開啟這項,那么你的日志中會大量出現(xiàn)這種記錄:

log-maxsize : 日志大小,當(dāng)大于這個大小會進(jìn)行切分 (Byte)

log-truncate : 當(dāng)啟動時切分日志

buffer-size : 比如前端(客戶端)向后端(服務(wù)器)發(fā)了一個請求,請求的大小是5M,那么buffer-size的大小就得大于1024*5,不然就報錯了

callable :app??#變量app 與 App.py文件中的app = Flask(__name__)對應(yīng)

```

## 2.3 在centos7.5機(jī)器上測試

>第一步:安裝python3.6環(huán)境(略)

>

>第二步:安裝uwsgi (pip3 install uwsgi)

>

>????-uwsgi在1.4版本以上,就支持gevent(官方介紹:https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/Gevent.html)

>

>第三步:安裝flask????(pip3 install flask)

>

>第四步:安裝gevent???(pip3 install gevent)

## 2.4 首先不使用gevent啟動uwsgi

>uwsgi uwsgi.ini

## 2.5 使用gevent啟動uwsgi

>

>uwsgi --gevent 100 --gevent-monkey-patch uwsgi.ini

>

## 2.6 壓測兩個接口

>ab -n 10 -c 5 http://101.133.225.166:5000/

>

>不使用gevent跑,可以看到 requests per second (每秒請求數(shù)為0.99)

>ab -n 10 -c 5 http://101.133.225.166:5000/

>

>使用gevent跑,可以看到 requests per second (每秒請求數(shù)為3.28)

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

相關(guān)閱讀更多精彩內(nèi)容

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