Flask 内置了简单的 Web 环境,让我们在开发的时候只需要专注于应用实现,而真正要在生产环境运行时这个简单的 Web 环境就不够用了,还需要一系列操作才能让 Web 应用高效的运行起来。现在记录一下在生产环境部署 Flask 应用的其中一套方案:Nginx + Gunicorn + Supervisor。

1. 准备

1.1 项目结构

我的项目结构类似这样, myapp 包是应用的主要代码,其中的初始化文件 init 提供了创建程序实例的工厂方法 create_app ,主目录下的 .flaskenv 和 .env 文件存储了一些 Flask 程序要用到的环境变量。

MyApp
|----myapp
| | __init__.py
| | ...
| .flaskenv
| .env
| ...

当然一个最简单的 Flask 应用可能类似下面这种结构也是可以的,我们只需要清楚自己最后的程序实例 app 的位置即可。

MyApp
| app.py
| ...

1.2 修改生产环境配置

这个配置写在 .flaskenv 文件里面比较方便,后面运行时从里面读取加载。

FLASK_ENV = production

1.3 在项目根目录创建 wsgi.py

创建这个文件的作用主要有两个:

  • 自行读取文件中定义的环境变量,因为后面用正式服务器运行时不会自动从文件中加载。
  • 导入程序实例,方便启动。
import os
from dotenv import load_dotenv from myapp import create_app # 读取环境变量
flaskenv_path = os.path.join(os.path.dirname(__file__), '.flaskenv')
env_path = os.path.join(os.path.dirname(__file__), '.env')
if os.path.exists(flaskenv_path):
load_dotenv(flaskenv_path)
if os.path.exists(env_path):
load_dotenv(env_path) # 如果是简单的单文件结构,这里直接 from app import app 也可
app = create_app()

2. 使用Gunicorn启动Flask应用

开发环境下使用flask run 命令或者程序中使用 app.run() 启动的是由 Werkzeug 提供的 WSGI 服务器,它的性能很弱,我们需要一个更健壮的WSGI服务器,也叫WSGI容器,主流选择是 uWSGIGunicorn ,也有其他像 GeventWaitress 等等,这里我们使用 Gunicorn,主要是简单易用且高效。

2.1 安装

Gunicorn 使用 pip 安装即可,若有用虚拟环境,在虚拟环境中安装。

pip install gunicorn

2.2 启动

Gunicorn 启动 Flask 程序需要指定包含程序实例的模块,还有其他参数设置例如工作进程数,一般为cpu核心数,监听地址,设置为 0.0.0.0:端口号 即可监听外网,这里我们只需监听本地地址,因为后面会用到 Web服务器 监听外网然后转发请求到本地地址。

# -w 6 工作线程数,相当于 --workers=6
# -b 127.0.0.1:8000 监听地址,相当于 --bind=127.0.0.1:8000
gunicorn -w 6 -b 127.0.0.1:8000 wsgi:app

3. 使用Supervisor管理进程

直接通过命令运行 Gunicorn 并不可靠,我们需要一个工具来自动在后台运行它并同时监控运行状态,自动重启等。

3.1 安装

sudo apt install supervisor

3.2 配置

全局配置文件在 /etc/supervisor/supervisord.conf,在同级 conf.d/ 目录下创建自己的程序配置myapp.conf,注意目录改成自己的目录,command 要使用正确的虚拟环境(如果有):

[program:myapp]
directory=/home/assassin/tmp/MyApp
stdout_logfile=/home/assassin/tmp/MyApp/supervisor.log
stderr_logfile=/home/assassin/tmp/MyApp/supervisor.log
command=/home/assassin/usr/miniconda3/envs/flask/bin/gunicorn -w 6 -b 127.0.0.1:8000 wsgi:app
user=assassin
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true

3.3 启动

重启 supervisor 服务来加载配置好的 WSGI 程序。

sudo service supervisor restart

查看程序运行状态:

sudo supervisorctl status

停止/启动程序:

sudo supervisorctl stop/start myapp

4. 使用Nginx提供反向代理

Gunicorn 这类WSGI服务器虽然内置了 Web 服务器,已经可以与客户端交换数据,但是不够健壮,更流行的方式是使用一个常规的 Web 服务器运行在前段为 WSGI 服务器提供反向代理,如Nginx,Apache等,这样做的好处有:

  • 提高处理静态文件的效率。Nginx可以对静态文件设置缓存,速度非常快。
  • 提高安全系数。避免直接暴露 WSGI 服务器。
  • 提高处理能力。缓冲请求,预处理,负载均衡等。

这样使用反向代理服务后,WSGI服务器只需要监听本地端口,由代理服务器监听外部端口,将请求转发到WSGI服务器。

4.1 安装

sudo apt install nginx

4.2 配置

新建 /etc/nginx/conf.d/myapp.conf 来配置代理服务

server {
listen 15535; # 监听15535端口来自外部的请求
server_name _; # 如果映射了域名,可以代替_ # 为HTTP规则 / 设置转发
location / {
proxy_pass http://127.0.0.1:8000; # 转发到本地端口
proxy_redirect off; # 重写一些请求首部
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 X-Forwarded-Proto $scheme;
} # 为 /static 静态资源请求设置转发,并指定缓存时间,这比从Flask中获取快得多
location /static {
alias /home/assassin/tmp/Bluelog/bluelog/static/;
expires 10d;
}
}

4.3 启动

使用 sudo nginx -t 来测试配置文件的正确性,没问题后便可以用 sudo service nginx restart 重启Nginx服务。此时访问主机地址的 15535 端口便可以访问到 Flask 应用。

