什么是uWSGI?

uWSGI(官方写法为"uWSGI")是一个Web服务器和应用服务器,用于将Web应用程序和Web服务器之间进行通信。它充当Web服务器和Python Web应用程序之间的桥梁,实现了WSGI协议(Web Server Gateway Interface)的处理。

uwsgi、uWSGI和WSGI辨析

WSGI(Web Server Gateway Interface):
WSGI是Python Web应用程序与Web服务器之间的接口规范。它定义了Web应用程序如何与Web服务器进行通信,以便能够处理HTTP请求并生成HTTP响应。WSGI规范旨在提供一种标准的方式来连接Web应用程序和Web服务器,使不同的Web框架和Web服务器能够无缝协作。

uWSGI(官方写法为"uWSGI"):
uWSGI是一个用于实现WSGI协议的Web服务器和应用服务器。它是一个独立的软件项目,提供了一个功能强大且灵活的服务器,用于将Web服务器(如Nginx或Apache)与Python Web应用程序(如Django或Flask)连接起来。uWSGI可以处理大量并发连接,并提供了各种高级功能,如负载均衡、缓存、自动扩展等。

uwsgi(小写的"uwsgi"):
uwsgi是uWSGI服务器的一种通信协议,用于定义uWSGI服务器与Web服务器之间的数据传输格式。uwsgi协议是uWSGI服务器与Web服务器之间进行通信的一种标准化协议。uWSGI服务器可以通过uwsgi协议与Web服务器进行通信,从而实现Web应用程序的处理。

总结来说,WSGI是Python Web应用程序与Web服务器之间的接口规范,uWSGI是一个实现了WSGI协议的Web服务器和应用服务器,而uwsgi是uWSGI服务器与Web服务器之间的通信协议。它们共同构成了将Python Web应用程序与Web服务器进行连接和通信的基础架构。

为什么需要uWSGI?

在生产环境中部署Python Web项目时,uWSGI负责处理Nginx转发的动态请求,并与我们的Python应用程序沟通,同时将应用程序返回的响应数据传递给Nginx。

客户端 <-> Nginx <-> uWSGI <-> Python应用程序(Django, Flask)

Nginx本身就是Web服务器,我们为什么还需要uWSGI这个Web服务器呢? Django不是自带runserver服务器?Flask不是自带Werkzeug吗? 答案是Nginx处理静态文件非常优秀,却不能直接与我们的Python Web应用程序进行交互。Django和Flask本身是Web框架,并不是Web服务器,它们自带的runserver和Werkzeug也仅仅用于开发测试环境,生产环境中处理并发的能力太弱。

为了解决Web 服务器与应用程序之间的交互问题,就出现了Web 服务器与应用程序之间交互的规范。最早出现的是CGI,后来又出现了改进 CGI 性能的FasgCGI,Java 专用的 Servlet 规范。在Python领域,最知名的就是WSGI规范了。

WSGI 全称是 Web Server Gateway Interface,也就是 Web 服务器网关接口,是一个web服务器(如uWSGI服务器)与web应用(如用Django或Flask框架写的程序)通信的一种规范。WSGI包含了很多自有协议,其中一个是uwsgi,它用于定义传输信息的类型。

uWSGI的安装

pip install uwsgi

为了测试uWSGI安装是否成功,可以编写一个test.py的测试文件,添加如下代码:

def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]

然后使用如下命令启动uWSGI Web服务器, 端口8080.

uwsgi --http :8080 --wsgi-file test.py

如果你已经有了一个现成的Django项目,你可以使用如下命令启动Web服务。

# 使用uwsgi命令行启动Django项目,端口8000
$ uwsgi --http :8000 --module myproject.wsgi

在生产环境中我们通常不会使用命令行启动Python Web项目,而是通常编辑好uWSGI配置文件uwsgi.ini, 然后使用如下命令启动Python Web项目。

# 使用uwsgi.ini配置文件启动Django应用程序
$ uwsgi --ini uwsgi.ini

uWSGI 常用命令

# 启动uWSGI服务器
$ uwsgi --ini uwsgi.ini

# 重启uWSGI服务器
$ sudo service uwsgi restart

# 查看所有uWSGI进程
$ ps aux | grep uwsgi

# 停止所有uWSGI进程
$ sudo pkill -f uwsgi -9

uWSGI常用配置
uWSGI常用配置选项如下所示,稍加修改(项目名,项目根目录)即可部署大部分Python Web项目。

[uwsgi]
uid=www-data # Ubuntu系统下默认用户名
gid=www-data # Ubuntu系统下默认用户组
project=mysite1  # 项目名
base = /home/user1 # 项目根目录

home = %(base)/Env/%(project) # 设置项目虚拟环境,Docker部署时不需要
chdir=%(base)/%(project) # 设置工作目录
module=%(project).wsgi:application # wsgi文件位置

master=True # 主进程
processes=2 # 同时进行的进程数,一般

# 选项1, 使用unix socket与nginx通信,仅限于uwsgi和nginx在同一主机上情形
# Nginx配置中uwsgi_pass应指向同一socket文件
socket=/run/uwsgi/%(project).sock

# 选项2,使用TCP socket与nginx通信
# Nginx配置中uwsgi_pass应指向uWSGI服务器IP和端口
# socket=0.0.0.0:8000 或则 socket=:8000

