如何在 Ubuntu 16.04 上使用 uWSGI 和 Nginx 提供 Flask 应用程序

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站

简介

在本指南中,我们将在 Ubuntu 16.04 上使用 Flask 微框架设置一个简单的 Python 应用程序。本文的大部分内容将介绍如何设置 uWSGI 应用服务器来启动应用程序,并使用 Nginx 作为前端反向代理。

先决条件

在开始本指南之前,您应该在服务器上配置一个非根用户。该用户需要具有 sudo 权限,以便可以执行管理功能。要了解如何设置,请参阅我们的初始服务器设置指南。

要了解更多关于 uWSGI、我们的应用服务器和 WSGI 规范的信息,您可以阅读本指南的相关部分。了解这些概念将使本指南更容易理解。

当您准备好继续时,请继续阅读。

从 Ubuntu 仓库安装组件

我们的第一步将是从仓库中安装我们需要的所有组件。我们将安装 pip,即 Python 包管理器,以便安装和管理我们的 Python 组件。我们还将获取构建 uWSGI 所需的 Python 开发文件,并立即安装 Nginx。

我们需要更新本地软件包索引,然后安装这些软件包。您需要的软件包取决于您的项目是使用 Python 2 还是 Python 3。

如果您使用 Python 2,请输入:

sudo apt-get update
sudo apt-get install python-pip python-dev nginx

如果您使用 Python 3,请输入:

sudo apt-get update
sudo apt-get install python3-pip python3-dev nginx

创建 Python 虚拟环境

接下来,我们将设置一个虚拟环境,以便将我们的 Flask 应用程序与系统上的其他 Python 文件隔离开来。

首先,使用 pip 安装 virtualenv 包。

如果您使用 Python 2,请输入:

sudo pip install virtualenv

如果您使用 Python 3,请输入:

sudo pip3 install virtualenv

现在,我们可以在我们的 Flask 项目的父目录中创建一个虚拟环境。创建后,进入该目录:

mkdir ~/myproject
cd ~/myproject

我们可以通过输入以下命令来创建一个虚拟环境,以存储我们的 Flask 项目的 Python 需求:

virtualenv myprojectenv

这将在您的项目目录中的名为 myprojectenv 的目录中安装 Python 和 pip 的本地副本。

在虚拟环境中安装应用程序之前,我们需要激活它。您可以通过输入以下命令来激活它:

source myprojectenv/bin/activate

您的提示符将更改以指示您现在正在虚拟环境中操作。它看起来类似于 (myprojectenv)user@host:~/myproject$

设置 Flask 应用程序

现在您已经在虚拟环境中,我们可以安装 Flask 和 uWSGI,并开始设计我们的应用程序:

安装 Flask 和 uWSGI

我们可以使用本地的 pip 实例来安装 Flask 和 uWSGI。输入以下命令来获取这两个组件:

pip install uwsgi flask

创建一个示例应用

现在我们有了 Flask,我们可以创建一个简单的应用程序。Flask 是一个微框架。它不包括许多更全面的框架可能包含的工具,主要作为一个模块存在,您可以将其导入到您的项目中,以帮助您初始化 Web 应用程序。

虽然您的应用程序可能更复杂,我们将在一个名为 myproject.py 的单个文件中创建我们的 Flask 应用程序:

nano ~/myproject/myproject.py

在这个文件中,我们将放置我们的应用程序代码。基本上,我们需要导入 Flask 并实例化一个 Flask 对象。我们可以使用它来定义在请求特定路由时应运行的函数:


from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

这基本上定义了在访问根域时要呈现的内容。完成后保存并关闭文件。

如果您遵循了初始服务器设置指南,您应该已经启用了 UFW 防火墙。为了测试我们的应用程序,我们需要允许访问端口 5000。

通过输入以下命令打开端口 5000:

sudo ufw allow 5000

现在,您可以通过输入以下命令来测试您的 Flask 应用程序:

python myproject.py

在 Web 浏览器中访问您的服务器域名或 IP 地址,后面加上 :5000

http://server_domain_or_IP:5000

您应该会看到类似于以下内容:

!Flask sample app

完成后,在终端窗口中多次按下 CTRL-C 以停止 Flask 开发服务器。

创建 WSGI 入口点

接下来,我们将创建一个文件,作为应用程序的入口点。这将告诉我们的 uWSGI 服务器如何与应用程序交互。

我们将把文件命名为 wsgi.py

nano ~/myproject/wsgi.py

这个文件非常简单,我们只需从我们的应用程序中导入 Flask 实例,然后运行它:

from myproject import app

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

完成后保存并关闭文件。

配置 uWSGI

我们的应用程序现在已经编写好,入口点也已经建立。现在我们可以继续配置 uWSGI。

测试 uWSGI 服务

我们首先要做的是测试 uWSGI 是否能够提供我们的应用程序。

我们可以通过简单地传递入口点的名称来测试。这是由模块的名称(通常情况下去掉 .py 扩展名)加上应用程序中的可调用名称构成的。在我们的情况下,这将是 wsgi:app

我们还将指定套接字,以便它将在公共可用接口上启动,并指定协议,以便它将使用 HTTP 而不是 uwsgi 二进制协议。我们将使用之前打开的相同端口号:

uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app

再次在浏览器中访问您服务器的域名或 IP 地址,并在末尾添加 :5000

http://server_domain_or_IP:5000

您应该再次看到应用程序的输出:

!Flask sample app

确认它正常运行后,在终端窗口中按下 CTRL-C。

现在我们已经完成了虚拟环境,所以我们可以将其停用:

deactivate

任何 Python 命令现在将再次使用系统的 Python 环境。

创建 uWSGI 配置文件

