使用NGINX + NGINX Unit + Flask组合在Python的Web应用上运行

使用NGINX + NGINX Unit + Flask进行Python Web应用开发。

我打算用Python进行Web开发,所以我进行了Python Web应用的环境搭建。
以前,NGINX <-> uwsgi <-> Flask的设置是主流的,但是在2018年4月,NGINX公司发布了轻量级的AP服务器NGINX Unit。
这次我将使用NGINX Unit,将环境搭建成NGINX <-> NGINX Unit <-> Flask的设置来进行Web应用的开发。

环境

作为 Web 服务器,使用 NGINX,作为 AP 服务器,使用 NGINX Unit,使用 Python 的 Web 框架 Flask。

    • OS : CentOS7

 

    • Python : 3.7.4

 

    • NGINX : 1.16.1

 

    • NGINX Unit : 1.10.0

 

    Flask : 1.1.1

备考

服务器使用Vagrant和VirtualBox虚拟环境。
请启用私有网络。

$ vagrant init centos/7
$ vi Vagrantfile
- # config.vm.network "private_network", ip: "192.168.33.10"
+ config.vm.network "private_network", ip: "192.168.33.10"
$ vagrant up
$ vagrant ssh

请使用 vagrant ssh 连接到虚拟环境,并将 selinux 禁用。

$ sudo vi /etc/selinux/config
- SELINUX=enforcing
+ SELINUX=disabled
$ sudo reboot

搭建Python开发环境

在虚拟环境中搭建Python开发环境。
CentOS默认安装了Python 2.7.5。

$ python --version
Python 2.7.5

本次将使用 Python 3.7.4。

在 CentOS 上安装 Python3

参考Python官方网站的步骤,在CentOS上安装Python。
首先,安装所需工具。

$ sudo yum -y groupinstall "development tools"
$ sudo yum install -y bzip2-devel gdbm-devel libffi-devel libuuid-devel ncurses-devel openssl-devel readline-devel sqlite-devel tk-devel wget xz-devel zlib-devel

请使用wget命令从Python官方网站下载安装程序。下载完成后,请解压缩。

$ wget https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz
$ tar xzf Python-3.7.4.tgz

解压源代码后进行构建。

$ cd Python-3.7.4
$ ./configure --enable-shared
$ make
$ sudo make install
$ sudo sh -c "echo '/usr/local/lib' > /etc/ld.so.conf.d/custom_python3.conf"
$ sudo ldconfig

构建命令将安装到/usr/local/bin目录下。

$ which python
/usr/bin/python
$ which python3
/usr/local/bin/python3
$ python3 --version
Python 3.7.4
$ which pip3
/usr/local/bin/pip3

最后,将pip升级。

$ pip3 install --upgrade pip --user

最新版本的pip命令将安装在本地的bin目录中。

$ which pip
~/.local/bin/pip
$ pip --version
pip 19.2.3 from /home/vagrant/.local/lib/python3.7/site-packages/pip (python 3.7)

Python的环境已经设置完毕。

创建Python虚拟环境

为了根据每个项目来切换和管理包,我们将建立Python虚拟环境。
Python提供了一个名为venv的标准模块来支持创建虚拟环境。
我们将使用venv来创建虚拟环境。

# flask_sampleという仮想環境を作成
$ python3 -m venv flask_sample
$ ls
venv

激活由 venv 创建的虚拟环境。

$ source flask_sample/bin/activate
(flask_sample)$

通过执行venv模块创建的目录内的activate脚本,可以激活虚拟环境。
激活虚拟环境后,提示符的开头将显示虚拟环境的名称。
移动到创建的虚拟环境目录并确认其配置。

(flask_sample)$ cd flask_sample
(flask_sample)$ ls
bin  include  lib  lib64  pyvenv.cfg

在bin目录中,有激活虚拟环境的activate脚本和Python的包管理工具pip命令。当在虚拟环境中执行pip命令时,将运行此目录中的命令。安装的包将被安装在lib/python3.7/site-packages和lib64/python3.7/site-packages目录中。在虚拟环境中,将忽略Python本身的site-packages目录,而使用此目录中的包。这样可以进行应用程序开发,而不会影响Python本身的包。

使用Flask创建样本项目。

Flask是Python的一个轻量级微框架。它只包含最基本的功能,适用于开发小型应用程序。由于有提供插件的功能,可以进行功能扩展。如果要从一开始开发大型应用程序,则需要使用Django。

安装Flask