# 选项3,使用http协议与nginx通信
# Nginx配置中proxy_pass应指向uWSGI服务器一IP和端口
# http=0.0.0.0:8000 

# socket权限设置
chown-socket=%(uid):www-data
chmod-socket=664

# 进程文件
pidfile=/tmp/%(project)-master.pid

# 以后台守护进程运行,并将log日志存于temp文件夹。
daemonize=/var/log/uwsgi/%(project).log 

# 服务停止时,自动移除unix socket和pid文件
vacuum=True

# 为每个工作进程设置请求数的上限。当处理的请求总数超过这个量,进程回收重启。
max-requests=5000

# 当一个请求花费的时间超过这个时间,那么这个请求都会被丢弃。
harakiri=60

#当一个请求被harakiri杀掉会,会输出一条日志
harakiri-verbose=true

# uWsgi默认的buffersize为4096,如果请求数据超过这个量会报错。这里设置为64k
buffer-size=65536

# 如果http请求体的大小超过指定的限制,打开http body缓冲,这里为64k
post-buffering=65536

#开启内存使用情况报告
memory-report=true

#设置平滑的重启(直到处理完接收到的请求)的长等待时间(秒)
reload-mercy=10

#设置工作进程使用虚拟内存超过多少MB就回收重启
reload-on-as=1024

uWSGI和Nginx之间的通信方式
unix socket,http-socket和http。Nginx的配置必需与uwsgi配置保持一致。

# 选项1, 使用unix socket与nginx通信
# 仅限于uwsgi和nginx在同一主机上情形
# Nginx配置中uwsgi_pass应指向同一socket文件地址
socket=/run/uwsgi/%(project).sock

# 选项2,使用TCP socket与nginx通信
# Nginx配置中uwsgi_pass应指向uWSGI服务器IP和端口
socket==0.0.0.0:8000 或则 socket=:8000

# 选项3,使用http协议与nginx通信
# Nginx配置中proxy_pass应指向uWSGI服务器IP和端口
http==0.0.0.0:8000 

如果你的nginx与uwsgi在同一台服务器上,优先使用本地机器的unix socket进行通信,这样速度更快。此时nginx的配置文件如下所示:

location / {     
    include /etc/nginx/uwsgi_params;
    uwsgi_pass unix:/run/uwsgi/django_test1.sock;
}

如果nginx与uwsgi不在同一台服务器上,两者使用TCP socket通信,nginx可以使用如下配置:

location / {     
    include /etc/nginx/uwsgi_params;
    uwsgi_pass uWSGI_SERVER_IP:8000;
}

如果nginx与uwsgi不在同一台服务器上,两者使用http协议进行通信,nginx配置应修改如下:

location / {     
    # 注意:proxy_pass后面http必不可少哦!
    proxy_pass http://uWSGI_SERVER_IP:8000;
}

include字段解析
include字段在Nginx配置中的作用是包含外部文件或模块的配置内容。它允许将其他文件中的配置指令包含到当前的配置文件中,以便实现代码的模块化和重用。

具体来说,include指令用于将指定路径下的文件内容包含到当前位置。这些被包含的文件可以包含Nginx的配置指令、变量定义、映射规则、缓存规则等。

include指令可以用于以下场景:

分割配置文件:将大型的Nginx配置文件分割为多个小文件,使得配置更加清晰和易于维护。可以根据不同的功能或服务,将相关的配置指令放在不同的文件中,并使用include指令将它们包含到主配置文件中。

共享配置片段:如果有多个Nginx服务器或虚拟主机需要共享一些相同的配置片段,可以将这些公共配置片段放在一个独立的文件中,并在需要的地方使用include指令进行引用。这样可以避免重复编写相同的配置,提高代码的重用性和可维护性。

引入第三方模块的配置:某些功能可能需要额外的第三方模块或插件来实现。这些模块通常会提供自己的配置文件,我们可以使用include指令将这些配置文件包含到主配置文件中,以启用这些模块的功能。

uwsgi_pass和proxy_pass的区别

uwsgi_pass和proxy_pass是Nginx配置中用于将请求转发到不同类型后端服务器的指令,它们有以下区别:

uwsgi_pass:
uwsgi_pass用于将请求转发给uwsgi服务器,通过uwsgi协议与后端uwsgi应用程序进行通信。uwsgi服务器是专门用于处理uwsgi协议的服务器,它能够直接与uwsgi应用程序进行交互,提供更高效和定制化的通信方式。当使用uwsgi_pass指令时,Nginx会将请求直接传递给uwsgi服务器,而不会进行HTTP协议的解析和转发。

proxy_pass:
proxy_pass用于将请求转发给HTTP或HTTPS服务器,通过HTTP协议与后端应用程序进行通信。这个后端服务器可以是任何支持HTTP协议的服务器,如Nginx、Apache、Node.js等。当使用proxy_pass指令时,Nginx会充当反向代理服务器,接收客户端的请求,并将其转发给后端的HTTP服务器进行处理。

所以,主要区别在于通信协议的不同。uwsgi_pass用于与uwsgi服务器之间的uwsgi协议通信,而proxy_pass用于与HTTP或HTTPS服务器之间的HTTP协议通信。具体使用哪个指令取决于后端服务器的类型和所需的通信协议。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