1. 梳理一下 nginx、WSGI、uwsgi、uWSGI、django/flask 关系

wsgi:全称web server gateway interface,wsgi不是服务器,也不是python模块,只是一种协议,描述web server如何和web application通信的规则。运行在wsgi上的web框架有bottle,flask,django.
uwsgi:和wsgi一样是通信协议,是uWSGI服务器的单独协议,用于定义传输信息的类型
uWSGI:是一个web服务器,实现了WSGI协议,uwsgi协议。性能块,内存占用低,详尽的日志功能,高度可定制。
nginx:web服务器,更加安全,更好的处理处理静态资源,缓存功能,负载均衡,因此nginx的强劲性能,配合uWSGI服务器会更加安全,性能有保障。
django/falsk:高级的python web框架,用于快速开发,解决web开发的大部分麻烦,程序员可以更专注业务逻辑,无须重新造轮子。

2. 使用uWSGI

    flask和Django一样,它们内部都没有实现socket服务端,需要依赖wsgi,而werkzurg作为flask依赖的wsgi,本质上提供了socket服务端,用于接收用户请求。它有着性能块,内存占用低,详尽的日志功能,高度可定制等优点。

用uWSGI启动flask项目:

  1. 创建项目的虚拟环境,并进入虚拟环境
python -m venv flask_env
source flask_env/bin/activate
  1. 安装本项目需要的三方包
    如果用uWSGI启动项目的话,需要额外安装 uWSGI 三方包。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple uWSGI
  1. 使用命令行或增加配置文件来启动flask
    使用命令行方式启动,–py-autoreload=1表示热加载flask项目:
flask_env/bin/uwsgi --http :8000 --wsgi-file app.py --callable app --py-autoreload=1

     使用配置文件方式启动—推荐使用:

flask_env/bin/uwsgi  --ini flask/project/flask_uwsgi.ini

flask_uwsgi.ini 内容如下:

[uwsgi]
http = 0.0.0.0:8000			# 如果不用nginx,直接使用uwsgi运行flask服务,就用这个http参数
chdir = /export/myflask/
wsgi-file = app.py
callable = app
processes = 1			
py-autoreload=1			# 表示项目有改动的话,自动重新加载

3. 使用nginx服务

    不使用nginx服务也可以起来,为什么还需要使用nginx呢?见下文第三点。

1 首先nginx 是对外的服务接口,外部浏览器通过url访问nginx。
2  nginx接收到浏览器发送过来的http请求,将包进行解析,分析url,如果是静态文件请求就直接访问用户给nginx配置的静态文件目录,直接返回用户请求的静态文件,如果不是静态文件,而是一个动态的请求,那么nginx就将请求转发给uwsgi, uwsgi接收到请求之后将包进行处理,处理成wsgi可以接受的格式,并发给wsgi, wsgi 根据请求调用应用程序的某个文件的某个函数,最后处理完将返回值再次交给uwsgi,uwsgi将返回值进行打包,打包成uwsgi能够接收的格式,uwsgi接收wsgi 发送的请求,并转发给nginx, nginx最终将返回值返回给浏览器。
3 要知道第一级的nginx并不是必须的,uwsgi完全可以完成整个的和浏览器交互的流程,但是要考虑到某些情况:
    (1) 安全问题。程序不能直接被浏览器访问到,而是通过nginx,nginx只开放某个接口,uwsgi本身是内网接口,这样运维人员在nginx上加上安全性的限制,可以达到保护程序的作用。
    (2)负载均衡问题,一个uwsgi很可能不够用,即使开了多个work也是不行,毕竟一台机器的cpu和内存都是有限的,有了nginx做代理,一个nginx可以代理多台uwsgi完成uwsgi的负载均衡。
    (3)静态文件问题,用django,flask或是uwsgi这种东西来负责静态文件的处理是很浪费的行为,而且他们本身对文件的处理也不如nginx好,所以整个静态文件的处理都直接由nginx完成,静态文件的访问完全不去经过uwsgi以及其后面的东西。
配置nginx反向代理和负载均衡

准备3台机器:
192.168.3.40:nginx代理服务器
192.168.3.41:flask服务1
192.168.3.42:flask服务2

请求数据: windows   ——>   192.168.3.40   ——>   192.168.3.41/192.168.3.42
返回数据: windows   <——   192.168.3.40   <——   192.168.3.41/192.168.3.42

修改代理服务器192.168.3.40的配置文件 nginx.conf

# 配置nginx负载均衡节点
    upstream flask {
        server 192.168.3.41:8001;
        server 192.168.3.42:8001 weight=5;
    }

    server {
        listen       80;
        listen       [::]:80;
        server_name    www.myflask.com;

        # nginx处理静态文件
        location /static {
            alias /export/myflask/static;
        }

        location / {
            uwsgi_pass  flask;    # 配置代理,将请求转发到名为flask的负载节点
            include  uwsgi_params; 
        }

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }

nginx相关命令:

- 重新加载配置项
	nginx -s reload
- 启动相关
	systemctl start nginx
	systemctl stop nginx
	systemctl restart nginx
- 开机启动
	systemctl enable nginx

4. 使用nginx+uWSGI拉起flask项目

  1. 如果uWSGI配合nginx来拉起flask项目的话,需要修改flask项目里的uWSGI 配置文件。
[uwsgi]
socket = 0.0.0.0:8001	# 改这块,把http改成socket
chdir = /export/myflask/
wsgi-file = app.py
callable = app
processes = 1
virtualenv = /export/envs/flask_env
py-autoreload=1
  1. 修改nginx配置文件,配置静态文件的处理,和反向代理,以及负载均衡。
# 配置nginx负载均衡节点
    upstream flask {
        server 192.168.3.41:8001;
        server 192.168.3.42:8001 weight=5;
    }

    server {
        listen       80;
        listen       [::]:80;
        server_name    www.myflask.com;

        # nginx处理静态文件
        location /static {
            alias /export/myflask/static;
        }

        location / {
            uwsgi_pass  flask;    # 配置代理,将请求转发到名为flask的负载节点
            include  uwsgi_params; 
        }

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
  1. 启动nginx服务:systemctl start nginx
  2. 一条命令启动项目即可。
nohup flask_env/bin/uwsgi --ini flask/project/flask_uwsgi.ini >> flask/project/outlog.log &
  1. 如果嫌停止或重启项目太麻烦的话,写个shell脚本放在项目目录下。
    重启flask项目脚本:restart.sh
#!/usr/bin/env bash

# -V:反过滤
echo -e "\033[34m--------------------wsgi process--------------------\033[0m"
ps -ef|grep flask_uwsgi.ini | grep -v grep
sleep 0.5

echo -e '\n--------------------going to close--------------------'
ps -ef |grep flask_uwsgi.ini | grep -v grep | awk '{print $2}' | xargs kill -9
sleep 0.5

echo -e '\n----------check if the kill action is correct----------'
/export/flask_env/bin/uwsgi  --ini  flask_uwsgi.ini &  >/dev/null
echo -e '\n\033[42;1m----------------------started...----------------------\033[0m'
sleep 1

ps -ef |grep flask_uwsgi.ini | grep -v grep

停止flask项目脚本:stop.sh

#!/usr/bin/env bash

echo -e "\033[34m--------------------wsgi process--------------------\033[0m"
ps -ef |grep flask_uwsgi.ini | grep -v grep
sleep 0.5

echo -e '\n--------------------going to close--------------------'
ps -ef |grep flask_uwsgi.ini | grep -v grep | awk '{print $2}' | xargs kill -9
sleep 0.5