我们已经测试过 uWSGI 能够提供我们的应用程序,但是我们希望为长期使用创建一个更健壮的 uWSGI 配置文件。我们可以创建一个带有我们想要的选项的 uWSGI 配置文件。

让我们将其放在我们的项目目录中,并将其命名为 myproject.ini

nano ~/myproject/myproject.ini

在文件中,我们将首先使用 [uwsgi] 标头,以便 uWSGI 知道应用这些设置。我们将通过引用我们的 wsgi.py 文件(去掉扩展名)来指定模块,并且文件中的可调用名称为 “app”:

[uwsgi]
module = wsgi:app

接下来,我们将告诉 uWSGI 以主模式启动,并生成五个工作进程来处理实际请求:

[uwsgi]
module = wsgi:app
master = true
processes = 5

在测试时,我们在网络端口上暴露了 uWSGI。然而,我们将使用 Nginx 来处理实际的客户端连接,然后将请求传递给 uWSGI。由于这些组件在同一台计算机上运行,因此更倾向于使用 Unix 套接字,因为它更安全且更快。我们将称套接字为 myproject.sock,并将其放在此目录中。

我们还需要更改套接字的权限。稍后我们将把 Nginx 组的所有权赋予 uWSGI 进程,因此我们需要确保套接字的组所有者可以从中读取信息并向其写入。当进程停止时,我们还需要清理套接字,通过添加 “vacuum” 选项来实现:

[uwsgi]
module = wsgi:app
master = true
processes = 5
socket = myproject.sock
chmod-socket = 660
vacuum = true

最后一件事是设置 die-on-term 选项。这有助于确保初始化系统和 uWSGI 对每个进程信号的含义有相同的假设。设置这一点可以使这两个系统组件保持一致,实现预期的行为:

[uwsgi]
module = wsgi:app
master = true
processes = 5
socket = myproject.sock
chmod-socket = 660
vacuum = true
die-on-term = true

您可能已经注意到,我们没有像在命令行中那样指定协议。这是因为默认情况下,uWSGI 使用 uwsgi 协议,这是一种快速的二进制协议,旨在与其他服务器通信。Nginx 可以原生地使用这种协议,因此最好使用这种协议,而不是强制使用 HTTP 进行通信。

完成后保存并关闭文件。

创建一个 systemd 单元文件

接下来,我们需要处理的是 systemd 服务单元文件。创建一个 systemd 单元文件将允许 Ubuntu 的 init 系统在服务器启动时自动启动 uWSGI 并提供我们的 Flask 应用程序。

首先,在 /etc/systemd/system 目录中创建一个以 .service 结尾的单元文件:

sudo nano /etc/systemd/system/myproject.service

在文件中,我们将从 [Unit] 部分开始,该部分用于指定元数据和依赖关系。我们将在这里放置我们服务的描述,并告诉 init 系统仅在网络目标达到后才启动此服务:


[Unit]
Description=uWSGI instance to serve myproject
After=network.target

接下来,我们将打开 [Service] 部分。我们将指定要运行进程的用户和组。我们将使用我们的常规用户帐户拥有该进程,因为它拥有所有相关文件。我们将给 www-data 组拥有权,以便 Nginx 可以轻松地与 uWSGI 进程通信。

然后,我们将映射工作目录并设置 PATH 环境变量,以便 init 系统知道进程的可执行文件位于何处(在我们的虚拟环境中)。然后,我们将指定启动服务的命令。Systemd 要求我们提供到 uWSGI 可执行文件的完整路径,该文件安装在我们的虚拟环境中。我们将传递我们在项目目录中创建的 .ini 配置文件的名称:


[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

最后,我们将添加一个 [Install] 部分。这将告诉 systemd 如果我们启用它以在启动时启动,要将此服务链接到什么。我们希望此服务在常规的多用户系统启动并运行时启动:


[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

[Install]
WantedBy=multi-user.target

完成后,我们的 systemd 服务文件就完成了。现在保存并关闭它。

我们现在可以启动我们创建的 uWSGI 服务,并启用它以便在启动时启动:

sudo systemctl start myproject
sudo systemctl enable 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/sammy/myproject/myproject.sock;
    }
}

这实际上就是我们需要为我们的应用程序提供服务的所有内容。完成后保存并关闭文件。

要启用我们刚刚创建的 Nginx 服务器块配置,将文件链接到 sites-enabled 目录:

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

将文件放在该目录中后,我们可以通过输入以下命令来测试语法错误:

sudo nginx -t

如果没有指示任何问题,我们可以重新启动 Nginx 进程以读取我们的新配置:

sudo systemctl restart nginx

我们需要做的最后一件事是再次调整我们的防火墙。我们不再需要通过端口 5000 进行访问,因此我们可以删除该规则。然后,我们可以允许访问 Nginx 服务器:

sudo ufw delete allow 5000
sudo ufw allow 'Nginx Full'

现在,您应该能够在 web 浏览器中输入服务器的域名或 IP 地址:

http://server_domain_or_IP

您应该能够看到您的应用程序输出:

!Flask sample app

结论

在本指南中,我们在 Python 虚拟环境中创建了一个简单的 Flask 应用程序。我们创建了一个 WSGI 入口点,以便任何支持 WSGI 的应用程序服务器都可以与其进行交互,然后配置了 uWSGI 应用服务器以提供此功能。随后,我们创建了一个 systemd 服务文件,以便在启动时自动启动应用程序服务器。我们创建了一个 Nginx 服务器块,将 Web 客户端流量传递到应用程序服务器,中继外部请求。

Flask 是一个非常简单但极其灵活的框架,旨在为您的应用程序提供功能,而不会对结构和设计施加太多限制。您可以使用本指南中描述的通用堆栈来为您设计的 Flask 应用程序提供服务。

猜你喜欢

转载自blog.csdn.net/rubys007/article/details/143277316