flask能够快速的搭建http服务,可是为了搭建网站仍是须要web服务器和相关监控管理操做,一套flask、uwsgi、supervisor、nginx是较好的完整解决方案。html
本文对本身学习作一个记录,以一个简单的显示‘Hello Flask!’程序来测试,跑通整个流程,方式是在局域网服务器上部署,在我的电脑上访问。python
服务器系统是centos7 安装了pyenvnginx
pyenv 切换到python3.5版本,不懂版本切换的能够参考我这边文章http://www.javashuo.com/article/p-hnuqpmwl-cc.htmlweb
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello Flask!' if __name__ == '__main__': app.run(host='0.0.0.0',port=8080)
在服务器上运行# python test_flask.py,出现以下: 此时,在我的电脑浏览器输入10.12.28.27:8080,(10.12.28.27是我服务器ip),出现以下错误:
flask
ok,此时缘由多是服务器防火墙打开了,须要关闭,在服务器上输入关闭防火墙命令(注意系统不一样命令也不一样): centos
关闭后,在我的电脑浏览器输入10.12.28.27:8080,出现hello,Flask!(注意web进程必定要设置ip:0.0.0.0,公网才能访问到) 浏览器
Flask 是一个 Web 应用框架,框架的做用在于处理 request 和 reponse,使用的是 Python 自带的 simple HTTPServer 建立的,在安全性和效率上都是不行的,而uWSGI 是一个全功能的 HTTP 服务器,他要作的就是把 HTTP 协议转化成语言支持的网络协议。好比把 HTTP 协议转化成 WSGI 协议,让 Python 能够直接使用。 uwsgi 是一种 uWSGI 的内部协议,使用二进制方式和其余应用程序进行通讯。 如今,咱们结束上面的flask服务,在服务器上安装uWSGI,直接输入以下命令缓存
pip install uwsgi安全
安装完,直接输入启动命令:服务器
uwsgi --http 0.0.0.0:8080 --home env --wsgi-file test_flask.py --callable app --master
出现以下错误
Fatal Python error: Py_Initialize: Unable to get the locale encoding ImportError: No module named 'encodings'
缘由是--home参数,之前uwsgi须要这个参数来指定python环境变量的目录,如今不须要这个参数,直接:
uwsgi --http 0.0.0.0:8080 --wsgi-file test_flask.py --callable app --master
运行成功:
在我的电脑浏览器输入10.12.28.27:8080,出现Hello,Flask!(注意uwsgi配置ip:0.0.0.0,公网才能访问到) 固然,为了减小输入命令麻烦,能够用配置文件来启动uwsgi, 在当前目录新建 vi uwsgi_config.ini:
[uwsgi] # uwsgi 启动时所使用的地址与端口 # socket = 0.0.0.0:8080 # 外网访问端口,若是直接用uWSGI外网,这里因为使用了Nginx,故注释掉 http= 0.0.0.0:8080 # 指向项目地址 chdir = /root/zlw/web_flask/ # python 启动程序文件,应该在上面的目录中 wsgi-file = test_flask.py # python 程序内用以启动的 application 变量名 # app 是 manage.py 程序文件内的一个变量,这个变量的类型是 Flask的 application 类 callable = app # 处理器数 processes = 4 # 线程数 threads = 2 #状态检测地址 stats = 127.0.0.1:9191
配置文件启动uwsgi(这里uwsgi_config.ini是在当前目录下):
uwsgi uwsgi_config.ini
ok,此时,你的应用已经得到了高并发的处理能力,但对于静态文件的处理uwsgi比较笨拙,而且这种方式安全性也不高,因此要加上Nginx反向代理服务。
在增长Nginx服务以前,咱们还有一个事情要作,考虑一下:我如今有一个进程须要每时每刻不断的跑,可是这个进程又有可能因为各类缘由有可能中断。当进程中断的时候我但愿能自动从新启动它,此时,我就须要使用到了Supervisor,supervisor管理进程,是经过fork/exec的方式将这些被管理的进程看成supervisor的子进程来启动,因此咱们只须要将要管理进程的可执行文件的路径添加到supervisor的配置文件中就行了。此时被管理进程被视为supervisor的子进程,若该子进程异常中断,则父进程能够准确的获取子进程异常中断的信息,经过在配置文件中设置autostart=ture,能够实现对异常中断的子进程的自动重启。
没有supervisor以前启动uwsgi服务是这样:uwsgi uwsgi_config.ini 如今我准备使用Supervisor,故uwsgi启动命令仅供测试的时候用。 安装supervisor:
yum install supervisor
打开全局配置文件(先找到配置文件路径:find / -name supervisord.conf)
vi /etc/supervisord.conf
在末尾加入:
[program:Test-flask] # 启动命令入口 command=uwsgi /root/zlw/web_flask/uwsgi_config.ini # 命令程序所在目录 directory=/root/zlw/web_flask #运行命令的用户名 user=root autostart=true # supervisor启动的时候是否随着同时启动 autorestart=true # 当程序跑出exit的时候,这个program会自动重启 startsecs=3 # 程序重启时候停留在runing状态的秒数 #日志地址 stdout_logfile=/root/zlw/web_flask/uwsgi_supervisor.log
supervisor 相关操做:
启动:supervisord 打开命令行: supervisorctl
命令行中查看命令: help
命令行中查看状态: status或者
supervisorctl status //查看状态
supervisorctl stop [进程名] //中止 supervisorctl start [进程名]
输入命令supervisord启动,子程序uwsgi服务将随之启动。 这个时候输入: ps -ef | grep uwsgi 能看到运行的uwsgi程序:
在我的电脑浏览器输入10.12.28.27:8080,出现Hello,Flask!(注意uwsgi配置ip:0.0.0.0,公网才能访问到) supervisor搭建完毕。
从上面的讲解中,咱们知道,uWSGI 能够起到 Web 服务器的做用,那么为何有了 uWSGI 还须要 Nginx 呢?
最广泛的说法是 Nginx 对于处理静态文件更有优点,性能更好。其实若是是小网站,没有静态文件须要处理,只用 uWSGI 也是能够的,但加上 Nginx 这一层,优点能够很具体:
对于运维来讲比较方便,若是服务器被某个 IP 攻击,在 Nginx 配置文件黑名单中添加这个 IP 便可,若是只用 uWSGI,那么就须要在代码中修改了。另外一方面,Nginx 是身经百战的 Web 服务器了,在表现上 uWSGI 显得更专业,好比说 uWSGI 在早期版本里是不支持 https 的,能够说 Nginx 更安全。
Nginx 的特色是可以作负载均衡和 HTTP 缓存,若是不止一台服务器,Nginx 基本就是必选项了,经过 Nginx,将资源能够分配给不一样的服务器节点,只有一台服务器,也能很好地提升性能,由于 Nginx 能够经过 headers 的Expires or E-Tag,gzip 压缩等方式很好地处理静态资源,毕竟是 C 语言写的,调用的是 native 的函数,针对 I/O作了优化,对于动态资源来讲,Nginx 还能够实现缓存的功能,配合 CDN 优化(这是 uWSGI 作不到的)。Nginx 支持epoll/kqueue 等高效网络库,可以很好地处理高并发短链接请求,性能比 uWSGI 不知道高到哪里去了。
若是服务器主机上运行了PHP,Python 等语言写的多个应用,都须要监听80端口,这时候 Nginx 就是必选项了。由于咱们须要一个转发的服务。 安装:
yum install nginx
打开全局配置文件(先找到配置文件路径:find / -name nginx.conf)
vi /etc/nginx/nginx.conf
修改配置:(注意先备份一份)
server { listen 80 default_server; listen [::]:80 default_server; server_name 10.12.28.27; # 这里是服务域名,请求的url必须包含该字段Nginx才能响应。 #root /usr/share/nginx/html; # Load configuration files for the default server block. # include /etc/nginx/default.d/*.conf; access_log /root/zlw/web_flask/nginx_access.log; # 服务器接收的请求日志 error_log /root/zlw/web_flask/nginx_error.log; # 错误日志 location / { include uwsgi_params; uwsgi_pass 0.0.0.0:8080; # 指向uwsgi 所应用的内部地址,全部请求将转发给uwsgi 处理 uwsgi_param UWSGI_CHDIR /root/zlw/web_flask; # 指向网站根目录 uwsgi_param UWSGI_SCRIPT test_flask:app; # 指定启动程序
nginx一些操做:
验证配置是否正确:nginx -t 启动: nginx 重启: nginx -s reload 中止: nginx -s quit
启动后,在我的电脑浏览器输入10.12.28.27:80,出现很卡的想象,一直出不来结果,等很久提示以下:
分析缘由:配置出现问题。 从新设置配置,将默认配置/etc/nginx/nignx.conf还原为原来的配置。而且默配置文件内有以下配置
include /etc/nginx/conf.d/*.conf;
ok,新建一个配置:
vi /etc/nginx/conf.d/my_nginx.conf
输入以下内容:
server { listen 80; server_name 10.12.28.27; # 服务器ip, charset utf-8; client_max_body_size 100M; location / { include uwsgi_params; #uwsgi_pass unix:/root/zlw/web_flask/flask_uwsgi.sock; # sock方式跑不通,缘由未知 uwsgi_pass 127.0.0.1:8080; } }
同时,修改以前的uwsgi_config.ini配置文件(注意本身的文件路径):
vi /root/zlw/web_flask/uwsgi_config.ini
修改成:
[uwsgi] # uwsgi 启动时所使用的地址与端口 socket = 127.0.0.1:8080 #socket = /root/zlw/web_flask/flask_uwsgi.sock # 经过sock文件的方式行不通,缘由未知 #permissions for the socket file #chmod-socket = 666 # 外网访问端口,若是直接用uWSGI外网,这里因为使用了Nginx,故注释掉 #http= 127.0.0.1:8080 # 指向项目地址 chdir = /root/zlw/web_flask/ # python 启动程序文件 wsgi-file = test_flask.py # python 程序内用以启动的 application 变量名 # app 是 manage.py 程序文件内的一个变量,这个变量的类型是 Flask的 application 类 callable = app # 处理器数 processes = 1 # 线程数 threads = 2 #状态检测地址 stats = 127.0.0.1:9191
保存好,重启supervisor,重启nginx
在我的电脑浏览器输入10.12.28.27:80,出现Hello,Flask! 输入10.12.28.27:8080将出现没法访问状况。由于uwsgi 服务ip设置为127.0.0.1了,其余电脑没法访问,只能经过nginx的监听端口80进行访问。若uwsgi 服务指定ip:0.0.0.0:8080,则,其余电脑输入10.12.28.27:8080也能从新hello,flask,固然10.12.28.27:80也能(uwsgi配置ip要和nginx配置一致)
到此能跑通也算大功告成了,可是不能知足,当咱们服务器运行了多个flask时该怎么处理呢,下面咱们就继续尝试管理多个进程时的相关配置操做。
咱们分别创建两个测试项目:
每一个项目目录下分别有文件:
test_flask1.py 和test_flask2.py是和上面简单测试程序同样的,uwsgi配置启动端口和检测端口分别不同。
uwsgi配置
uwsgi_config1.ini:
[uwsgi] # uwsgi 启动时所使用的地址与端口 socket = 127.0.0.1:8080 # 指向项目地址 chdir = /root/web_flask/ # python 启动程序文件 wsgi-file = test_flask1.py # python 程序内用以启动的 application 变量名 # app 是 manage.py 程序文件内的一个变量,这个变量的类型是 Flask的 application 类 callable = app # 处理器数 processes = 1 # 线程数 threads = 2 #状态检测地址 stats = 127.0.0.1:9191
uwsgi_config2.ini:
[uwsgi] # uwsgi 启动时所使用的地址与端口 socket = 127.0.0.1:7070 # 指向项目地址 chdir = /root/zlw/ # python 启动程序文件 wsgi-file = test_flask2.py # python 程序内用以启动的 application 变量名 # app 是 manage.py 程序文件内的一个变量,这个变量的类型是 Flask的 application 类 callable = app # 处理器数 processes = 1 # 线程数 threads = 2 #状态检测地址 stats = 127.0.0.1:7171
此时测试一下,uwsgi分别启动项目(注意只能单个分别启动,ctrl+c结束) uwsgi /root/web_flask/uwsgi_config1.ini uwsgi /root/zlw/uwsgi_config2.ini 分别都能启动成功,进行supervisor配置,经过supervisor来同时启动两个项目。
supervisor配置
个人supervisor默认配置是/etc/supervisor.conf,打开会找到相似这样的配置
[include] files = supervisord.d/*.ini
所以能够在/etc/supervisord.d/目录下的构建两个进程的配置文件.ini各式。固然也能够直接在默认配置文件中增长进程配置。 如下是个人配置(增长两个进程配置文件,同时记得将默认配置文件原来设置的进程配置删除掉): /etc/supervisord.d/my_flask1.ini
[program:Test-Flask1] command=uwsgi /root/web_flask/uwsgi_config1.ini stdout_logfile=/root/web_flask/logs/supervisor.log autostart=true autorestart=true startsecs=5 # 启动5秒内没异常说明启动成功。 priority=1 # 启动优先级 stopasgroup=true # 程序被终止是否通知用户组 killasgroup=true #被kill是否通知用户组
/etc/supervisord.d/my_flask2.ini
[program:Test-Flask2] command=uwsgi /root/zlw/uwsgi_config2.ini stdout_logfile=/root/zlw/logs/supervisor.log autostart=true autorestart=true startsecs=5 # 启动5秒内没异常说明启动成功。 priority=1 # 启动优先级 stopasgroup=true # 程序被终止是否通知用户组 killasgroup=true #被kill是否通知用户组
启动supervisord,打开supervisorctl能看到启动成功。 此时,已经能够在服务器电脑上分别访问127.0.0.1:8080和127.0.0.1:7070,都将返回Hello Flask。
配置Nginx
分别为每一个进程配置一个nginx配置文件,文件目录/etc/nginx/conf.d/ 有以下文件: web_flask1.conf:(监听80端口指向127.0.0.1:8080)
server { listen 80; server_name 10.12.28.27; charset utf-8; client_max_body_size 100M; access_log /root/web_flask1/logs/nginx_access.log; # 服务器接收的请求日志 error_log /root/web_flask1/logs/nginx_error.log; # 错误日志 location / { include uwsgi_params; #uwsgi_pass unix:/root/web_flask/flask_uwsgi.sock; uwsgi_pass 127.0.0.1:8080; } }
web_flask2.conf:(监听70端口指向127.0.0.1:7070)
server { listen 70; server_name 10.12.28.27; charset utf-8; client_max_body_size 100M; access_log /root/web_flask2/logs/nginx_access.log; # 服务器接收的请求日志 error_log /root/web_flask2/logs/nginx_error.log; # 错误日志 location / { include uwsgi_params; #uwsgi_pass unix:/root/web_flask/flask_uwsgi.sock; uwsgi_pass 127.0.0.1:7070; } }
好了,配置结束。重启nginx
在我的电脑浏览器输入10.12.28.27:80,出现Hello,Flask!
在我的电脑浏览器输入10.12.28.27:70,出现Hello,Flask!