如何在 Ubuntu 14.04 上使用 uWSGI 和 Nginx 服务 Flask 应用程序
介绍
在本指南中,我们将在 Ubuntu 14.04 上使用 Flask 微框架设置一个简单的 Python 应用程序。本文的大部分内容是关于如何设置 uWSGI 应用服务器来启动应用程序和 Nginx 作为前端反向代理。
先决条件
在开始本指南之前,您应该在您的服务器上配置一个非根用户。此用户需要具有 sudo
权限才能执行管理功能。要了解如何进行设置,请遵循我们的初始服务器设置指南。
要了解有关 uWSGI、我们的应用程序服务器和 WSGI 规范的更多信息,您可以阅读本指南的链接部分。理解这些概念将使本指南更容易理解。
当您准备好继续时,请继续阅读。
从 Ubuntu 存储库安装组件
我们的第一步是从存储库安装我们需要的所有部分。我们将安装 Python 包管理器 pip
,以安装和管理我们的 Python 组件。我们还将获得构建 uWSGI 所需的 Python 开发文件,我们现在也将安装 Nginx。
更新本地包索引,然后键入以下命令安装包:
sudo apt-get update
sudo apt-get install python-pip python-dev nginx
创建 Python 虚拟环境
接下来,我们将设置一个虚拟环境,以便将我们的 Flask 应用程序与系统上的其他 Python 文件隔离开来。
首先使用 pip
安装 virtualenv
包:
sudo pip install virtualenv
现在,我们可以为我们的 Flask 项目创建一个父目录。创建后进入目录:
mkdir ~/myproject
cd ~/myproject
我们可以创建一个虚拟环境来存储我们的 Flask 项目的 Python 需求,方法是输入:
virtualenv myprojectenv
这会将 Python 和 pip
的本地副本安装到项目目录中名为 myprojectenv
的目录中。
在我们在虚拟环境中安装应用程序之前,我们需要激活它。您可以通过键入以下内容来执行此操作:
source myprojectenv/bin/activate
您的提示符将发生变化,表明您现在正在虚拟环境中操作。它看起来像这样 (myprojectenv)user@host:~/myproject$
。
设置 Flask 应用程序
现在您已进入虚拟环境,我们可以安装 Flask 和 uWSGI 并开始设计我们的应用程序:
安装 Flask 和 uWSGI
我们可以使用 pip
的本地实例来安装 Flask 和 uWSGI。键入以下命令以获取这两个组件:
pip install uwsgi flask
创建示例应用程序
现在我们有了 Flask,我们可以创建一个简单的应用程序。 Flask 是一个微型框架。它不包括功能更全的框架可能包含的许多工具,并且主要作为一个模块存在,您可以将其导入到您的项目中以帮助您初始化 Web 应用程序。
虽然您的应用程序可能更复杂,但我们将在单个文件中创建我们的 Flask 应用程序,我们将其称为 myproject.py
:
nano ~/myproject/myproject.py
在这个文件中,我们将放置我们的应用程序代码。基本上,我们需要导入 flask 并实例化一个 Flask 对象。我们可以使用它来定义在请求特定路由时应该运行的函数。我们将在代码 application
中调用我们的 Flask 应用程序来复制您在 WSGI 规范中找到的示例:
from flask import Flask
application = Flask(__name__)
@application.route("/")
def hello():
return "<h1 style='color:blue'>Hello There!</h1>"
if __name__ == "__main__":
application.run(host='0.0.0.0')
这基本上定义了访问根域时要呈现的内容。完成后保存并关闭文件。
您可以通过键入以下内容来测试您的 Flask 应用程序:
python myproject.py
在您的 Web 浏览器中访问您服务器的域名或 IP 地址,然后是终端输出中指定的端口号(很可能是 :5000
)。你应该看到这样的东西:

完成后,在终端窗口中按 CTRL-C 几次以停止 Flask 开发服务器。
创建 WSGI 入口点
接下来,我们将创建一个文件作为我们应用程序的入口点。这将告诉我们的 uWSGI 服务器如何与应用程序交互。
我们将调用文件 wsgi.py
:
nano ~/myproject/wsgi.py
该文件非常简单,我们可以简单地从我们的应用程序中导入 Flask 实例,然后运行它:
from myproject import application
if __name__ == "__main__":
application.run()
完成后保存并关闭文件。
配置uWSGI
现在我们的应用程序已经编写完毕,我们的入口点也已建立。我们现在可以转向 uWSGI。
测试 uWSGI 服务
我们要做的第一件事是测试以确保 uWSGI 可以为我们的应用程序提供服务。
我们可以通过简单地将入口点的名称传递给它来做到这一点。我们还将指定套接字,以便它在公开可用的接口和协议上启动,以便它使用 HTTP 而不是 uwsgi
二进制协议:
uwsgi --socket 0.0.0.0:8000 --protocol=http -w wsgi
如果您在 Web 浏览器中访问服务器的域名或 IP 地址并在末尾附加 :8000
,您应该会看到如下所示的页面:

当您确认它正常运行时,请在您的终端窗口中按 CTRL-C。
我们现在已经完成了我们的虚拟环境,所以我们可以停用它:
deactivate
现在的任何操作都将在系统的 Python 环境中完成。
创建一个 uWSGI 配置文件
我们已经测试过 uWSGI 能够为我们的应用程序提供服务,但是我们想要更健壮的东西以供长期使用。我们可以使用我们想要的选项创建一个 uWSGI 配置文件。
让我们把它放在我们的项目目录中并将其命名为 myproject.ini
:
nano ~/myproject/myproject.ini
在内部,我们将从 [uwsgi]
标头开始,以便 uWSGI 知道应用设置。我们将通过引用我们的 wsgi.py
文件来指定模块,减去扩展名:
[uwsgi]
module = wsgi
接下来,我们将告诉 uWSGI 以主模式启动并生成五个工作进程来服务实际请求:
[uwsgi]
module = wsgi
master = true
processes = 5
当我们进行测试时,我们在一个网络端口上暴露了 uWSGI。然而,我们将使用 Nginx 来处理实际的客户端连接,然后将请求传递给 uWSGI。由于这些组件在同一台计算机上运行,因此首选 Unix 套接字,因为它更安全、速度更快。我们将调用套接字 myproject.sock
并将其放在这个目录中。
我们还必须更改套接字的权限。稍后我们将授予 uWSGI 进程的 Nginx 组所有权,因此我们需要确保套接字的组所有者可以从中读取信息并向其写入信息。我们还将通过添加 \vacuum 选项在进程停止时清理套接字:
[uwsgi]
module = wsgi
master = true
processes = 5
socket = myproject.sock
chmod-socket = 660
vacuum = true
我们需要做的最后一件事是设置 die-on-term
选项。这是必需的,因为 Upstart init 系统和 uWSGI 对于不同的进程信号应该意味着什么有不同的想法。设置此对齐两个系统组件,实现预期的行为:
[uwsgi]
module = wsgi
master = true
processes = 5
socket = myproject.sock
chmod-socket = 660
vacuum = true
die-on-term = true
您可能已经注意到我们没有像在命令行中那样指定协议。这是因为默认情况下,uWSGI 使用 uwsgi
协议进行通信,这是一种旨在与其他服务器通信的快速二进制协议。 Nginx 可以本地使用此协议,因此最好使用它而不是强制通过 HTTP 进行通信。
完成后,保存并关闭文件。
创建新贵脚本
我们需要处理的下一个部分是 Upstart 脚本。创建一个 Upstart 脚本将允许 Ubuntu 的初始化系统在服务器启动时自动启动 uWSGI 并为我们的 Flask 应用程序提供服务。
在 /etc/init
目录下创建一个以 .conf
结尾的脚本文件开始:
sudo nano /etc/init/myproject.conf
在内部,我们将从脚本目的的简单描述开始。紧接着,我们将定义系统启动和停止此脚本的条件。正常的系统运行时编号是 2、3、4 和 5,因此我们将告诉它在系统达到这些运行级别之一时启动我们的脚本。我们将告诉它在任何其他运行级别停止(例如当服务器重新启动、关闭或处于单用户模式时):
description "uWSGI server instance configured to serve myproject"
start on runlevel [2345]
stop on runlevel [!2345]
接下来,我们需要定义运行 uWSGI 的用户和组。我们的项目文件都是属于我们自己的用户账号,所以我们将自己设置为用户来运行。 Nginx 服务器在 www-data
组下运行。我们需要 Nginx 能够读取和写入套接字文件,因此我们将授予该进程的组所有权:
description "uWSGI server instance configured to serve myproject"
start on runlevel [2345]
stop on runlevel [!2345]
setuid user
setgid www-data
接下来,我们需要设置进程,以便它能够正确找到我们的文件并进行处理。我们已经将所有 Python 组件安装到虚拟环境中,因此我们需要以此为路径设置一个环境变量。我们还需要切换到我们的项目目录。之后,我们可以简单地调用 uWSGI 可执行文件并将我们编写的配置文件传递给它:
description "uWSGI server instance configured to serve myproject"
start on runlevel [2345]
stop on runlevel [!2345]
setuid user
setgid www-data
env PATH=/home/user/myproject/myprojectenv/bin
chdir /home/user/myproject
exec uwsgi --ini myproject.ini
完成后保存并关闭文件。
您可以通过键入以下内容立即开始该过程:
sudo start myproject
配置 Nginx 来代理请求
我们的 uWSGI 应用程序服务器现在应该启动并运行,等待对项目目录中套接字文件的请求。我们需要配置 Nginx 以使用 uwsgi
协议将 Web 请求传递到该套接字。
首先在 Nginx 的 sites-available
目录中创建一个新的服务器块配置文件。我们将简单地调用此 myproject
以与指南的其余部分保持一致:
sudo nano /etc/nginx/sites-available/myproject
打开一个服务器块并告诉 Nginx 在默认端口 80 上侦听。我们还需要告诉它使用这个块来请求我们服务器的域名或 IP 地址:
server {
listen 80;
server_name server_domain_or_IP;
}
我们唯一需要添加的另一件事是匹配每个请求的位置块。在此块中,我们将包含 uwsgi_params
文件,该文件指定需要设置的一些通用 uWSGI 参数。然后我们将请求传递到我们使用 uwsgi_pass
指令定义的套接字:
server {
listen 80;
server_name server_domain_or_IP;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/user/myproject/myproject.sock;
}
}
这实际上就是我们为应用程序提供服务所需的全部。完成后保存并关闭文件。
要启用我们刚刚创建的 Nginx 服务器块配置,请将文件链接到 sites-enabled
目录:
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
使用该目录中的文件,我们可以通过键入以下内容来测试语法错误:
sudo nginx -t
如果返回时没有任何问题,我们可以重新启动 Nginx 进程以读取我们的新配置:
sudo service nginx restart
您现在应该能够在 Web 浏览器中转到服务器的域名或 IP 地址并查看您的应用程序:

结论
在本指南中,我们在 Python 虚拟环境中创建了一个简单的 Flask 应用程序。我们创建一个 WSGI 入口点,以便任何支持 WSGI 的应用程序服务器都可以与之交互,然后配置 uWSGI 应用程序服务器以提供此功能。之后,我们创建了一个 Upstart 脚本来在启动时自动启动应用程序服务器。我们创建了一个 Nginx 服务器块,将 Web 客户端流量传递到应用程序服务器,中继外部请求。
Flask 是一个非常简单但极其灵活的框架,旨在为您的应用程序提供功能,而不会过多地限制结构和设计。您可以使用本指南中描述的通用堆栈来为您设计的 Flask 应用程序提供服务。