5. 补充

  • Nginx 和 supervisor 安装后默认都是自启动的,如果不需要,可以使用如下命令(Ubuntu):
# 查看服务状态
service --status-all
# 查看自启
systemctl list-unit-files | grep enable
# 关闭自启
sudo systemctl disable nginx.service
sudo systemctl disable supervisor.service
# 打开自启
sudo systemctl enable nginx.service
sudo systemctl enable supervisor.service

Nginx+Gunicorn+Supervisor部署Flask应用的更多相关文章

  1. flask +gevent+nginx+Gunicorn+supervisor部署flask应用

    上篇   可以完美部署flask ,但是视乎在结合gevent+apscheduler 实现异步非阻塞后台和定时任务的时候视乎不是那么完美.请教了前辈,决定使用flask+gevent+nginx+g ...

  2. CentOS 下部署Nginx+Gunicorn+Supervisor部署Flask项目

    原本之前有一部分东西是在Windows Server,但是由于Gunicorn不支持Windows部署起来颇为麻烦.最近转战CentOS,折腾一段时间,终于简单部署成功.CentOS新手,作为一个总结 ...

  3. 2020最新nginx+gunicorn+supervisor部署基于flask开发的项目的生产环境的详细攻略

    本攻略基于ubuntu1804的版本,服务器用的华为云的服务器,python3(python2已经在2020彻底停止维护了,所以转到python3是必须的)欢迎加我的QQ6398903,或QQ群讨论相 ...

  4. 给我一台全新的服务器,使用nginx+gunicorn+supervisor部署django

    0.准备工作 在一台全新的服务器中新建用户以及用户的工作目录,之后的操作都以这个用户的身份进行,而不是直接用root. 举个栗子: 在服务器下新建用户rinka并赋予sudo权限 1) root登陆, ...

  5. Python基础 - Ubuntu+Nginx+uwsgi+supervisor部署Flask应用

    网上找了许多讲关于Flask应用部署的文章几乎都是一个helloworld的Demo,按照helloworld来部署都没问题,但实际项目部署时还是遇到了不少问题.在这里简单写下自己成功部署的过程,防止 ...

  6. flask部署:Ubuntu下使用nginx+uwsgi+supervisor部署flask应用

    之前一直用的Centos或者Red hat,自从使用Ubuntu后,发现Ubuntu使用起来更方便,自此爱上Ubuntu. 一.从github上下载flask应用 1.我已经成功将自己编写好的应用上传 ...

  7. Nginx+uwsgi+supervisor+Ubuntu+flask

    Nginx+uwsgi+supervisor+Ubuntu+flask Nginx+uwsgi+supervisor在Ubuntu上部署flask应用 网上找了许多讲关于Flask应用部署的文章几乎都 ...

  8. 学习大牛笔记nginx + gunicorn + supervisor

    安装 gunicorn pip install gunicorn pip 是一个重要的工具,python 用来管理包.还有一个最佳生产就是每次使用 pip 安装的库,都写入一个 requirement ...

  9. 在Mac上使用Nginx和FastCGI部署Flask应用

    最近在学习Flask,本文介绍一下如何部署Flask开发的应用,同时也学习一下Nginx的使用,这只是在Mac上的一个实验. 应用 这里使用的应用就是官方的文档中给出的Flaskr. 安装Nginx ...

随机推荐

  1. springMVC使用JSR303数据校验

    JSR303注解 hibernate validate是jsr 303的一个参考实现,除支持所有的标准校验注解外,他还支持扩展注解 spring4.0拥有自己独立的数据校验框架,同时支持jsr 303 ...

  2. MySQL主从同步简单介绍&配置

    介绍: 现在mysql集群基本上都是使用一主多从方式,实现读写分离(主库写.从库读).负载均衡.数据备份,以前只是使用从未配置过,今天简单配置一下! mysql主从复制是通过binary log日志实 ...

  3. 初学WebGL引擎-BabylonJS:第2篇-基础模型体验

    此次学习进度会比之前快很多,有了合适的学习方法后也就会有更多的乐趣产生了. 接上一章代码 上章代码 <!DOCTYPE html> <html> <head> &l ...

  4. Ocelot+Consul实现微服务架构

    API网关 API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口.这样就可以明显的简化客户端实现和微服务应用程序之间的沟通方式.以前的话,客户端不得不去请求微服务A ...

  5. RunTime 启动bat程序

    bat文件路径 String cmd= PathUtil.appPath + File.separator + "nginx-1.14.2"+ File.separator +&q ...

  6. console线和RJ45

    123 前言 一直以为console口和RJ45是同一种接口,but后来我发现我错了~ RJ45 先介绍一下RJ45吧 什么是RJ45? RJ45是一种接口 我们家用的网线的接口 其实就是RJ45 r ...

  7. Apache Nginx Tomcat

    Tomcat Tomcat:动态解析容器 处理动态请求,是编译JSP/Servlet的容器 区别: 严格意义上来说 Apache和nginx应该叫做HTTP Server tomcat是一个Appli ...

  8. leetcode刷题-46全排列

    题目 给定一个 没有重复 数字的序列,返回其所有可能的全排列. 思路 回溯算法 不断取出字符,对剩余字符进行选择 实现 class Solution: def permute(self, nums: ...

  9. ajax之---原生ajax

    原生ajax,基于XMLHttpRequest对象来完成请求 <!DOCTYPE html><html><head lang="en">    ...

  10. 刀哥多线程自动释放池autoreleasepool

    自动释放池 作用 自动释放对象的 所有 autorelease 的对象,在出了作用域之后,会被自动添加到最近创建的自动释放池中 自动释放池被销毁或者耗尽时,会向池中所有对象发送 release 消息, ...