安裝
簡單如下
pip install uwsgi
配置
以ini文件配置,摘取部分常用的,配置實在太“靈活”了
[uwsgi]
#默認情況下Python plugin不會初始化GIL,也就是說app生成的線程不會執行,如果需要線程,需要配置開啟
enable-threads = true
#綁定本地ip和端口,如果直接":port"的話,綁定的ip是0.0.0.0,這是uwsgi方式,如果前端webserver不支持uwsgi的時候用http-socket
socket = 127.0.0.1:15000
#stats服務綁定配置,使用時:uwsgitop 127.0.0.1:3167,非必須配置
stats = 127.0.0.1:3167
#設置python的虛擬環境目錄,我這裡用的anaconda3創建的虛擬環境
virtualenv = /home/**/anaconda3/envs/**
#設置一個系統環境變量ALITA_CONFIG,這裡的變量名字自己起,在項目啟動時可以用來傳給python配置路徑,非必須,可以在代碼中配置
env = ALITA_CONFIG=../config/dev/dev.py
#配置wsgi文件路徑和名稱
wsgi-file = wsgi.py
#設置WSGI回調,默認“application”
callable = application
# 在每個worker而不是master中加載應用,這樣可以保證每個worker在一個一致的並且乾淨的環境中運行
lazy-apps = true
# 啟動主進程,來管理其他進程,其它的uwsgi進程都是這個master進程的子進程,如果kill這個master進程,相當於重啟所有的uwsgi進程。
master = true
#生成指定數目的worker/進程,和workers配置項一樣
processes = 2
#設置用於uwsgi包解析的內部緩存區大小為64k。默認是4k
buffer-size = 32768
#當服務器退出的時候自動刪除unix socket文件和pid文件
vacuum = true
#為每個工作進程設置請求數的上限。當一個工作進程處理的請求數達到這個值,那麼該工作進程就會被回收重用(重啟)。你可以使用這個選項來默默地對抗內存洩漏
max-requests = 20000
#當一個工作進程的虛擬內存佔用超過了限制的大小,那麼該進程就會被回收重用(重啟)
reload-on-as = 128
#跟reload-on-as的效果類似,不過這個選項控制的是物理內存。你可以同時使用這2個選項,如下配置會導致超過96M物理內存的工作進程重啟,當工作進程因此重啟時,本次請求的響應不會受影響,返回正常結果
reload-on-rss: 96
#設置在平滑的重啟(直到接收到的請求處理完才重啟)一個工作子進程中,等待這個工作結束的最長秒數。這個配置會使在平滑地重啟工作子進程中,如果工作進程結束時間超過了8秒就會被強行結束(忽略之前已經接收到的請求而直接結束)
reload-mercy = 8
#如果一個請求花費的時間超過了這個harakiri超時時間,那麼這個請求都會被丟棄,並且當前處理這個請求的工作進程會被回收再利用(即重啟),如下設置會使uwsgi丟棄所有需要20秒以上才能處理完成的請求
harakiri = 20
#當一個請求被harakiri殺掉以後,你將在uWSGI日誌中得到一條消息。激活這個選項會打印出額外的信息
harakiri-verbose = true
#設置socket的監聽隊列大小(默認:100),每一個socket都有一個相關聯的隊列,請求會被放入其中等待進程來處理。當這個隊列慢的時候,新來的請求就會被拒絕。隊列大小的最大值依賴於系統內核
listen = 1024
#這個鎖用來串行化accept,防止“驚群”現象
thunder-lock = true
#指定pid文件
pidfile = /tmp/**.pid
#守護進程的方式,如果用supervisor啟動時不要配置這個,跟supervisor裡面的日誌衝突
daemonize = /home/***/logs/uwsgi.log
#日誌格式設置
log-format = %(addr) - %(pid) [%(ltime)] "%(method) %(uri) %(proto)" %(status) %(hsize) %(rsize) "%(referer)" "%(uagent)" %(switches) %(micros)
nginx 配置
使用 TCP socket 的配置
uwsgi_pass 127.0.0.1:3031;
include uwsgi_params;
或者使用uWSGI socket文件方式
uwsgi_pass unix:///tmp/uwsgi.sock;
include uwsgi_params;
性能監控
假設按照上面配置開了state如下
#stats服務綁定配置,使用時:uwsgitop 127.0.0.1:3167,非必須配置
stats = 127.0.0.1:3167
當運行起uWsgi程序後,可以通過curl 127.0.0.1:3167看到運行的情況,當然,返回的json結構數據太長,有個工具類似linux的top的工具,看起來清爽多了
#安裝監控工具
pip install uwsgitop
#使用
uwsgitop 127.0.0.1:3167
每一列說明如下
Field | Description |
---|---|
WID | Worker ID |
% | Worker usage |
PID | Worker PID |
REQ | Number of requests the worker executed since last (re)spawn |
RPS | Requests per second |
EXC | Exceptions |
SIG | Managed uwsgi signals |
STATUS | Worker is busy or free to use? |
AVG | Average request time |
RSS | Worker RSS (Resident Set Size, see linux memory management) |
VSZ | Worker VSZ (Virtual Memory Size, see linux memory management) |
TX | How much data was transmitted by the worker |
ReSpwn | Respawn count |
HC | Harakiri count |
RunT | How long the worker has been running |
LastSpwn | Last spawn time |
注意事項
- http和http-socket完全不同。http將生成一個額外的進程,將請求轉發給workers(一種屏蔽形式,和apache、nginx差不多),而http-socket將workers設置為以本地方式使用http協議。如果直接向公眾公開uWSGI,用--http;如果將其代理到webserver後面並使用http協議,就用--http-socket,當然,官方是建議使用uwsgi協議的。
- 進程數和線程數配置沒有一定的規則,除了拍腦袋使用cpu核數*2,uwsgitop是個不錯的健康監控工具,幫助來確定什麼配置更合適
- 配置memory-report,勤檢查worker內存佔用情況,
- 如果用UNIX sockets的話,注意文件權限
- 不要以root用戶運行uWSGI,如果在root下運行的話,可以配置一下uid和gid指定一下運行在那個用戶和用戶組下
- 默認情況下uWSGI是先加載app,然後才fork worker的,這樣會導致比如在flask下使用orm會有獲取session失敗的情況,所以配置一下lazy-apps,讓每個worker獨立加載app,這樣每個app的環境是獨立且乾淨的,雖然佔用內存要多些,但穩定
- 默認情況下,Python插件不會初始化GIL。這意味著你的應用程序生成的線程將不會運行。如果需要線程,請記住使用enable-threads啟用它們
- 默認情況下,uWSGI為每個請求的頭分配一個非常小的緩衝區(4096字節)。如果在日誌中開始收到 “invalid request block size” ,則可能意味著需要更大的緩衝區。使用buffer-size選項增加它(最多65535個)
- 如果(Linux)服務器似乎有很多空閒的工作線程,但性能仍然低,查看下ip_conntrack_max系統變量的值,並將其增大以查看是否有幫助
- py-autoreload這個配置只在開發的時候使用,生產模式下就算了,挺耗性能的