uwsgi的使用示例+django(监听队列长度)
-https://docs.djangoproject.com/zh-hans/3.2/howto/deployment/wsgi/uwsgi/
- https://uwsgi-docs-cn.readthedocs.io/zh_CN/latest/WSGIquickstart.html
- 监听队列最大长度: https://www.cxyzjd.com/article/wyfcode/86258232
- python如何获取uwsgi的各个worker的status: https://blog.csdn.net/qq_29306999/article/details/102500211
完全命令类似这种:uwsgi --connect-and-read 127.0.0.1:5000
uwsgi基本了解
前置条件:uWSGI¶
uWSGI 百科介绍了几种 安装流程。Pip (Python 包管理器)能让你仅用一行代码就安装任意版本的 uWSGI。例子:
# Install current stable version.
$ python -m pip install uwsgi
# Or install LTS (long term support).
$ python -m pip install https://projects.unbit.it/downloads/uwsgi-lts.tar.gz
uWSGI 模块¶
uWSGI 以客户端-服务端模型运行。Web 服务器(例如 nginx,Apache)与一个 django-uwsgi "worker" 进程交互,提供动态内容。
配置并启动用于 Django 的 uWSGI 服务器¶
uWSGI 支持多种配置进程的方式。参考 uWSGI 的 配置文档。
以下是个示例命令,用于启动一个 uWSGI 服务器:
uwsgi --chdir=/path/to/your/project \
--module=mysite.wsgi:application \
--env DJANGO_SETTINGS_MODULE=mysite.settings \
--master --pidfile=/tmp/project-master.pid \
--socket=127.0.0.1:49152 \ # can also be a file
--processes=5 \ # number of worker processes
--uid=1000 --gid=2000 \ # if root, uwsgi can drop privileges
--harakiri=20 \ # respawn processes taking more than 20 seconds
--max-requests=5000 \ # respawn processes after serving 5000 requests
--vacuum \ # clear environment on exit
--home=/path/to/virtual/env \ # optional path to a virtual environment
--daemonize=/var/log/uwsgi/yourproject.log # background the process
假设你有个叫做 mysite 的顶级项目包,期中包含一个模板 mysite/wsgi.py,模块包含一个 WSGI application 对象。如果你使用的是较新的 Django,这就是你运行 django-admin startproject mysite (使用你的项目名替换 mysite)后得到的目录结构。若该文件不存在,你需要创建它。参考文档 如何使用 WSGI 进行部署 看看你需要配置的默认内容,以及你还能添加什么。
Django 指定的参数如下:
chdir:需要包含于 Python 的导入路径的目录的路径——例如,包含 mysite 包的目录。
module:要使用的 WSGI 模块——可能是 startproject 创建的 mysite.wsgi 的模块。
env:至少要包括 DJANGO_SETTINGS_MODULE。
home: 可选的路径,指向你工程的虚拟环境。
示例 ini 配置文件:
[uwsgi]
chdir=/path/to/your/project
module=mysite.wsgi:application
master=True
pidfile=/tmp/project-master.pid
vacuum=True
max-requests=5000
daemonize=/var/log/uwsgi/yourproject.log
示例 ini 配置文件语法:
uwsgi --ini uwsgi.ini
uwsgi源码分析-工作流程
参考:
uwsgi 是一个用 c 写的 webserver, 经典的 master/worker 进程模式。
uwsgi采用的是经典的 单master/多worker 并发模型。master负责信号处理,初始化,创建并管理worker进程,以及绑定监听sockets。worker的每个线程,处在这样的一个循环中:accept -> recv -> handle request -> send response。
一开始进入main函数,启动这个就是主进程了,uwsgi_setup函数(主进程)里面针对选项参数做一些处理,执行环境设置,执行一些hook,语言环境初始化(python),如果没有设置延迟加载app,则app在主进程加载;如果设置了延迟加载,则在每一个worker进程中都会加载一次。uwsgi_setup函数还执行了插件的初始化(eg http、python:http是gateway类型的插件,这种插件是向外暴露http服务的,python的 requests 类型的插件,用来服务请求的)、tcp socket的绑定与监听(这个是指http与work之间的通信,且它的端口是自动产生的)。最后uwsgi主进程fork了指定worker进程用来接收(accept)请求。虽然在setup中就fork了子进程,但是现在还没有开始accept。
主进程执行部分是一个无限循环,他可以执行特定的hook以及接收信号等,总之是用来管理worker进程以及一些定时或者事件触发任务。worker部分:注册型号处理函数,执行一些hook,循环接收(accept)请求。在启动woker时可以根据–threads参数指定要产生的线程个数,否则只在当前进程启动一个线程。这些线程循环接收请求并处理。
worker中接收请求的函数wsgi_req_accept有一个锁:thunder_lock,这个锁用来串行化accept,防止“惊群”现象:主进程绑定并监听socket,然后调用fork,在各个子进程进行accept。无论任何时候,只要有一个连接尝试连接,所有的子进程都将被唤醒,但只有一个会连接成功,其他的会得到一个EAGAIN的错误,导致巨大的CPU资源浪费,如果在进程中使用线程,这个问题被再度放大。一个解决方法是串行化accept,在accept前防止一个锁。
nginx + uwsgi + django部署的原理
参考:
首先客户端请求服务资源,
nginx作为直接对外的服务接口,接收到客户端发送过来的http请求,会解包、分析,
如果是静态文件请求就根据nginx配置的静态文件目录,返回请求的资源,
如果是动态的请求,nginx就通过配置文件,将请求传递给uWSGI;uWSGI 将接收到的包进行处理,并转发给wsgi,
wsgi根据请求调用django工程的某个文件或函数,处理完后django将返回值交给wsgi,
wsgi将返回值进行打包,转发给uWSGI,
uWSGI接收后转发给nginx,nginx最终将返回值返回给客户端(如浏览器)。
*注:不同的组件之间传递信息涉及到数据格式和协议的转换
uwsgi常用配置
uwsgi.ini
# uwsgi --http :8000 --ini uwsgi.ini # http启动命令
# uwsgi --master --https 0.0.0.0:443,foobar.crt,foobar.key,HIGH --chdir /workdir/bean/ --module bean.wsgi # https启动命令
[uwsgi]
# close tlsv1.0 1.1
ssl-enable3 = false
ssl-option = 67108864
ssl-enable-tlsv1 = false
https = 0.0.0.0:9443,/path/cert/server.pem,/path/cert/server.key,HIGH
# http-to = /tmp/uwsgi.sock
# 路径 可不指定workdir
wsgi-file = bean/wsgi.py
# auto load py
# py-autoreload = 1
# static map
static-map=/static=/static
# 重启时间
# harakiri = 10
# 主进程
master = true
# 4个进程/workers
processes = 4
# 两个核心
# threads = 1
; 将写入 log 的工作委托给 master 进程
log-master = true
; 单独开一个线程进行 log 写入工作,这样有更好的性能
threaded-log = true
# 避免惊群效应 multiprocess + multithread
# https://stackoverflow.com/questions/34824487/when-is-thunder-lock-beneficial
thunder-lock = true
# 开启线程
enable-threads = false
# 单个进程最大请求数
max-requests = 5000
# 解包缓冲区大小
buffer-size = 65536
# 平滑重启时间
reload-mercy = 5
worker-reload-mercy = 5
# 状态监听地址
stats = 127.0.0.1:5000 # uwsgi --connect-and-read 127.0.0.1:5000查看uwsgi的连接状态
# master进程位置,用于停止和重新加载
pidfile = /var/run/uwsgi.pid
# 退出后自动清理socket pid文件,停止后将无法重启
vacuum = true
# 日志分块大小
# log-maxsize = 50000000
# 不记录请求日志,只记录错误及内部消息
# disable-logging = true
# logto 指定日志存储位置及文件名
# logto = /var/log/itp/itpserver/logs/uwsgi.log