Mac系统下,Flask、uwsgi、Nginx部署应用

最近微信不是出个小程序,试了一下觉得还挺好玩,朋友说想和我做一个,本来做iOS开发的,仗着自己有些服务器底子,感觉python挺好用,直接就开始干了。
本来以为就部署个服务器么,后来发现有好多坑,网上也有别人写的,但是大多是Linux下的部署方式,与Mac有些小差异,所以就记下来,免得以后忘。

1.安装Flask

移步这里:
http://docs.jinkan.org/docs/flask/installation.html#installation

2.配置uwsgi

$pip install uwsgi
然后在项目目录下新建config.ini文件,内容如下

[uwsgi]
master = true
home = /System/Library/Frameworks/Python.framework/Versions/2.7  //python目录
wsgi-file = run.py  //flask程序入口
callable = app   //flask的app变量,是Flask实例
socket = 127.0.0.1:3031  
processes = 4
threads = 2
buffer-size = 32768
protocol = http
module = app

这时输入uwsgi config.ini就可以运行服务了。
但是我当时碰到了一个no module found: site 的错误,因为不了解python,查了好长时间才知道site指的是python的安装目录下的一个site.py文件,也就是这个文件找不到,所以就是home路径设置有问题,当时我是用witch python命令查看的python路径,但是这个路径下没有site.py文件,后来又查到了一个查看路径方法,如下:

input python进入命令行模式,
<<import sys
<<print sys.path
如果运行后找不到app移步这里:
http://stackoverflow.com/questions/31476441/unable-to-load-app-0-mountpoint-flask-app-with-uwsgi

3.配置supervisor

由于我们最初的目的是想让Nginx托管Flask,但是由于Ngxin是不支持直接与Flask交流的,所以需要uwsgi做中间的服务层,但是我们肯定不希望每次启动服务时还要先启动uwsgi,再启动Nginx,这时我们就需要supervisor了

brew services start supervisor
然后进行配置,找到supervisor安装目录

cd /etc
sudo touch supervisord.conf
sudo chmod 777 /etc
sudo chmod 777 /supervisord.conf

编辑supervisord.conf

[program:blog] 
 # 启动命令入口 
command=uwsgi /Users/alienchang/Desktop/workspace/MediaServer/config.ini             
 # 命令程序所在目录 
directory=/Users/alienchang/Desktop/workspace/MediaServer/
 #运行命令的用户名 
user=Alienchang
autostart=true
autorestart=true

brew services start supervisor

supervisord -c /etc/supervisord.conf

如果出现问题执行

echo_supervisord_conf >> /etc/supervisord.conf

添加默认配置到supervisord.conf

supervisorctl是supervisord的进程管理,可以用来控制stop和restart

但是我发现supervisorctl关闭进程却不能关闭uWSGI的进程
所以我就手动kill了

提示:
Another program is already listening on a port that one of our HTTP servers is configured to use

后来发现不是不能结束进程,而是不能释放端口,后来查了解决方案
sudo unlink /usr/local/var/run/supervisor.sock
这样就可以释放端口了

killall -9 uwsgi

查看端口占用命令

lsof -i tcp:port 

4.配置Nginx

brew install nginx

brew info nginx查看nginx安装目录,找到config文件,我的是/usr/local/etc/nginx/nginx.conf,chmod 777 修改权限,在nginx.conf中添加

server {
     listen       80;
     server_name  127.0.0.1;
     #server_name localhost;
     location / {
         #include uwsgi_params;
         include uwsgi_params;
         uwsgi_pass 127.0.0.1:8001;
         uwsgi_param UWSGI_PYHOME /System/Library/Frameworks/Python.framework/Versions/2.7;
         uwsgi_param UWSGI_CHDIR  /Users/alienchang/Desktop/workspace/MediaServer/;
         uwsgi_param UWSGI_SCRIPT app:app;
    }
 }

重启Nginx服务:sudo service nginx restart

此时,又出现问题了!
....upstream prematurely closed connection while reading response header from upstream uwsgi....

经过反复检查,每个部件都没有问题。刷了一天的stackoverflow,才找到答案,还不知道为什么(求轻喷)那篇文章还找不到了。。
解决方案是把nginx.config的
uwsgi_param http://127.0.0.1:8001
改为
proxy_pass http://127.0.0.1:8001

我没记错的话那个答案的意思跟下面的意思差不多:
http://stackoverflow.com/questions/34562730/difference-between-uwsgi-pass-and-proxy-pass-in-nginx

!!!已经找到问题,细心的人应该发现我上面的uwsgi的config.ini文件写了protocol = http,意思是uwsgi使用http协议,但是nginx.config文件中写的是uwsgi_pass,使用的是uwsgi的协议,所以冲突了,把他们都设置统一的协议就可以:
1.uwsgi.ini 中 protocol = http ,nginx.config 中 使用proxy_pass
2.uwsgi.ini 中 去掉protocol = http ,nginx.config 中使用uwsgi_pass
然后我的项目就可以正常运行了

参考:

http://www.jianshu.com/p/84978157c785
http://stackoverflow.com/questions/31476441/unable-to-load-app-0-mountpoint-flask-app-with-uwsgi
http://dhq.me/mac-supervisor-install

本文使用demo:
https://github.com/Alienchang/MediaServer.git

推荐阅读更多精彩内容