安裝
簡單如下
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這個配置隻在開發的時候使用,生産模式下就算了,挺耗性能的