在venv虚拟环境中,安装Flask。

(flask_sample)$  pip install Flask

创建应用程序

样本项目的组成如下所示。

/sample
  |- app.py
  |- templates
        |- index.html
        |- post.html

每个代码的实现如下所示。

from flask import Flask ,render_template,request

application = Flask(__name__)

@application.route('/')
def index():
    return render_template('index.html')

@application.route('/sample',methods=['POST'])
def sample():
    message = request.form['message']
    return render_template('post.html',message=message)

if __name__=="__main__":
    application.run(host='0.0.0.0')
<html>
  <head>
    <meta charset="utf-8" />
    <title>Flask Sample</title>
  </head>
  <body>
    <h1>Flask Smaple</h1>
    <form action="sample" method="post">
      <input type="text" name="message" />
      <input type="submit" value="送信" />
    </form>
  </body>
</html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Flask Sample</title>
  </head>
  <body>
    <h1>Flask Smaple</h1>
    メッセージ:{{message}}
  </body>
</html>

在实施后执行app.py,启动Flask应用程序。

(flask_sample)$ python /sample/app.py
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

当您启动后,在浏览器中访问http://虚拟环境的私有IP:5000/,将显示index.html页面。如果能确认这一点,那么Flask的操作已完成。下一步,将使用NGINX Unit构建AP服务器。

NGINX Unit = NGINX 单元

NGINX Unit 是由 NGINX 公司开发的轻量级应用服务器。
由于可以运行多种语言的应用程序,因此可以在同一台服务器上运行不同语言的应用程序。
支持的语言包括Python、PHP、Go、Perl、Ruby、Node.js和Java。
此外,还可以共存并运行不同版本的同一种语言(如Python2.7和Python3)。
通过API或JSON,可以实时更改配置而无需停止服务器,从而可以无缝地在不停止服务的情况下进行配置更改。

安装

在公式文档中,每个操作系统的安装方法都已经公开。

退出虚拟环境,然后添加yum仓库。

(flask_sample)$ deactivate
$ sudo vi /etc/yum.repos.d/unit.repo
[unit]
name=unit repo
baseurl=https://packages.nginx.org/unit/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

我将安装。

$ sudo yum install -y unit
$ sudo yum install -y unit-devel unit-go unit-jsc8 unit-perl unit-php unit-python

我們將設置NGINX Unit的自動啟動。

$ sudo systemctl enable unit
Created symlink from /etc/systemd/system/multi-user.target.wants/unit.service to /usr/lib/systemd/system/unit.service.
$ sudo service unit start
Redirecting to /bin/systemctl start unit.service
$ sudo service unit status
Redirecting to /bin/systemctl status unit.service
● unit.service - NGINX Unit
   Loaded: loaded (/usr/lib/systemd/system/unit.service; enabled; vendor preset: disabled)
   Active: active (running) since 火 2019-11-05 15:42:47 UTC; 7h ago
 Main PID: 5714 (unitd)
   CGroup: /system.slice/unit.service
           ├─5714 unit: main v1.12.0 [/usr/sbin/unitd --log /var/log/unit/unit.log --pid /var/run/unit/unit.pid --no-daemon]
           ├─5716 unit: controller
           └─5717 unit: router

可以确认通过service unit status命令,NGINX Unit已成功启动。

设置Flask的配置

进行设置,将Flask的应用程序配置在NGINX Unit上运行。
通过从NGINX Unit的套接字获取配置文件,将Flask的应用程序加载到NGINX Unit中进行配置。
NGINX Unit用于控制的Unix套接字位于/var/run/unit/control.sock中(位置因操作系统而异)。

$ cd /sample
$ sudo curl --unix-socket /var/run/unit/control.sock http://localhost/config/ > config.json
$ vi config.json
{
  "listeners": {
    "*:8080": {
      "pass": "applications/flask_app"
    }
  },

  "applications": {
    "flask_app": {
      "type": "python",
      "processes": 2,
      "path": "/sample/",
      "module": "app"
    }
  }
}
    • listeners : ポートの設定を行います。*:8080のpassの値が、applicationsの階層と紐ずいています。

 

    • applications :

type : モジュール名(言語)を指定
processes : worker 数
path : Python プログラムを配置しているパス
module : 起動するファイル。ファイル名から拡張子を除いた形で指定

将创建的配置文件PUT到NGINX Unit的套接字,以便应用配置的更改。

