menu Chancel's blog
rss_feed
Chancel's blog
我就是这样的人

Flask框架与Nginx服务器的部署指南

作者:Chancel, 更新:2019 Sep 06, 字数:6727, 已阅:798

这篇文章更新于 1368 天前,文中部分信息可能失效,请自行甄别无效内容。

后端程序是用Flask写的,之前是采用Gunicorn+Nginx进行部署的,最近打算换成uwsgi的方式

HTTP协议/WSGI协议

HTTP协议

超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。

http协议是基本的协议之一,底层使用TCP协议,通过浏览器等工具,发起一个HTTP请求到指定服务器的指定端口,一旦收到请求,服务器会立刻返回一个状态,这就是HTTP协议

关于HTTP协议可以直接参考超文本传输协议 - 维基百科

WSGI协议

Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。

WSGI是基于现存的CGI标准而设计的,WSGI其实是一种中间件,实现了API交互双方所需要的数据规范,因此可以在WSGI服务器与WSGI应用起调节作用

用Python语言写一个符合WSGI规范的Hello world程序如下所示

def app(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    yield "Hello world!\n"

更详细的数据依旧可以参考Web服务器网关接口 - 维基百科

开发与生产环境的区别

无论是Django还是Flask都是自带了一个实现了WSGI协议的Server以及Application来方便你专心写Web服务,但这个Server不保障其性能,故可用于本地调试但不可用于生产环境下

而无论是gunicorn还是uWSGI的本质都是实现了WSGI协议的Web服务器

创建一个最小的Flask-Application例子

这里创建一个最小的Application,并假设这个就是你的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',port=8889)

尝试启动下你的应用

python hello.py

# 输出
# chancel @ chancel-cp in /tmp/flask [17:20:11] 
$ python hello.py
 * Serving Flask app "hello" (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:8889/ (Press CTRL+C to quit)

访问下 http://127.0.0.1:8889,可以得到蓝色的Hello world标题

关闭上面的运行,进入安装gunicorn/uwsgi的环节,如无特别说明,以下操作均在/tmp/flask目录中完成(即你的项目文件)

Gunicorn部署指南

安装运行gunicorn

首先是安装gunicorn

pip install gunicorn

启动gunicorn

# hello是你的程序入口文件名(app.py/__init__.py等,不需要带后缀),app是你的flask实例变量名
gunicorn --bind 0.0.0.0:5000 hello:app

# 输出

# chancel @ chancel-cp in /tmp/flask [17:24:54] C:130
$ gunicorn --bind 0.0.0.0:8889 hello:app
[2019-09-06 17:25:02 +0800] [16092] [INFO] Starting gunicorn 19.9.0
[2019-09-06 17:25:02 +0800] [16092] [INFO] Listening at: http://0.0.0.0:8889 (16092)
[2019-09-06 17:25:02 +0800] [16092] [INFO] Using worker: sync
[2019-09-06 17:25:02 +0800] [16095] [INFO] Booting worker with pid: 16095

这个时候gunicorn已经运行起来了,接下来我们要考虑怎么后台运行这个程序了,这里考虑两种方式

  • supervisor
  • systemd

以前的文章写了不少关于如何设置supervisor的方式,这里介绍一下如何设置程序为systemd吧

注册gunicorn为systemd

systemd是什么?

systemd是Linux计算机操作系统之下的一套中央化系统及设置管理程序(init),包括有守护进程、程序库以及应用软件,由Lennart Poettering带头开发。

无论是sshd服务还是firewalld服务,只要是使用systemctl start <service_name>格式的均是属于systemd管理程序,其配置文件均存放于 /etc/systemd/system/ 目录下

首先我们编辑创建gunicorn的systemd配置文件

# 文件名既是服务名,根据需要自行定制
vim /etc/systemd/system/gunicorn.service


[Unit] # Unit 多存放描述信息以及启动条件
Description=Gunicorn instance to serve flask
After=network.target # 如果开机启动的话,在网络初始化完毕之后启动

[Service]
User=chancel    # 程序运行的用户
Group=chancel   # 程序运行的组
WorkingDirectory=/tmp/flask/ # 程序目录
Environment="PATH=/tmp/flask/flaskenv/bin" # 程序环境变量,如设置了venv则需要填写此项
ExecStart=/tmp/flask/flaskenv/bin/gunicorn --workers 3 --bind unix:flask.sock -m 007 hello:app # 启动命令

[Install]
WantedBy=multi-user.target

最后我们使用systemctl来启动程序以及设计开机自启

sudo systemctl start gunicorn
sudo systemctl enable gunicorn

Uwsgi部署指南

安装运行Uwsgi

首先安装uwsgi

pip install uwsgi

创建uwsgi配置文件

vim /tmp/flask/uwsgi.ini

[uwsgi]
module = hello:app
master = true
processes = 5 # 进程数量

chdir = /tmp/flask
socket = /tmp/flask/uwsgi.sock # 设置为socks协议,不走http协议(据说效率更高,没有考证)
chmod-socket = 660 # socket权限
vacuum = true

die-on-term = true
# 日志记录交由supervisor管理
logto = /tmp/flask/flasg.log # 日志输出

启动uwsgi

uwsgi /tmp/flask/uwsgi.ini

注册Uwsgi为Systemd

上面已经介绍过Systemd了,这里直接编辑创建uwsgi的systemd配置文件,大体配置是相似的

# 文件名既是服务名,根据需要自行定制
vim /etc/systemd/system/uwsgi.service


[Unit] # Unit 多存放描述信息以及启动条件
Description=Uwsgi instance to serve flask
After=network.target # 如果开机启动的话,在网络初始化完毕之后启动

[Service]
User=chancel    # 程序运行的用户
Group=chancel   # 程序运行的组
WorkingDirectory=/tmp/flask/ # 程序目录
Environment="PATH=/tmp/flask/flaskenv/bin" # 程序环境变量,如设置了venv则需要填写此项
ExecStart=/tmp/flask/flaskenv/bin/Uwsgi /tmp/flask/uwsgi.ini

[Install]
WantedBy=multi-user.target

最后我们使用systemctl来启动程序以及设计开机自启

sudo systemctl start uwsgi
sudo systemctl enable uwsgi

Nginx部署指南

首先安装Nginx

rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
yum install nginx -y

设置开机启动

systemctl start nginx
systemctl enable nginx

Nginx的默认配置文件位于 /etc/nginx/nginx.conf,建议采用导入配置文件的方式,参考下面的配置文件,重点在于 *include /etc/nginx/conf.d/.conf;**

user chancel;
worker_processes  1;

error_log  /var/log/nginx/error.log;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;
    # gzip设置
    gzip on;
    gzip_comp_level 9;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
    gzip_vary on;
    gzip_disable "MSIE [1-6]\.";
    gzip_buffers 32 4k;

    ...

    include /etc/nginx/conf.d/*.conf; # 导入/etc/nginx/conf.d/目录下所有.conf配置文件
}

配置Nginx.conf之后,如果是采用gunicorn的部署方式,在 /etc/nginx/conf.d/目录下新增一个flask.conf的配置,并参考下面的配置

server {
    listen 80;

    access_log  /var/log/nginx/flask_access.log;
    error_log   /var/log/nginx/flask_error.log;

    location / {
        # 这里将部分头信息转发到Flask应用
    	proxy_set_header    Host             $host;
    	proxy_set_header    X-Real-IP        $remote_addr;
    	proxy_set_header    X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header    HTTP_X_FORWARDED_FOR $remote_addr;
        proxy_pass http://127.0.0.1:5000;
    }
}

如果是uwsgi配置,由于是采用socks通信的,配置与gunicorn差异主要表现在代理地址与重写转发头处

server {
    listen 80;

    access_log  /var/log/nginx/flask_access.log;
    error_log   /var/log/nginx/flask_error.log;

    location / {
        include uwsgi_params;
        uwsgi_param    Host             $host;
        uwsgi_param    X-Real-IP        $remote_addr;
        uwsgi_param    X-Forwarded-For  $proxy_add_x_forwarded_for;
        uwsgi_param    HTTP_X_FORWARDED_FOR $remote_addr;
        uwsgi_pass_request_headers on;
        uwsgi_pass unix:/opt/api/uwsgi.sock;
    }
}

到这里本篇就结束了,感谢阅读


[[replyMessage== null?"发表评论":"发表评论 @ " + replyMessage.m_author]]

account_circle
email
web_asset
textsms

评论列表([[messageResponse.total]])

还没有可以显示的留言...
[[messageItem.m_author]] [[messageItem.m_author]]
[[messageItem.create_time]]
[[getEnviron(messageItem.m_environ)]]
[[subMessage.m_author]] [[subMessage.m_author]] @ [[subMessage.parent_message.m_author]] [[subMessage.parent_message.m_author]]
[[subMessage.create_time]]
[[getEnviron(messageItem.m_environ)]]
目录