采用 Tornado WSGI 容器部署 Flask 为 Systemd 服务并使用 Apache2 进行反向代理的方法

本文介绍了如何通过 Tornado,在 Virtualenv 下将 Flask 应用以独立 WSGI 容器的形式部署,并配置为 Systemd 服务和使用 Apache2 进行反向代理以提供 SSL 的方式。本文使用的是 Ubuntu 18.04 系统,您的系统可能因为发行版不同而在操作和配置上有所差异,敬请注意。

编写 Tornado 代码

首先参照 Flask 官方文档的代码,编写一个 Tornado 入口文件。

1
2
3
4
5
6
7
8
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from <开发时 Flask 的入口文件> import app

http_server = HTTPServer(WSGIContainer(app))
http_server.listen(<端口号>)
IOLoop.instance().start()

<> 包裹起来的部分,替换为自己的代码。随后,将这个文件放入 Python 代码的根目录。

依赖安装

使用 Virtualenv 内的 pip 命令安装依赖,本文不再赘述。

配置 Systemd

/lib/systemd/system(可能因系统发行版不同而不同,也可能在 /usr/lib/systemd/system 中)建立一个新的服务文件,名字可以自己去,但是要以 .service 结尾。如:flask-wsgi-application.service

在文件中加入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=<服务描述>
After=network.target

[Service]
Type=simple
User=<用户名称,可以为 nobody 以提升安全性>
Restart=on-failure
RestartSec=<崩溃后多少秒重启,如:5s>
WorkingDirectory=<工作目录,选择为代码根目录,如:/var/flaskapp>
ExecStart=<Virtualenv Python 二进制文件的地址,如:/var/flaskapp/venv/bin/python3> <Tornado 代码入口文件,如:/var/flaskapp/tornado_wsgi_start.py>

[Install]
WantedBy=multi-user.target

<> 包裹起来的部分,替换为自己的代码。选择工作目录的目的,是使得 Virtualenv 能够正常启动。

启用 Systemd

1
2
systemctl enable flask-wsgi-application
service flask-wsgi-application start

将命令中的 flask-wsgi-application 替换为你的服务文件名(不含 .service 后缀)。根据情况,可以使用 sudo 命令。

配置反向代理

/etc/apache2/sites-available/ 下创建站点的配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
<VirtualHost *:80>
ServerName <域名>

ErrorLog ${APACHE_LOG_DIR}/<错误日志文件名>
CustomLog ${APACHE_LOG_DIR}/<访问日志文件名> combined

<Location />
ProxyPass http://127.0.0.1:<Tornado 文件内的端口号>/
ProxyPassReverse http://127.0.0.1:<Tornado 文件内的端口号>/
ProxyPreserveHost On
</Location>
</VirtualHost>

如果要启用 SSL,需要在配置文件末尾加入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<VirtualHost *:443>
ServerName <域名>

ErrorLog ${APACHE_LOG_DIR}/<错误日志文件名>
CustomLog ${APACHE_LOG_DIR}/<访问日志文件名> combined

SSLEngine on
SSLCertificateFile <证书文件地址>
SSLCertificateKeyFile <证书私钥地址>

<Location />
ProxyPass http://127.0.0.1:<Tornado 文件内的端口号>/
ProxyPassReverse http://127.0.0.1:<Tornado 文件内的端口号>/
ProxyPreserveHost On
</Location>
</VirtualHost>

最后执行 a2ensite <你的 Apache2 配置文件名称> 即可。