上次说到了 Flask,接触到 uWSGI。在实际生产环境,一般采用 Nginx + uWSGI + Flask 的组合方式。

  • Nginx 负责提供对外的 Web 服务;
  • uWSGI 充当中间件,桥接对外的 Web 服务和实际的应用服务;
  • Flask 提供应用服务,完成业务逻辑;

1 Nginx 配置

在这里,使用 Nginx 的主要目的如下:

  1. 安全。客户端对 Web 服务器的访问需要先经过 Nginx。这样可以防止外部程序直接对应用服务器的恶意攻击;
  2. 负载均衡。在有多个应用服务器的情况下,Nginx 可以根据应用服务器的负载情况,动态地把请求交给不同的应用服务器来处理;
  3. 提升 IO 性能。一个 HTTP 请求的数据,从客户端传输给服务器,是需要时间的,例如 N 秒,如果直接传给应用服务器,应用服务器就需要让一个进程(或线程)阻塞 N 秒,进行 IO 操作,这样会降低应用服务器的性能。如果先让 Nginx 接收完整的 HTTP 请求,再把请求发给应用服务器,就能提升应用服务器的性能。还有一些静态文件的请求,可以直接交给 Nginx 来处理,不需要经过应用服务器,降低了应用服务器的 QPS。

但是默认情况下,Nginx 不具备 WSGI 规范的能力,需要通过 ngx_http_uwsgi_module 模块进行扩展,这个模块默认已经集成在 Nginx,所以不需要重新编译 Nginx。

# 修改 Nginx 配置
sudo vi /etc/nginx/sites-enabled/default

# 修改 location 部分
location / {
	include        uwsgi_params;
	uwsgi_pass     127.0.0.1:5051;
	uwsgi_param UWSGI_CHDIR  /data/projects/flaskr;
	uwsgi_param UWSGI_SCRIPT app:app;
}

# 保存配置,并重新加载
sudo systemctl reload nginx

2 uWSGI 配置

Python 默认情况下,没有 uWSGI,所以需要手动安装一下:

sudo pip3 install uwsgi

之后,在 Flask 项目中,创建 uWSGI 的配置文件 /data/projects/flaskr/uwsgi_config.ini,并配置如下:

[uwsgi]
socket = 127.0.0.1:5051
master = true
project = /data/projects/flaskr/
pythonpath = %(project)
module = app
wsgi-file = %(project)/app.py
callable = app
processes = 1
threads = 1
daemonize = %(project)/server.log
stats = %(project)/uwsgi/uwsgi.status
pidfile = %(project)/uwsgi/uwsgi.pid

3 Flask 应用

编写一个简单的 Flask 应用,先用来测试。创建 /data/projects/flaskr/app.py 文件,并输入:

# -*- coding: utf-8 -*-
__author__ = "winking324@gmail.com"
__copyright__ = "Copyright (c) 2019 winking.io, Inc."


from flask import Flask


app = Flask(__name__, instance_relative_config=True)


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    app.run()

使用 uwsgi 命令启动 Flask 应用服务:

uwsgi --ini /data/projects/flaskr/uwsgi_config.ini

如果需要重启 uwsgi,使用:

uwsgi --reload /data/projects/flaskr/uwsgi/uwsgi.pid

如果需要停止服务,使用:

uwsgi --stop /data/projects/flaskr/uwsgi/uwsgi.pid

4 请求测试

在浏览器中,访问对应 Nginx 的地址,会在浏览器中显示 Hello world!

5 参考链接