原本之前有一部分东西是在Windows Server,但是由于Gunicorn不支持Windows部署起来颇为麻烦。最近转战CentOS,折腾一段时间,终于简单部署成功。CentOS新手,作为一个总结和整理,错漏难免。
 
首先,需要明确上述几个模块各自的作用(因为以前在windows的IIS就颇为简单,只需要在IIS建站,通过fastCGI处理php文件即可,所以对于CentOS部署中的各个package,理解其各自的作用尤为关键):
  1. 在Flask框架下,直接运行app即可利用localhost进行访问,但是该解析器仅仅适用于调试, 可以说比较简陋,不能直接在生产环境中使用。因为其实单线程处理,一个请求没有结束,其他的请求全都进不来,所以需要Gunicorn的多进程来提升处理能力. 关于Flask的调试,我利用Chrome的Advanced Rest clien进行api调试
         2. Gunicorn:基于Python的WSGI Server(UNIX) 能够处理请求并交给Flask的app去处理然后进行返回。
  1. Nginx: 其实刚看到Gunicorn,已经能够处理http请求了,为什么还需要它呢?一句话:性能和可拓展性。可能你只是一台server,只是简单的套一个Nginx并且不进行配置,可能用处真的不大,不过考虑到 (参考:https://www.zhihu.com/question/38528616):

    • 静态文件: Nginx可以直接处理静态文件请求,那么通过配置让Nginx直接处理静态文件。
    • Hold住并发:Nginx可能并不能提升处理能力,但是在一些高并发的场景下,通过nginx保持住请求可以为后端处理赢取时间而不是直接挂掉。由Nginx来缓存发起的请求直到请求接收完全再交给Gunicorn去处理,避免Gunicorn处理请求和响应到客户端的时间消耗,提升Gunicorn的处理能力。
    • 负载均衡:这个在单服务器下可能用处不大,但是谁保不会拓展到多服务器,那么利用Nginx对请求进行分发实现反向负载均衡就意义重大了。
    • 多域名处理:通过Nginx的分发,可以在一台服务器上挂多个域名,以免80端口冲突:即Nginx占用80并分发不同的请求到不同的内部端口。
    • 访问控制,限流等,我暂时没有用到
  2. Supervisor: 利用它,对Gunicorn的进程进行管理。例如CentOS重启的情况,我们自然需要Gunicorn自动开始运行提供服务而不是每次重启都要手动输入再去启动一遍。
 
部署流程:
 
1.根据需要,在CentOS上利用yum安装你的服务所需要的基本环境并且进行配置, 对我来讲:
  • Mysql: 数据持久化和一致性的存储的关系数据库
  • Redis:  我只是利用其做cache(之前用的Memcached)
  • Git: 用来做版本控制,同时方便本机开发的东西从hub上clone和pull
  • Anaconda: 我利用conda来进行虚拟环境管理 (可以利用virtualenv, 总之就是为了防止你不同的项目(不同的版本)之间不同的python库的相互干扰,利用conda/virtualenv来隔离不同的运行环境)
  • 各种环境的安装细节我就不表了,善用搜索引擎。
这一步中可能出现的bugs比较多,善用系统反馈给你的提示和搜索引擎。
 
2.从Git中心Clone你自己的项目到服务器本地, 然后利用你的project中的model生成数据库,同时配置你的配置文件(例如数据库参数,redis参数等等),同时建立项目的Vitualenv,然后安装项目的依赖项到该虚拟环境!!(不要全局安装)
#for conda
source activate my_project_env
conda install -r requirements.txt #for virtualenv
activate my_project_env
pip install -r requirements.txt
安装完项目需要的环境,配合数据库和缓存都做好,这个时候应该已经可以利用 python app.py (激活了my_project_env的情况下)来通过Flask自己的server提供测试级别的服务,就像在本地测试那样测试你的项目是否OK.
此步中如果requirements.txt中可能没有包含的packages, 直接安装解决冲突就好了。
 
3.安装Gunicorn (安装细节不表), 安装了Gunicorn后,利用

gunicorn -w 4 -b 0.0.0.0:8080 run:app
# -w: worker 表示可以处理的进程数 相当于 --worker=4
# -b: bind 就是绑定到哪个屁和端口,0.0.0.0表示可以用服务器的ip访问
# run: 表示run.py app表示Flask application. 
# 此条命令需要在run.py目录下执行,否则需要指明run的路径例如/home/leslie/flask_proj/run:app
 
可以利用服务器或者Advanced RESTFul  client 进行测试了, your-IP:8080
 
4.Nginx的配置
这一步是比较麻烦的,此前的步骤无非就是package的缺失和冲突。而Nginx的配置就需要手动改一些参数了,需要理解。
Nginx的配置文件,存在CentOS的 /etc/nginx/nginx.conf: (关于CentOS下怎么改文档,可以用VIM(https://coolshell.cn/articles/5426.html)或者nano,如果利用windows生成的文档可能会造成换行符的错误,请利用notepad++先转成Unix格式文档再上传)
server {
    listen       80;     # nginx监听的端口

    server_name  _;   

    location / {
        proxy_pass http://127.0.0.1:8080;    # 表名nginx接收到请求去哪里找gunicorn的服务

        proxy_redirect off;
        proxy_set_header Host $host:80;
        proxy_set_header X-Real-IP $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
注意:该配置文件中有 include:  /etc/nginx/conf.d/default.conf  # 所以配置哪个应该都是可以的。
service nginx start/stop/restart/reload/status   

#check status: ps -aux | grep nginx  
Nginx配置完毕并开启后,应该就可以直接用ip访问了,不需要再指定端口8080了,
相当于 request----->nginx------>gunicorn---->Flask
Flask + Gunicorn + Nginx 部署这位同学的例子很形象:
(nginx收到客户端发来的请求,根据nginx中配置的路由,将其转发给WSGI)
 
nginx:"WSGI,找你的来了!"
 
(WSGI服务器根据WSGI协议解析请求,配置好环境变量,调用start_response方法呼叫flask框架)
 
WSGI服务器:"flask,快来接客,客户资料我都给你准备好了!"
 
(flask根据env环境变量,请求参数和路径找到对应处理函数,生成html)
 
flask:"!@#$%^......WSGI,html文档弄好了,拿去吧。"
 
(WSGI拿到html,再组装根据env变量组装成一个http响应,发送给nginx)
 
WSGI服务器:"nginx,刚才谁找我来着?回他个话,!@#$%^....."
 
(nginx再将响应发送给客户端)
 
5.Supervisor
最后是通过基于python的supervisor来管理gunicorn的开机启动了(当然nginx也要开机启动),首先利用conda或者pip安装Supervisor (注意Supervisor目前不支持python3,可能需要建立2.7的环境来安装):
Supervisor的配置有几个步骤:
  • 配置supervisor启动Gunicorn来提供Flask的服务
  • 配置Supervisor的开机启动,从而实现重启后你的web继续提供服务
具体步骤主要参考这两篇,不过在我的实践中,这两篇各有一些小问题,不过综合起来就差不多了:
  • 安装supervisor(pip or conda)
###生成一个supervisord服务的配置文件
echo_supervisord_conf > supervisord.conf
###将配置文件统一放在/etc下
cp supervisord.conf /etc/supervisord.conf
 
### 修改配置文件
vi /etc/supervisord.conf
 
##加入以下配置信息,
[include]
files = /etc/supervisord.d/*.conf  
 
###为了不将所有新增配置信息全写在一个配置文件里
### 每个配置信息新增一个配置文件,都会被上面那个include添加进去
mkdir /etc/supervisord.d/
 
### 在此目录下增加本app的conf
sudo vi /etc/supervisord.d/my_flask.conf
 
#加入, 注意其中的路径和用户名:
[program:my_flask_app]
directory=/home/leslie/flask-project-directory 
command=/your-gunicorn-whole-path-here/gunicorn app:app -b 127.0.0.1:8080 --workers 8 --max-requests 1000
user=leslie
autostart=true
autorestart=true
redirect_stderr=True
  • 创建supervisor作为一个service的启动脚本( 位置/etc/init.d/supervisord ):
#!/bin/sh
#
# /etc/init.d/supervisord
#
# Supervisor is a client/server system that
# allows its users to monitor and control a
# number of processes on UNIX-like operating
# systems.
#
# chkconfig: - 64 36
# description: Supervisor Server
# processname: supervisord
 
# Source init functions
/etc/rc.d/init.d/functions
 
prog="supervisord"
 
prefix="/usr/leslie"
exec_prefix="${prefix}"
prog_bin="${exec_prefix}/your-path-of-supervisor/bin/supervisord"
# PIDFILE="/var/run/$prog.pid"  # 博客推荐的这个设置对我来说不行,我检查自己的supervisord.conf发现pidfile在tmp
PIDFILE="/tmp/$prog.pid"    
CONF= "/etc/supervisord.conf"   # 让启动的时候知道去哪里找配置文件 文章2没有这个
 
start()
{
       echo -n $"Starting $prog: "
       ###注意下面这一行一定得有-c /etc/supervisord.conf 
       daemon $prog_bin -c $CONF --pidfile $PIDFILE
       [ -f $PIDFILE ] && success $"$prog startup" || failure $"$prog startup"
       echo
}
 
stop()
{
       echo -n $"Shutting down $prog: "
       [ -f $PIDFILE ] && killproc $prog || success $"$prog shutdown"
       echo
}
 
case "$1" in
 
 start)
   start
 ;;
 
 stop)
   stop
 ;;
 
 status)
       status $prog
 ;;
 
 restart)
   stop
   start
 ;;
 
 *)
   echo "Usage: $0 {start|stop|restart|status}"
 ;;
 
esac
  • 然后加入该service到centos的启动项并启动
sudo chmod +x /etc/rc.d/init.d/supervisord
sudo chkconfig --add supervisord
sudo chkconfig supervisord on
sudo service supervisord start
  • 就可以查看了:
ps -ef | grep supervisord
## 同时也可以有service supervisord restart/stop/stats
此步中可能出现的问题:
ps -ef | grep supervisord   # 通过这个来获得supervisord的进程pid 然后杀掉之前的进程后再启动。
kill (-s SIGTERM) pid
---- supervisor需要python2的环境,而项目可能是不同的环境,所以在较多配置的时候都需要显式的指定路径。
---- syntax error near unexpected token 之类的问题很可能是脚本的问题(比如之前提到window上编辑造成的行位标识符的区别)
---- service supervisord start 时候出现 “No such file or directory error”:
   a.请不要太相信你自己的输入,请多检查!!我因为吧directory写成了derectory(对vi不太熟的时候)这个问题困扰了很久。
   b.此问题也可能来源与/etc/init.d/service_script的符号,例如windows创建的问题。。 详细可见:(Starting service on Linux throws a No such file or directory error  
 
 
 
6 TODO: 
----利用fabric部署?
----http--->https
 
 
更多参考:

CentOS 下部署Nginx+Gunicorn+Supervisor部署Flask项目的更多相关文章

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

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

  2. Nginx+Gunicorn+Supervisor部署Flask应用

    Flask 内置了简单的 Web 环境,让我们在开发的时候只需要专注于应用实现,而真正要在生产环境运行时这个简单的 Web 环境就不够用了,还需要一系列操作才能让 Web 应用高效的运行起来.现在记录 ...

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

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

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

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

  5. CentOS 下用 Nginx 和 uwsgi 部署 flask 项目

    前几天利用flask 写了几个调用salt-api 的接口,需要上线到正式环境,搜了一下 都是 用 nginx + uwsgi 来部署,这里记录下关键的配置项. 1.首先将代码上传到服务器上目录为: ...

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

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

  7. Nginx+uwsgi+supervisor+Ubuntu+flask

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

  8. linux/centos下安装nginx(rpm安装和源码安装)详细步骤

    Centos下安装nginx rpm包                                                                                 ...

  9. Ubuntu/CentOS下编译Nginx最基本参数

    Ubuntu/CentOS下编译Nginx安装基本参数,做个记录: groupadd www useradd -g www www ./configure --user=www --group=www ...

随机推荐

  1. vscode设置默认shell 快速到行

    vscode设置默认shell - CSDN博客 https://blog.csdn.net/butterfly5211314/article/details/78944805 在文件 -> 首 ...

  2. 【题解】cycle

    [题解]cycle 题目描述 给定一个无向图,求一个环,使得环内边权\(\div\)环内点数最大. 数据范围 \(n \le 5000\) \(m\le 10000\) \(Solution\) 考虑 ...

  3. 【题解】P3258松鼠的新家

    [题解][P3258 JLOI2014]松鼠的新家 树链剖分板子题. 总结一点容易写错的地方吧: if(d[top[u]]<d[top[v]]) swap(u,v);注意是\(top\). 在\ ...

  4. BZOJ1815: [Shoi2006]color 有色图

    BZOJ1815: [Shoi2006]color 有色图 Description Input 输入三个整数N,M,P 1< = N <= 53 1< = M < = 1000 ...

  5. 我的Java开发学习之旅------>工具类:Java获取字符串和文件进行MD5值

    ps:这几天本人用百度云盘秒传了几部大片到云盘上,几个G的文件瞬秒竟然显示"上传成功"!这真让我目瞪口呆,要是这样的话,那得多快的网速,这绝对是不可能的,也许这仅是个假象.百度了一 ...

  6. global 全局变量的用法

    说明:i 和foo()都为全局变量,i 是在模块文件顶层注册的,所以为全局变量,他能够在函数内部进行引用而不需要再特意声明是全局变量,且foo()函数也是全局变量 1.当没有局部变量时,print(i ...

  7. Android tab页制作

    全屏启动页 activity_launcher <?xml version="1.0" encoding="utf-8"?> <Relativ ...

  8. POJ - 3278 Catch That Cow 【BFS】

    题目链接 http://poj.org/problem?id=3278 题意 给出两个数字 N K 每次 都可以用三个操作 + 1 - 1 * 2 求 最少的操作次数 使得 N 变成 K 思路 BFS ...

  9. 深入理解SP、LR和PC

    深入理解ARM的这三个寄存器,对编程以及操作系统的移植都有很大的裨益. 1.堆栈指针r13(SP):每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,也就是说五种异常模式.非异常模 ...

  10. wampserver发布常见问题

    1 之前使用wamp在本地通过localhost访问PHP网站,一直很正常,最近想要发布至服务器,需要域名解析,发现PHP网站无法使用ip登陆,比如输入ip+端口地址,会报错:you don't ha ...