注意:这里假定nginx已经搭建,flask应用已经可以在本地运行。

这里设置uWSGI并不采用通常的Python Virtual Environment,即Python的虚拟环境。


不采用Python Virtual Environment的原因

在更新了Ubuntu 15.04后,我好奇15.04的默认python是什么版本,所以直接

python

shell马上提醒我并没有python这个命令,将信将疑换命令

python3

很快显示是python 3.4.3

当键入命令

python2

python27

python2.7

时均显示没有命令。

虽然我没有去仔细找15.04的change log,但我感觉Ubuntu为了解决14.04下恼人的

python

即python 2.7版本,且手动改变python的符号链接会出现问题,而直接在15.04中将python设为了缺省;让用户放心大胆调整python命令的实际python版本。

因为这个原因,我没有考虑Python Virtual Environment,只需要给自己的falsk app设定正确的python版本就可以了,如想要python命令为python 3.4.3版本的话,只需要创建符号连接:

ln -s /usr/bin/python3 /usr/bin/python

而实际上,我也尝试过使用Python Virtual Environment,但在实际运行,尤其是加载flask扩展是,出现了很多意想不到的问题,遂最终放弃Python Virtual Environment。

测试flask app是否能够正常运行

将flask主程序run()部分修改一下:

if __name__ == "__main__":
    app.run(host='0.0.0.0')

然后

python myproject.py

正常启动后浏览器通过IP访问,即http://IP:5000,app能够正常工作,则测试结束;否则需要手动排查错误,这里错误一般是app本身的错误。

CTRL+C停止flask服务。

安装并配置uWSGI

安装

pip install uwsgi

或者可能是

pip3 install uwsgi

配置

首先测试uWSGI能否正常工作,切换到app目录

uwsgi --socket 0.0.0.0:8000 --protocol=http -w myproject

myproject即启动flask的myproject.py文件

此时通过IP访问,即http://IP:8000,app能够正常工作,则测试结束。

接下来创建uWSGI配置文件,在app目录下创建myproject.ini(名字可以任意改动,systemd配置部分需要用到)

nano myproject.ini

文件内容如下:

[uwsgi]
module = myproject

master = true
processes = 5

socket = myproject.sock
chmod-socket = 777
vacuum = true

die-on-term = true

module = myproject即上述的myproject.py
socket = myproject.sock即创建的sock,这里myproject名字可以任意改,注意之后nginx配置时需要用到
chmod-socket = 777设置sock文件权限为777是为了避免access denied错误

配置systemd

Ubuntu 15.04中采用systemd而默认没有安装upstart,所以这里也采用systemd

创建systemd服务文件

nano /etc/systemd/system/myproject.service

(这里myproject名字任意,即为以后启动服务的名字)

内容如下:

[Unit]
Description=uWSGI instance to serve 12306
After=network.target

[Service]
User=me
Group=me
WorkingDirectory=/home/me/myproject
Environment="PATH=/usr/bin"
ExecStart=/usr/bin/uwsgi --ini myproject.ini

[Install]
WantedBy=multi-user.target

注意:uwsgi目录/usr/bin/uwsgi可能需要修改为/usr/local/bin/uwsgi


User=me
Group=me
WorkingDirectory=/home/me/myproject
中的me均为系统中的用户,注意这里尽可能不要设置用户为root
WorkingDirectory=/home/me/myproject即app路径
ExecStart=/usr/bin/uwsgi --ini myproject.ini中ini文件即为之前创建的ini文件

打开实时日志

这是为了便于查看使用systemd启动app时是否正常启动

journalctl -f

这样即能看到实时的最新日志

启动app

打开新的终端,systemctl启动app

systemctl start myproject

此时实时日志中会显示uwsgi启动信息,出现如 1 app running之类的即启动成功,否则需要排除错误。

停止app命令:

systemctl stop myproject

如果没问题,则可以将app设为开机启动

systemctl enable myproject

注意:此时app虽然在运行,但并不能通过IP访问到。

配置nginx

nginx的配置很简单,只需要将对应的请求发送给uWSGI就可以了,即那个sock文件。

编辑nginx配置文件

nano /etc/nginx/sites-available/default

添加一个新的server:

server {
    listen 80;
    server_name the.domain.you.want.com;
    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/me/myproject/myproject.sock;
    }
}

即传递给之前设置的sock文件。

重启nginx:

service nginx restart

提示:之后可以考虑对此server设置gzip压缩,如默认不压缩的json数据。

不出意外的话现在就可以通过设定的地址访问此flask app了。


一些注意事项:

  • 如果一直到systemd启动app都没问题,但nginx设置后不能访问,如出现500错误,需要去查看nginx的日志,绝大部分情况是access denied
  • 如果日志记录是file not exist,考虑是否app没有启动
  • 将app设为开机启动后,可能app在某些依赖没有就绪的情况下就启动了,这是需要手动stop并start
  • 在全部配置好,并正常运行后,可以考虑nginx中设置将此app的server日志单独记录
  • 可以考虑将uwsgi日志记录到文件,而不是stdout
  • 注意测试完毕后关闭flask的debug模式

参考:
How To Serve Flask Applications with uWSGI and Nginx on Ubuntu 14.04
How To Serve Flask Applications with Gunicorn and Nginx on CentOS 7
How To Serve Flask Applications with uWSGI and Nginx on CentOS 7
Quickstart for Python/WSGI applications uWSGI 2.0 documentation