安装
简单如下
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这个配置只在开发的时候使用,生产模式下就算了,挺耗性能的