flask+uwsgi

"nginx"

Posted by zwt on August 12, 2020

项目

编写各种服务 主要流程:

1
2
3
4
5
6
7
8
首先客户端请求服务资源,
nginx作为直接对外的服务接口,接收到客户端发送过来的http请求,会解包、分析,
如果是静态文件请求就根据nginx配置的静态文件目录,返回请求的资源,
如果是动态的请求,nginx就通过配置文件,将请求传递给uWSGI;uWSGI 将接收到的包进行处理,并转发给wsgi,
wsgi根据请求调用django/flask工程的某个文件或函数,处理完后django/flask将返回值交给wsgi,
wsgi将返回值进行打包,转发给uWSGI,
uWSGI接收后转发给nginx,nginx最终将返回值返回给客户端(如浏览器)。
*注:不同的组件之间传递信息涉及到数据格式和协议的转换

作用:

1
2
3
4
1. 第一级的nginx并不是必须的,uwsgi完全可以完成整个的和浏览器交互的流程;
2. 在nginx上加上安全性或其他的限制,可以达到保护程序的作用;
3. uWSGI本身是内网接口,开启多个work和processes可能也不够用,而nginx可以代理多台uWSGI完成uWSGI的负载均衡;
4. django/flask在debug=False下对静态文件的处理能力不是很好,而用nginx来处理更加高效。

uwsgi

一种线路协议实现了wsgi,web服务器,代码用c编写,性能好。

Flask 是一个 Web 应用框架,框架的作用在于处理 request 和 reponse,使用的是 Python 自带的 simple HTTPServer 创建的,在安全性和效率上都是不行的,而uWSGI 是一个全功能的 HTTP 服务器,他要做的就是把 HTTP 协议转化成语言支持的网络协议。比如把 HTTP 协议转化成 WSGI 协议,让 Python 可以直接使用。 uwsgi 是一种 uWSGI 的内部协议,使用二进制方式和其他应用程序进行通信。

安装:pip install uwsgi
如果报错:error: lto-wrapper failed 
collect2: error: ld returned 1 exit status

问题是由于gcc版本过高:
查看当前系统gcc版本:ls /usr/bin/gcc* -l
如果系统版本高于5,则安装:sudo apt-get  install gcc-4.8
更改系统gcc默认版本:
sudo rm /usr/bin/gcc #删除已有软连接
sudo ln -s /usr/bin/gcc-4.8 /usr/bin/gcc #创建指向gcc4.8的软连接

配置文件:创建config.ini

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[uwsgi]
# uwsgi 启动时所使用的地址与端口 uwsgi配置ip:0.0.0.0,公网才能访问到, 127.0.0.1:8080
# socket = 0.0.0.0:8080 
# 外网访问端口,如果直接用uWSGI外网,这里由于使用了Nginx,故注释掉
http= 0.0.0.0:8080
# 指向项目地址
chdir = /root/robot/zwt/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
pidfile = /root/robot/zwt/web_flask/uwsgi.pid #指定pid文件

运行:

1
uwsgi config.ini

到这里,项目已经具备了高并发的能力,但是对于静态文件来说,uwsgi处理不好,同时其安全性也不好,所以通常需要加上nginx做反向代理。

在这之前,还需要做一件事,比如:我现在有一个进程需要每时每刻不断的跑,但是这个进程又有可能由于各种原因有可能中断。当进程中断的时候我希望能自动重新启动它,此时,我就需要使用到了Supervisor,supervisor管理进程,是通过fork/exec的方式将这些被管理的进程当作supervisor的子进程来启动,所以我们只需要将要管理进程的可执行文件的路径添加到supervisor的配置文件中就好了。此时被管理进程被视为supervisor的子进程,若该子进程异常中断,则父进程可以准确的获取子进程异常中断的信息,通过在配置文件中设置autostart=ture,可以实现对异常中断的子进程的自动重启。

supervisor

主要是用来实现对进程的管理,通过配置启动uwsgi,来对其进行管理。

安装:yum install supervisor

配置文件:/etc/supervisord.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
在末尾添加:
[program:myBlog]
# 启动命令入口
command=/home/robot/anaconda3/envs/robot/bin/uwsgi /home/robot/zwt/myBlog/config.ini

# 命令程序所在目录
directory=/root/robot/zwt/myBlog
#运行命令的用户名
user=root
autostart=true   # supervisor启动的时候是否随着同时启动
autorestart=true  # 当程序跑出exit的时候,这个program会自动重启
startsecs=3   # 程序重启时候停留在runing状态的秒数
#日志地址
stdout_logfile=/root/robot/zwt/myBlog/uwsgi_supervisor.log

相关命令:

1
2
3
4
5
6
7
8
9
10
启动:supervisord
命令行:supervisorctl
状态:status

supervisorctl status //查看状态
supervisorctl stop [进程名] //停止
supervisorctl start [进程名]

查看uwsgi启动的进程号
ps -ef | grep uwsgi

出现Another program is already listening on a port that one of our HTTP servers is configured to use.”错误时的解决方法:

1
2
3
4
5
进入到命令行
reread:重新读取配置
update:更新配置
start all:更新配置
status:查看所有状态

nginx

安装:yum install nginx,默认配置文件nginx.conf中有include /etc/nginx/conf.d/*.conf;

配置文件:vi /etc/nginx/conf.d/my_nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
    listen      80;
    server_name  10.12.28.27;  # 服务器ip,
    charset    utf-8;
     access_log      /root/robot/zwt/myBlog/nginx_access.log;
    error_log       /root/robot/zwt/myBlog/nginx_error.log;
    client_max_body_size 100M;

    location / {
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:8080;
    }
}

参考

  1. uwsgi.ini配置文件常用参数
  2. flask+uwsgi+supervisor+nginx在局域网服务器上部署实践
  3. uwsgi、wsgi和nginx的区别和关系