接触了flask开发有一小段时间了,使用flask主要完成了咱们产品的Android客户端的后台服务(提供REST API),还有就是为运营提供数据统计及应用发布的web系统。以前都是经过传统的笔记原本记录开发中遇到的问题,渐渐发现不少问题存在着不少的共性,经过博客的方式开启一个记录和交流的新方法吧。文中若是有什么错误欢迎指出,对flask开发有兴趣的朋友也能够互相交流,探讨问题。html
flask在他的官方文档中是这样描述的,flask是一个python的微框架,基于Werkzeuk和Jinjia2。目前对于python2和python3的支持都很好。入门也很简单,强烈推荐官方文档,例子简单清楚。官方文档.另一个参考的就是《FlaskWeb开发:基于Python的Web应用开发实战》在网上能够找到不少电子版的,经过官方的文档能够了解flask是什么以及如何开始一个hello word,而经过上面提到第二个参考资料,能够实现一个简单的博客系统,更好的了解flask的。在这里就很少介绍如何开始flask开发的,我感受官方的文档已经介绍的足够简单清楚,这些内容也不是本文的主要内容,本文的焦点主要放在如何实现flask的部署,以及分享我在部署过程当中遇到的问题,以及通过这些折腾以后个人建议吧。python
系统: centos 6.5 x86_64linux
python: 版本3.5.2nginx
flask:用来实现REST API及相关的web功能, 版本0.11web
celery : 一个很好的分布式管理队列,在个人应用场景中主要使用它来作一些定时的任务,其实主要是定时向咱们的运维人员发送一些日志及告警信息。shell
官方文档.版本3.1.24flask
gunicorn : 做为flask应用的web server,自带的web server是用来咱们开发和测试过程当中进行调试的,是一个单进程单线程的,没法作生产部署只用,centos
以前尝试过uwsgi做为web server,可是从部署角度来讲,gunicorn配置更加方便,另外,gunicorn 对于gevent的支持也是很是不错的,服务器
因此综合以上两个缘由,才用的gunicorn做为web server部署。官方配置文档, 版本19.6网络
gevent: 一个很好的基于协程的python网络库,能够很容易的提高系统的并发性,并且gunicorn对gevent的支持也很好,配置简单。官方文档, 版本1.2
nginx: 用做反向代理, 版本1.6.2
supervisord: 用以管理个人flask应用以及celery任务。gunicorn已经能够实现将本身做为一个守护进程,从必定程度上来讲,即便不适用supervisord也没有任何
问题,可是celery在centos 6.5上配置自启动以及变成守护进程相对麻烦,另外从统一管理及维护简单的角度来考虑,采用supervisord也是一个不错
的选择。不得不说下,在使用supervisord以前,都是手动杀gunicorn的进程的。一样附上官方文档.版本3.3.1
我再啰嗦一下,为何每一个都附上了官方的文档,由于我在个人部署过程当中遇到过很多的问题,搜索过到不少其余人分享的东西,发现不少别人分享的东西都有特定的版本限制,而一般过程当中,做者并无写清楚他当时使用的版本,而对于一个开始接触这种部署方式的人来讲,调错是一件耗时耗力的事情,虽然过程当中咱们能够经过解决问题提高本身,但从我我的的感觉来看,若是第一次配置部署中出现了难以解决的问题,极可能会迫使你转用其余的方式,因此官方文档给的配置说明是最清晰的。
1、必定使用Python虚拟环境(即virtualenv),为何这么说呢,从部署的角度来讲,方便,易维护,若是服务器上有多个版本的python或者当你使用Python3 来开发项目,而后使用跟我同样的部署方式的时候你就会跟我有同样的体会。
一、安装virtualenv: yum install virtualenv
二、进入到你的工程目录,我的建议把虚拟环境放到你的工程目录当中,保证每个工程有本身独立的python环境,
在shell中执行: virtualenv -p python3 venv 来建立虚拟环境,其中 -p 参数制定python的路径,执行完以后能够发如今工程目录中产生一个
名为venv的文件夹,之后该虚拟环境全部的扩展包的安装目录。
三、安装Python虚拟环境的全部依赖包:
在开发过程当中能够经过执行指令 pip freeze > requirement.txt 来导出依赖包及其对应的版本。
在工程目录中,执行: source venv/bin/activate 进入虚拟环境,这时,在你的shell中应该是以下相似的显示: (venv) localhost:service allan$
接着经过执行 pip install -r requirement.txt 来安装全部的扩展包,至此,虚拟环境配置完成。若是须要退出虚拟环境,
能够在shell中执行 deactivate
在工程目录中使用flask自带的web server 运行flask应用,应用功能一切正常。
2、nginx相关配置:
1 location / { 2 proxy_pass http://127.0.0.1:9000; 3 proxy_set_header Host $host; 4 proxy_set_header X-Real-IP $remote_addr; 5 proxy_set_header REMOTE-HOST $remote_addr; 6 proxy_set_header X-Forward-For $proxy_add_x_forwarded_for; 7 proxy_redirect off; 8 }
3、gunicorn已经在第一步虚拟环境的配置的部分的扩展包安装中完成,其简单配置以下:
1 import gevent.monkey 2 import multiprocessing 3 4 gevent.monkey.patch_all() 5 6 bind = '0.0.0.0:9000' 7 # restart workers when code change, only use in development 8 #reload = True 10 preload_app = True 12 # debug when development and error when production 13 loglevel = 'error' 14 logfile = 'log/debug.log' 15 accesslog = 'log/access.log' 16 access_log_format = '%(h)s %(t)s %(U)s %(q)s' 17 errorlog = 'log/error.log' 18 # process name 19 proc_name = 'vservice' 21 pidfile = 'log/gunicorn.pid' 22 # set process daemon, not use in default 23 #daemon = True 25 # number of processes 26 workers = multiprocessing.cpu_count() * 2 + 1 27 # number of threads of per process 28 threads = multiprocessing.cpu_count() * 2 29 worker_class = 'gevent'
其中23行的daemon参数的设置是要特殊注意的,若是只是使用gunicorn而不使用supervisord相似的进程管理工具,该参数设置为true,使进程成为守护进程,但一旦使用相似supervisord等进程管理工具时,该参数必定不要设置,gunicorn默认该参数为False,不然会出现问题。
固然,gunicorn还有不少的参数配置,具体可参考前面部分提供的官方配置文档部分。
若是单独使用gunicorn运行,经过指令 gunicorn -c config.py manager:app 来运行,其中manager对应工程目录中的manager.py, app为flask应用的名称。
至此,若是在flask应用中不使用celery也不使用supervisord作进程管理,在必定程度上已经实现了服务器端的部署。到了这里仍然缺乏一个很重要的环节,那就是监控,我是经过在跟服务器不一样网络的一台测试机器上部署了一个模仿正常客户端的Python脚原本实现对服务器是否正常工做的检测,若是连续丢失几个包会认为服务器程序异常会向运维人员发送报警的短信及邮件。
4、supervisord配置及安装:
在虚拟环境的shell中执行 pip install supervisor 安装supervisord, 我使用的Python版本为3.5.2, pip安装以后supervisord的版本为3.3.1.
安装完成以后,利用supervisord自带的命令产生配置文件模板,强烈建议这么作,由于从网上其余人的分享中找过来的模板极可能版本不匹配,致使supervisord一直不能正常运行,并且supervisord报的错误也会让你一开始没有头绪。
假定在工程目录中放置你的supervisord配置文件: echo_supervisord_conf /data/vservice/supervisord.conf ,该指令会产生一个你安装的版本的supervisord对应的模板配置文件。
下面是我在个人工程实践中的supervisord的配置文件,在模板的基础上,参考官方文档各个参数的意义进行的修改:
1 [program:vservice] 2 command=/data/vservicer/venv/bin/gunicorn -c /data/vservice-server/config.py manager:app 3 process_name=%(program_name)s 4 numprocs=1 5 directory=/data/vservice/ 6 autostart=true 7 autorestart=unexpected 8 user=allan 9 stdout_logfile=/data/vservice/log/supervisor/stdout.log 10 stderr_logfile=/data/vservice/log/supervisor/stderr.log 11 12 [program:send_mail] 13 command=/data/vservice/venv/bin/celery worker --app=manager.celery --beat -l INFO 14 process_name=%(program_name)s 15 numprocs=1 16 directory=/data/vservice/ 17 autostart=true 18 autorestart=unexpected 19 stdout_logfile=/data/vservice/log/celery/stdout.log 20 stderr_logfile=/data/vservice/log/celery/stderr.log
首先咱们要测试咱们的配置是否正确,因为supervisord默认是开启deamon的,因此在测试supervisord是否正确工做的状况下咱们先加一个参数,让supervisord如今前台工做:
supervisord -c /data/vserver/supervisord.conf -n
这个时候若是你的supervisord若是已经正常工做且没有错误的话,应该会显示vservice以及send_mail两个程序进入running状态,下面是个人输出,仅供参考:
1 2016-11-04 16:18:31,125 INFO RPC interface 'supervisor' initialized 2 2016-11-04 16:18:31,125 CRIT Server 'unix_http_server' running without any HTTP authentication checking 3 2016-11-04 16:18:31,125 INFO supervisord started with pid 1812 4 2016-11-04 16:18:32,128 INFO spawned: 'send_mail' with pid 1817 5 2016-11-04 16:18:32,129 INFO spawned: 'vservice' with pid 1818 6 2016-11-04 16:18:33,130 INFO success: send_mail entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 7 2016-11-04 16:18:33,131 INFO success: vservice entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
这个时候你能够经过supervisorctl 指令查看状态,启动,中止或者重启对应的程序
查看状态: supervisorctl -c /data/vservice/supervisord.conf status
执行以上指令以后以后显示的结果:
send_mail RUNNING pid 1911, uptime 0:00:11 vservice RUNNING pid 1912, uptime 0:00:11
中止某个应用: supervisorctl -c /data/vservice/supervisord.conf stop send_mail(或者all或者vservice)
执行以上指令以后以后显示的结果:
[allan@TEST vservice]# supervisorctl -c /data/vservice/supervisord.conf stop send_mail send_mail: stopped [allan@TEST vservice]# supervisorctl -c /data/vservice/supervisord.conf status send_mail STOPPED Nov 04 04:28 PM vservice RUNNING pid 1912, uptime 0:06:16
启动某个应用: supervisorctl -c /data/vservice/supervisord.conf start send_mail(或者all或者vservice)
重启某个应用: supervisorctl -c /data/vservice/supervisord.conf restart send_mail(或者all或者vservice) 一切测试正常以后,如今能够去掉supervisord的 -n参数,这时候supervisord会变成一个守护进程进入后台,至此在外部测试你的flask应用是否正常工做便可,部署在这时候已经基本完成。在使用supervisord的过程当中我遇到过很多的问题。一、最开始在网上看到有人说supervisord对Python3的支持目前只是demo阶段,还不稳定,当时心凉了一截,后来仔细查各类文档及别人分享的经验,发现supervisord 自己运行须要的Python环境是2.x的版本,所以在这个时候Python虚拟环境的重要性再次体现出来:使用2.x的版本环境运行supervisord,可是supervisord自己做为一个进程管理软件,它启动Python3开发的应用用是彻底没有问题的。二、若是首次使用supervisord 启动程序出现错误,好比exit with code 1, not expected等时,你再次运行supervisord时会报地址端口被占用的错误(在supervisord的错误日志目录中),这时候你必定记得经过linux的进程管理查看下你的flask 应用是否是已经启动了,由于极可能出现的状况是,supervisord已经把你的程序启动了,可是出现错误是在其余的步骤中,所以你再次启动时,会出现以上的错误状况。三、supervisord的用户配置问题,如root帐户的问题。以上是个人部署过程以及部署过程当中曾经遇到过的问题,固然过程当中也还有其余的一些小问题,并无一一的在这列出,若是发现有什么错误或者有相关的问题要进行交流讨论,能够经过邮件进行交流:yanhaicheng@gmail.com