官方参考文档html
pip install uwsgi uwsgi --version # 查看 uwsgi 版本
新建一个测试文件 helloworld.py
前端
def application(env, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'hello world',]
uwsgi --http :9090 --wsgi-file helloworld.py
uwsgi 默认是单进程单线程启动的python
添加多进程使用 --processes 选项, 添加多线程使用 --threads 选项nginx
uwsgi --http :9090 --wsgi-file helloworld.py --master --processes 4 --threads 2 # 表示启动 4 个进程,每一个进程 2 个线程;一个主进程,当进程挂掉后重新生成新的进程
监测是一个重要的任务。在生产环境中知道发生了什么是相当重要的git
stats 子系统容许你以 json 格式导出 uwsgi 的内部统计信息web
uwsgi --http :9090 --wsgi-file helloworld.py --master --processes 4 --threads 2 --stats 127.0.0.1:9091 # 添加监测,经过 127.0.0.1:9091 访问 json 格式的统计信息 # 把 stats 绑定到一个私有地址,不然全部人均可以访问这个统计信息 uwsgitop 一个相似 top 的监控 uwsgi 的工具 pip install uwsgitop
uwsgi可使用 HTTP, FastCGI, SCGI, uwsgi 协议,其中性能最好的是 uwsgi,nginx 支持 uwsgi 协议,apache 在添加对应的模块后也能够支持 uwsgi 协议apache
一个常见的 nginx 配置以下:django
location / { include uwsgi_params; uwsgi_pass 127.0.0.1:3031; } # 使用 uwsgi 协议将每一个请求转发到绑定 3031 端口的服务器
使用 uwsgi 协议启动 uwsgi 服务器json
uwsgi --socket 127.0.0.1:3031 --wsgi-file helloworld.py --master --processes 4 --threads 2 -stats 127.0.0.1:9191
若是你的代理前端服务器使用的是 http 协议,你必须让 uwsgi 也使用 http 协议flask
uwsgi --http-socket 127.0.0.1:3031 --wsgi-file helloworld.py --master --processes 4 --threads 2 --stats 127.0.0.1:9091 # --http 和 --http-socket 不同,--http 自带一个代理
在使用脚原本启动 uwsgi 以前,看是否可使用其余进程管理程序来启动 uwsgi,好比:
Upstart, Systemd supervisord, god, monit, circus
uwsgi 能够很好的与以上的进程管理器集成,若是有大量的应用须要部署,建议使用 uWSGI Emperor
假设 django 项目路径是: /home/foobar/myproject
uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --wsgi-file myproject/wsgi.py --master --processes 4 --theads 2 --stats 127.0.0.1:9191
--chdir 切换到 django 的项目路径下,这是 django 正确加载模块所必须的
以上这个很长的命令行命令能够写在一个 uwsgi 的 .ini 格式的配置文件中,好比 foo.ini
[uwsgi] socket = 127.0.0.1:3031 chdir = /home/foobar/myproject/ wsgi-file = myproject/wsgi.py processes = 4 threads = 2 stats = 127.0.0.1:9191
使用配置文件启动
uwsgi foo.ini
若是使用的是旧版本的django(< 1.4),须要多加一下配置
uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --pythonpath .. --env DJANGO_SETTINGS_MODULE=myproject.settings --module "django.core.handlers.wsgi:WSGIHandler()" --processes 4 --threads 2 --stats 127.0.0.1:9191
[uwsgi] socket = 127.0.0.1:3031 chdir = /home/foobar/myproject/ pythonpath = .. env = DJANGO_SETTINGS_MODULE=myproject.settings module = django.core.handlers.wsgi:WSGIHandler() processes = 4 threads = 2 stats = 127.0.0.1:9191
旧版本的 django(< 1.4) 须要设置 env,module, pythonpath(容许获取到 myproject.settings 模块)
若是没有使用多线程启动 uwsgi,那么在应用里面生成的线程不会运行
可使用 --enable-threads 选项,enable-threads = true .ini文件配置项,在不使用多线程启动 uwsgi 时支持应用内的多线程运行
uwsgi 支持 python 虚拟环境内查找 python 模块,只须要添加配置项 virtualenv = <path>
安全性
不要使用 root 用户运行 uwsgi,可使用 uid 和 gid 移除特权
[uwsgi] https = :9090,foobar.crt,fooar.key uid = foo gid = bar chdir = path_to_web2py module = wsgihandler master = true processes = 8
若是要使用特权端口(如 443),可使用共享 socket
[uwsgi] shared-socket = :443 https = 0, foobar.crt, foobar.key uid = foo gid = bar chdir = path_to_web2py module = wsgihandler master = true processes = 8
能够性
请求阻塞问题,能够设置一个 harakiri 定时器,在指定时间后销毁被阻塞的 worker
[uwsgi] shared-socket = :443 https = =0,foobar.crt,foobar.key uid = foo gid = bar chdir = path_to_web2py module = wsgihandler master = true processes = 8 harakiri = 30
若是一个请求阻塞了 30 秒,那么这个 worker 会被销毁
能够经过 stats 子系统实时查看每一个worker,thread 或者 async 工做状况
uwsgi offloading 子系统在特定匹配模式或可使用纯C线程时,能够很快的释放掉 worker,好比:从文件系统发送静态文件,从网络发送数据等
意思是:worker把请求中的特定操做(发送文件,发送数据等)分配给其余的进程线程,从而使得 worker 能够被尽快释放,处理跟多的请求
添加 --offload-threads <n>
选项启用,(建议每一个CPU启用 1 个线程)
最好的方法是内置一个独立于语言的特性的二进制文件,并为每一个Python版本提供一个按需加载的插件
编译时使用 PROFILE=nolang
make PROFILE=nolang
编译python 插件
PYTHON=python3.4 ./uwsgi --build-plugin "plugins/python python34" PYTHON=python2.7 ./uwsgi --build-plugin "plugins/python python27" PYTHON=python2.6 ./uwsgi --build-plugin "plugins/python python26"
会获得3个插件:python34_plugin.so, python27_plugin.so, python26_plugin.so
将这些复制到您想要的目录中,默认状况下,uWSGI在当前工做目录中搜索插件。
如今能够在 uwsgi 配置文件中使用这些插件,添加在最顶端
[uwsgi] plugins-dir = <path_to_your_plugin_directory> plugin = python26
2019-2-20 by achxku@163.com