python中使用uswgi详解

2019/09/10 python

python中使用uswgi详解

启动uwsgi

uwsgi --http :9090 --wsgi-file foobar.py

当你有一个前端web服务器,或者你正进行某些形式的基准时,不要使用 –http ,使用 –http-socket 。继续阅读快速入门来了解原因。

添加并发和监控

你可以用 –processes 选项添加更多的进程,或者使用 –threads 选项添加更多的线程 (或者可以同时添加)。

这将会生成4个进程 (每个进程有2个线程),一个master进程 (在Inc死掉的时候会生成它们) 和HTTP路由器 (见前面)。

uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2

一个重要的任务是监控。在生产部署上,了解正在发生的事情是至关重要的。stats子系统允许你将uWSGI的内部统计数据作为JSON导出:

uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

将它放在一个完整的web服务器之后

即使uWSGI HTTP路由器是稳定并且高性能的,但是你或许想要将你的应用放在一个全功能的web服务器之后。

uWSGI原生支持HTTP, FastCGI, SCGI及其特定的名为”uwsgi”的协议 (是哒,错误的命名选择)。最好的协议显然是uwsgi,nginx和Cherokee已经支持它了 (虽然有各种Apache模块可用)

location / {
    include uwsgi_params;
    uwsgi_pass 127.0.0.1:3031;
}

现在,我们可以生成uWSGI来本地使用uwsgi协议:

uwsgi --socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

部署Django

Django大概是最常使用的Python web框架了。部署它是相当容易的 (我们继续配置4个进程,每个进程有2个线程)。

假设Django工程位于 /home/foobar/myproject:

uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --wsgi-file myproject/wsgi.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

(使用 –chdir ,我们移到指定的目录下)。在Django中,需要使用它来正确加载模块。

以上命令行太长了,且不便管理,使用配置文件:

[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 yourfile.ini

关于Python线程的注意事项

如果你想要维护Python线程支持,而不为你的应用启动多线程,那么仅需添加 –enable-threads 选项 (或者在ini风格的文件中添加 enable-threads = true )。

安全性和可用性

总是 避免以root用户运行你的uWSGI实例。你可以使用 uid 和 gid 选项来去除权限:

[uwsgi]
https = :9090,foobar.crt,foobar.key
uid = foo
gid = bar
chdir = path_to_web2py
module = wsgihandler
master = true
processes = 8

如果你需要绑定到特许端口 (例如用于HTTPS的443),那么使用共享socket。它们在去除权限之前创建,并且可以通过 =N 语法引用,其中, N 是socket号 (从0开始):

[uwsgi]
shared-socket = :443
https = =0,foobar.crt,foobar.key
uid = foo
gid = bar
chdir = path_to_web2py
module = wsgihandler
master = true
processes = 8

web应用部署的一个常见问题是“卡住的请求”。你所有的线程/worker都卡住了 (请求阻塞) ,而你的应用无法接收更多的请求。要避免这个问题,你可以设置一个 harakiri 定时器。它是一个监控器 (由master进程管理),会摧毁那些卡住超过指定秒数的进程 (小心选择 harakiri 值)。例如,你也许想要摧毁那些阻塞超过30秒的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

其他

Python自动重载 (DEVELOPMENT ONLY!)

只在开发时使用它。

[uwsgi]
...
py-autoreload = 2

全栈CGI设置

我们在/var/www中有静态文件,在/var/cgi中有cgi。将会使用/cgi-bin挂载点访问cgi。所以将会在到/cgi-bin/foo.lua的请求上运行/var/cgi/foo.lua

[uwsgi]
workdir = /var
ipaddress = 0.0.0.0

; start an http router on port 8080
http = %(ipaddress):8080
; enable the stats server on port 9191
stats = 127.0.0.1:9191
; spawn 2 threads in 4 processes (concurrency level: 8)
processes = 4
threads = 2
; drop privileges
uid = nobody
gid = nogroup

; serve static files in /var/www
static-index = index.html
static-index = index.htm
check-static = %(workdir)/www

; skip serving static files ending with .lua
static-skip-ext = .lua

; route requests to the CGI plugin
http-modifier1 = 9
; map /cgi-bin requests to /var/cgi
cgi = /cgi-bin=%(workdir)/cgi
; only .lua script can be executed
cgi-allowed-ext = .lua
; .lua files are executed with the 'lua' command (it avoids the need of giving execute permission to files)
cgi-helper = .lua=lua
; search for index.lua if a directory is requested
cgi-index = index.lua

Nginx支持

一般来说,你只需包含uwsgi_params文件 (包含在nginx发行版本中),使用uwsgi_pass指令来设置uWSGI socket的地址。

uwsgi_pass unix:///tmp/uwsgi.sock;
include uwsgi_params;
—— 或者如果你使用的是TCP socket,
uwsgi_pass 127.0.0.1:3031;
include uwsgi_params;

集群

对于所有的上游处理程序,Nginx支持漂亮的集群集成。

添加一个 upstream 指令到server配置块外:

upstream uwsgicluster {
  server unix:///tmp/uwsgi.sock;
  server 192.168.1.235:3031;
  server 10.0.0.17:3017;
}

然后修改你的uwsgi_pass指令:

uwsgi_pass uwsgicluster;

动态应用

当传递特殊变量的使用,uWSGI服务器可以按需加载应用。 如果请求设置了 UWSGI_SCRIPT 变量,那么服务器将会加载指定的模块:

location / {
  root html;
  uwsgi_pass uwsgicluster;
  uwsgi_param UWSGI_SCRIPT testapp;
  include uwsgi_params;
}

你甚至还可以在每个location内配置多个应用:

location / {
  root html;
  uwsgi_pass uwsgicluster;
  uwsgi_param UWSGI_SCRIPT testapp;
  include uwsgi_params;
}

location /django {
  uwsgi_pass uwsgicluster;
  include uwsgi_params;
  uwsgi_param UWSGI_SCRIPT django_wsgi;
}

在同一个进程中托管多个应用 (亦称管理SCRIPT_NAME和PATH_INFO)

WSGI标准决定了 SCRIPT_NAME 是一个用来选择特定应用的变量。不幸的是, nginx不能够根据SCRIPT_NAME重写PATH_INFO。出于这样的原因,你需要指示uWSGI在所谓的“挂载点”中映射特定的应用,并且自动重写SCRIPT_NAME和PATH_INFO:

[uwsgi]
socket = 127.0.0.1:3031
; mount apps
mount = /app1=app1.py
mount = /app2=app2.py
; rewrite SCRIPT_NAME and PATH_INFO accordingly
manage-script-name = true

[uwsgi]
socket = 127.0.0.1:3031
; mount apps
mount = the_app1=app1.py
mount = the_app2=app2.py


[uwsgi]
socket = 127.0.0.1:3031
; mount apps
mount = example.com=app1.py
mount = foobar.it=app2.py

clear environment on exit

vacuum = true


Search

    Table of Contents