$ sudo curl -X PUT --data-binary @config.json --unix-socket /var/run/unit/control.sock http://localhost/config
{
    "success": "Reconfiguration done."
}

当成功返回时,设置已经完成。您还可以确认设置的内容。

$ sudo curl --unix-socket /var/run/unit/control.sock http://localhost/
{
    "certificates": {},
    "config": {
        "listeners": {
            "*:8080": {
                "pass": "applications/flask_app"
            }
        },

        "applications": {
            "flask_app": {
                "type": "python",
        "processes": 2,
                "path": "/sample/",
                "module": "app"
            }
        }
    }
}

启动虚拟环境,访问http://localhost:8080/。

$ source venv/bin/activate
(flask_sample)$ curl http://localhost:8080/
<html>
  <head>
    <meta charset="utf-8" />
    <title>Flask Sample</title>
  </head>
  <body>
    <h1>Flask Smaple</h1>
    <form action="sample" method="post">
      <input type="text" name="message" />
      <input type="submit" value="送信" />
    </form>
  </body>
</html>

如果index.html文件被显示出来,那么就表示已经完成了构建。即使在浏览器中访问,也会显示index.html文件。
以上是关于NGINX Unit的构建。接下来我们将构建NGINX Web服务器。

NGINX 是一个开源的高性能的Web服务器和反向代理服务器。

輕量高速是這款開源網頁伺服器的特點,被關注作為對Apache的替代伺服器。
相較於Apache,它在可伸縮性方面更為優越,其處理性能、並行處理和記憶體使用量等特點更加突出。我們這次將使用它作為代理伺服器。

在CentOS上安装NGINX

由于NGINX官方正式发布了yum仓库,所以我们会从该仓库中进行安装。
我们将根据官方网页的描述来添加仓库并进行安装。

添加仓库

我将从Python虚拟环境中退出。
我将添加yum仓库。我将添加/etc/yum.repos.d/NGINX.repo。

$ sudo vi /etc/yum.repos.d/NGINX.repo
[NGINX]
name=NGINX repo
baseurl=http://NGINX.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1

安装

我会检查存储库。

$ sudo yum info nginx
Available Packages
Name        : NGINX
Arch        : x86_64
Epoch       : 1
Version     : 1.16.1
Release     : 1.el7_4.ngx
Size        : 754 k
Repo        : NGINX/x86_64
Summary     : High performance web server
URL         : http://NGINX.org/
License     : 2-clause BSD-like license
Description : NGINX [engine x] is an HTTP and reverse proxy server, as well as
            : a mail proxy server.

一旦使用yum info命令确认存储库中是否存在NGINX,然后进行安装。

$ sudo yum install nginx

设置自动启动,并启动NGINX。

$ sudo systemctl enable nginx
$ sudo service start nginx
$ ![nginx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239179/0d818e0a-7aee-8a07-af95-72d34dfaa824.png)
service status nginx
● NGINX.service - NGINX - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/NGINX.service; enabled; vendor preset: disabled)
   Active: active (running)

在启动 NGINX 后,使用浏览器访问虚拟环境的私有 IP,如果显示以下类似界面,则表示启动成功。

nginx.png

NGINX 和 NGINX Unit 的协作

Nginx 的配置文件

NGINX作为NGINX Unit之前的Web服务器和代理服务器运行。
将应用程序的请求代理给Nginx Unit。
NGINX的配置文件位于/etc/nginx/conf.d目录中。

$ sudo vi /etc/nginx/conf.d/app.conf
upstream unit-python {
        server 127.0.0.1:8080;
}
server {
    listen 80;
    server_name localhost;

    location ~ / {
      proxy_pass http://unit-python;
      proxy_set_header Host $host;
    }
}

重启NGINX并访问 http://localhost/ 。

$ sudo service restart nginx
$ curl http://localhost/
<html>
  <head>
    <meta charset="utf-8" />
    <title>Flask Sample</title>
  </head>
  <body>
    <h1>Flask Smaple</h1>
    <form action="sample" method="post">
      <input type="text" name="message" />
      <input type="submit" value="送信" />
    </form>
  </body>
</html>

如果显示 ‘index.html’,则代理设置已完成。您可以在浏览器中访问虚拟环境的私有IP并确认 index.html。至此,Python Web应用程序的环境配置已完成。

总结一下

我使用NGINX、NGINX Unit和Flask搭建了一个WEB应用环境。由于NGINX Unit专注于微服务的运营,我认为它将在未来继续受到关注。我希望能够持续地进行学习和实践。