一、概述
WSGI 、uWSGI 和 uwsgi 是三个相关的概念,它们是在 Web 运用程序开发中运用的不同的工具和协议。下面是它们的详细介绍:
-
WSGI(Web Server Gateway Interface)
:WSGI 是一个 Python Web 运用程序与 Web 服务器之间的接口标准,它界说了运用程序和服务器之间的标准接口,使得运用程序能够在不同的 Web 服务器上运转。WSGI 标准规则了运用程序有必要完成的接口方法和服务器需求支撑的方法。WSGI 协议使得不同的 Python Web 结构(例如 Flask、Django 等)能够在不同的 Web 服务器上运转,这些服务器能够是 Apache、Nginx 等。 -
uWSGI
:uWSGI 是一个 Web 服务器,它是一个用 C 语言编写的 Web 运用程序容器,支撑运转 Python、Ruby、Perl 等多种编程语言。uWSGI 服务器能够作为一个独立的运用服务器,也能够与其他 Web 服务器(如 Nginx、Apache)一起运用,经过 WSGI 协议与 Python 运用程序通讯。 -
uwsgi
:uwsgi 是一个与 uWSGI 服务器相关的协议。uwsgi 协议是一种二进制协议,它界说了 uWSGI 服务器与运用程序之间的通讯协议。运用 uwsgi 协议,uWSGI 服务器能够与 Python 运用程序通讯,而不需求像 CGI 那样发动一个新的进程来处理每个恳求。uwsgi 协议允许 uWSGI 服务器与运用程序之间进行双向通讯,从而提高了性能。
因此,uWSGI 是一个 Web 服务器,能够经过 WSGI 协议与 Python 运用程序通讯,并运用 uwsgi 协议进行通讯。WSGI 是 Python Web 运用程序与 Web 服务器之间的接口标准,界说了运用程序和服务器之间的标准接口。而 uwsgi 则是 uWSGI 服务器与运用程序之间的二进制通讯协议。
二、装置 uwsgi 模块
uWSGI 是一种 Web 服务器网关接口(Web Server Gateway Interface),它能够用于将 Python Web 运用程序与 Web 服务器(如 Nginx 或 Apache)集成在一起。
-
在运用uWSGI模块时,需求装置
uwsgi
模块,并在Python Web运用程序中导入uwsgi
模块,并运用uwsgi模块提供的函数来装备和办理Web运用程序的运转。常见的uwsgi模块函数包括uwsgi.optin()、uwsgi.route()、uwsgi.applications()等。 -
别的,uWSGI模块还提供了一些高档特性,如Master/Worker形式、进程办理、负载均衡、主动扩展等,使得Web运用程序能够更好地习惯高并发和大流量的状况。
1)装备pip源
国内源地址:
- pypi 清华大学源:pypi.tuna.tsinghua.edu.cn/simple
- pypi 腾讯源:mirrors.cloud.tencent.com/pypi/simple
- pypi 阿里源:mirrors.aliyun.com/pypi/simple…
mkdir ~/.pip/
cat >~/.pip/pip.conf<<EOF
[global]
index-url = https://repo.huaweicloud.com/repository/pypi/simple
trusted-host = repo.huaweicloud.com
timeout = 120
EOF
2)装置 uwsgi 模块
# 装置python3
yum -y install python3
yum -y install gcc-c++ -y
yum -y install python3-devel -y
# 装置 uwsgi flask 模块
pip3 install uwsgi flask
# 检查版别
uwsgi --version
三、示例演示(uWSGI + Nginx 装备)
1)装置 nginx
yum update -y
yum install epel-release
yum -y install nginx
2)创立 app.py 文件
创立一个名为 app.py
的文件,增加以下代码:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
3)创立 uWSGI 装备文件
创立一个 uWSGI 装备文件,例如 uwsgi.ini
,其间包括以下信息:
[uwsgi]
module = app:app
# 相当于指令下面两行
#wsgi-file = app.py # 项目入口文件
#callable = app # flask运用目标
# 支撑http+socket两种方法,这儿选用socket,也能够选择http-socket,下面会解说这三种差异
# http = 127.0.0.1:8000
socket = 0.0.0.0:8000
# 也能够运用socket文件,在nginx装备文件中装备也对应,仅限本机通讯,一般也很少运用
# socket = /app/myapp.sock
# 留意记住提前创立目录
chdir = /opt/myapp
pidfile=/opt/myapp/myapp.pid
processes = 4
threads = 2
master = true
vacuum = true
py-autoreload = 1
daemonize = /tmp/uwsgi.log
uwsgi.ini常用装备参数详解:
-
chdir
=/xxx/xxx # 指定项目目录, 这儿写上程序根目录(即app.py
文件地点目录)对应上述目录结构为src
-
home
=/xxx/xxx # 指定虚拟环境变量 -
wsgi-file
=xxx # 指定加载WSGI文件 -
socket
=xxx # 指定uwsgi的客户端将要衔接的socket的途径(运用UNIX socket的状况)或许地址(运用网络地址的状况)。#socket协议,用于和nginx通讯,端口可装备成其他端口;假如有nginx在uwsgi之前作为署理的话应该配socket 如:socket=0.0.0.0:5000。当然也能够运用http-socket
#而假如客户端恳求不经过(不搭建)Nginx署理服务器,服务恳求直接到uwsgi服务器的话那么就配http。如:http=0.0.0.0:5000;IP和端口与项目发动文件app.py中共同; 127.0.0.1尽管是表明本地IP,但想要在网络上拜访有必要设置host=0.0.0.0才不受IP限制。 -
callable
=app # 这个 app 指的是 flask 项目发动程序中界说的 flask name 的名字,我的发动程序是 app.py , 里面界说的 flask 的名字是 app 。 -
module
= mysite.wsgi # 加载一个WSGI模块,这儿加载mysite/wsgi.py这个模块 - `master=true # 指定发动主进程
- `processes=4 # 设置工作进程的数量
-
threads
=2 # 设置每个工作进程的线程数 -
vacuum
=true # 当服务器退出时主动删除unix socket文件和pid文件 -
logfile-chmod
=644 # 指定日志文件的权限 -
daemonize
=%(chdir)/xxx.log # 进程在后台运转,并将日志打印到指定文件 -
pidfile
=%(chdir)/xxx.pid # 在失去权限前,将主进程pid写到指定的文件 -
uid
=xxx # uWSGI服务器运转时的用户id -
gid
=xxx # uWSGI服务器运转时的用户组id -
procname-prefix-spaced
=xxx # 指定工作进程名称的前缀 -
chdir
=/xxx/xxx # 指定项目目录, 这儿写上程序根目录(即app.py
文件地点目录)对应上述目录结构为/opt/uwsgi/
-
listen
= 120 # 设置socket的监听队列大小(默许:100)
4)发动 uWSGI
在指令行中发动 uWSGI:
uwsgi --ini uwsgi.ini
###或许
uwsgi uwsgi.ini
### 重启
uwsgi --reload /opt/myapp/myapp.pid
###封闭
uwsgi --stop /opt/myapp/myapp.pid
【温馨提示】其实也能够经过一条指令带上对应的参数即可发动,可是不引荐,测试能够。一般运用装备文件的方法发动服务。
运用http协议发动uwsgi的指令为:
uwsgi --http :8000 --ini uwsgi_conf.ini -d ./uwsgi.log --pidfile=uwsgi.pid
-
--http
指定用5800端口发动http协议 -
--ini
指定上述的发动装备文件 -
-d
指定uwsgi的log,便利咱们调试 -
--pidfile
将发动的进程号写到uwsgi.pid
文件中,便利咱们在需求停止服务器时kill掉。
5)装备 Web 服务器
将 Web 服务器装备为反向署理 uWSGI,例如,在 Nginx 中,能够运用以下装备文件:
# vi /etc/nginx/conf.d/myapp.conf
server {
listen 8080;
server_name myapp.com;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8000;
}
}
其间,uwsgi_params
文件包括以下内容:
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
【特别留意】
uwsgi_params
在nginx conf文件夹下自带,uwsgi_pass一定要跟uwsgi_conf.ini中写的地址完全共同。
6)重启 Web 服务器
重启 Web 服务器以使装备生效。
# 重启
systemctl restart nginx
# 假如是之前nginx服务现已存在,只是修正了装备,可主张运用reload加载
nginx -t && nginx -s reload
# 或许
systemctl reload nginx
拜访(浏览器拜访,curl拜访也行)
7)Nginx upstream 负载均衡
Nginx上游(upstream)是指一组后端服务器,Nginx能够与其通讯并将客户端恳求转发到这些服务器。换句话说,上游服务器是Nginx署理恳求的后端服务器。
Nginx的upstream支撑5种 分配方法,其间 轮询(默许)、权重、IP散列这三种为Nginx原生支撑的分配方法,fair
和 url_hash
为第三方支撑的分配方法。
1、轮询(默许)
轮询是upstream
的默许分配方法,即每个恳求依照时刻顺序轮番分配到不同的后端服务器,假如某个后端服务器 down 掉后,能主动除掉。
upstream backend {
server 192.168.182.110:8000;
server 192.168.182.111:8000;
}
2、权重(weight)
轮询的加强版,既能够指定轮询比率,weight 和拜访几率成正比,首要运用于后端服务器异质的场景下。
upstream backend {
server 192.168.182.110:8000 weight=1;
server 192.168.182.111:8000 weight=2;
}
3、IP散列(ip_hash)
每个恳求依照拜访 Ip(即Nginx的前置服务器或客户端IP)的 hash成果分配,这样每个访客会固定拜访一个后端服务器,能够处理 session 共同问题。
upstream backend {
ip_hash;
server 192.168.182.110:8000 weight=1;
server 192.168.182.111:8000 weight=2;
}
先在别的一个节点上再起一个uWSGI服务,将上面示例装备修正:
# vi /etc/nginx/conf.d/myapp.conf
upstream backend {
server 192.168.182.110:8000;
server 192.168.182.111:8000;
}
server {
listen 8080;
server_name myapp.com;
location / {
include uwsgi_params;
uwsgi_pass backend;
}
}
192.168.182.110 节点 app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World 192.168.182.110!\n'
if __name__ == '__main__':
app.run()
192.168.182.111 节点 app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World 192.168.182.111!\n'
if __name__ == '__main__':
app.run()
验证
curl 127.0.0.1:8080
从上图可知,恳求轮询调度,这才是企业一般想要的效果,负载均衡。
8)http、http-socket 和 socket 差异
-
http
和http-socket
的差异在于,假如咱们想直接将uwsgi用作服务器(例如Apache和nginx那样)直接暴露在公网那么就运用http
; - 假如有独自的服务器(例如Apache或许nginx),由服务器将恳求转发给uwsgi处理,而且运用
http
协议,那么此刻运用http-socket
。 -
http
: 自己会发生一个http进程(能够以为与nginx同一层)担任路由http
恳求给worker
,http
进程和worker
之间运用的是uwsgi协议。 -
http-socket
: 不会发生http进程, 一般用于在前端webserver不支撑uwsgi
而仅支撑http时运用, 他发生的worker运用的是http协议。 - 因此,
http
一般是作为独立部署的选项;http-socket
在前端webserver不支撑uwsgi时运用, 假如前端webserver支撑uwsgi, 则直接运用socket即可(tcp or unix)。
【1】socket
示例(uwsgi.ini):
[uwsgi]
module = app:app
#socket = 127.0.0.1:8000
socket = 0.0.0.0:8000
chdir = /opt/myapp
pidfile=/opt/myapp/myapp.pid
processes = 4
threads = 2
master = true
vacuum = true
py-autoreload = 1
daemonize = /tmp/uwsgi.log
nginx装备
upstream backend {
server 192.168.182.110:8000;
server 192.168.182.111:8000;
}
server {
listen 8080;
server_name myapp.com;
location / {
include uwsgi_params;
uwsgi_pass backend;
}
}
【2】http
示例(uwsgi.ini):
[uwsgi]
module = app:app
socket = 0.0.0.0:8000
chdir = /opt/myapp
pidfile=/opt/myapp/myapp.pid
processes = 4
threads = 2
master = true
vacuum = true
py-autoreload = 1
daemonize = /tmp/uwsgi.log
nginx装备
upstream backend {
server 192.168.182.110:8000;
server 192.168.182.111:8000;
}
server {
listen 8080;
server_name myapp.com;
location / {
include uwsgi_params;
proxy_pass http://backend;
}
}
【3】http-socket
示例(uwsgi.ini):
[uwsgi]
module = app:app
http = 0.0.0.0:8000
chdir = /opt/myapp
pidfile=/opt/myapp/myapp.pid
processes = 4
threads = 2
master = true
vacuum = true
py-autoreload = 1
daemonize = /tmp/uwsgi.log
nginx装备
upstream backend {
server 192.168.182.110:8000;
server 192.168.182.111:8000;
}
server {
listen 8080;
server_name myapp.com;
location / {
include uwsgi_params;
proxy_pass http://backend;
}
}
9)TCP 与 uinx 差异
TCP和Unix套接字(Unix domain socket)是两种不同类型的套接字。
-
TCP套接字是基于TCP/IP协议的网络套接字,用于在网络上进行进程间通讯。TCP套接字需求指定IP地址和端口号,以便其他进程能够衔接到该套接字进行通讯。TCP套接字是一种跨网络边界的套接字,能够在不同的核算机之间进行通讯。TCP套接字常用于客户端/服务器架构中,如Web服务器、数据库服务器等。
-
Unix套接字是基于Unix域套接字(Unix domain socket)的本地套接字,用于在同一台核算机上进行进程间通讯。Unix套接字只需求指定一个文件途径,而不需求运用IP地址和端口号。Unix套接字是一种进程间通讯(IPC)机制,它提供了高效、可靠和安全的进程间通讯方法。Unix套接字一般用于本地服务器和本地客户端之间的通讯,例如X Window体系中的客户端和服务器。
因此,TCP套接字用于在网络上进行通讯,而Unix套接字用于在同一台核算机上进行通讯。尽管TCP套接字能够经过网络衔接到不同的核算机,可是Unix套接字提供了更高效的进程间通讯机制,而且更适合于需求在同一台核算机上运转的进程间通讯。
【TCP 示例】常用
uwsgi.ini
:
[uwsgi]
module = app:app
socket = 127.0.0.1:8000
chdir = /opt/myapp
pidfile=/opt/myapp/myapp.pid
processes = 4
threads = 2
master = true
vacuum = true
py-autoreload = 1
daemonize = /tmp/uwsgi.log
【unix 示例】仅限于本机通讯,很少运用。
uwsgi.ini
:
[uwsgi]
module = app:app
socket = /opt/myapp/myapp.socket
chdir = /opt/myapp
pidfile=/opt/myapp/myapp.pid
processes = 4
threads = 2
master = true
vacuum = true
py-autoreload = 1
daemonize = /tmp/uwsgi.log
nginx装备
server {
listen 8080;
server_name myapp.com;
location / {
include uwsgi_params;
proxy_pass unix:///opt/myapp/myapp.sock;
}
}
Python 中 web开发中的 WSGI、uWSGI 和 uwsgi 三者介绍就先到这儿了,有任何疑问欢迎给我留言或私信,也可重视我的大众号【大数据与云原生技术共享】深入技术交流~