天天看點

uWsgi的安裝和配置筆記

安裝

簡單如下

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