生产环境中,一般使用nginx+UWSGI的方式部署flask项目。
nginx
直接通过uWSGI或gunicorn也可以让外网访问到,但是nginx具有高性能、高并发、静态文件缓存等优点,选择nginx很有必要。
普遍的部署方式都是通过让nginx绑定80端口,并接受客户端的请求将动态内容的请求反向代理给运行在本地端口的uWSGI或者Gunicorn,所以既可以通过nginx+uWSGI也可以通过nginx+Gunicorn来部署Flask应用。
nginx优点:
- 安全;不管什么请求都需要经过代理服务器,避免了外部程序直接攻击web服务器。
- 负载均衡:根据请求情况和服务器负载情况,将请求分配给不同的web服务器,保证服务器性能。
- 提高web服务器的IO性能:对于一些静态文件,可以直接由反向代理处理,不经过web服务器。
nginx配置
在项目使用中,使用最多的三个核心功能是静态服务器、反向代理和负载均衡。这三个不同的功能的使用,都跟nginx的配置密切相关,nginx服务器的配置信息主要集中在nginx.conf这个配置文件中,并且所有的可配置选项大致分为以下几个部分:
main # 全局配置
events { # 工作模式配置
}
http { # http设置
....
server { # 服务器主机配置(虚拟主机、反向代理等)
....
location { # 路由配置(虚拟目录等)
....
}
location path {
....
}
location otherpath {
....
}
}
server {
....
location {
....
}
}
upstream name { # 负载均衡配置
....
}
}
- main模块
- event模块
- http模块
作为web服务器,http模块是nginx最核心的一个模块,配置项也是比较多的,项目中会设置到很多的实际业务场景,需要根据硬件信息进行适当的配置。
- 基础配置
- 日志配置
- SSL证书配置
- 压缩配置
- 文件缓存配置
- server模块
- location模块
location模块是nginx配置中出现最多的一个配置,主要用于配置路由器访问信息。在路由访问信息配置中关联到反向代理、负载均衡等等各项功能,所以location模块也是一个非常重要的配置模块。
- 基本配置
- 反向代理配置
- uwsgi配置
- 负载均衡模块(upstream)
配置nginx
在/etc/nginx/sites-available/目录下,default文件内容为:
upstream flask_stream{
server 127.0.0.1:6666;
server 127.0.0.1:7777;
}
server{
listen 80 default_server;
listen [::]:80 default_server;
server_name_;
location / {
include uwsgi_params;
uwsgi_pass flask_stream;
uwsgi_send_timeout 1060;
uwsgi_connect_timeout 1060;
uwsgi_read_timeout 1060;
}
}
在/etc/nginx/sites-enabled/目录下,default文件内容为:
upstream flask_stream{
server 127.0.0.1:6666;
server 127.0.0.1:7777;
}
server{
listen 80 default_server;
listen [::]:80 default_server;
server_name_;
location / {
include uwsgi_params;
uwsgi_pass flask_stream;
uwsgi_send_timeout 1060;
uwsgi_connect_timeout 1060;
uwsgi_read_timeout 1060;
}
}
在/etc/nginx/sites-enabled/目录下,imageretrieval6666和imageretrieval7777内容为:
server{
listen 8066 default_server;
listen [::]:8066 default_server;
server_name_;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:6666;
uwsgi_send_timeout 1060;
uwsgi_connect_timeout 1060;
uwsgi_read_timeout 1060;
}
}
WSGI(Web Server Gateway Interface)-uwsgi-uWSGI
- WSGI
- uwsgi
- uWSGI
uWSGI服务器的安装与配置
安装
配置uwsgi的服务,将uwsgi服务加入系统进程,可以使用如下两种方式安装:
测试uWSGI
在服务器上写一个test.py,uWSGI Python加载器将会搜索的默认函数application。
#test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return 'Hello World'
启动uWSGI,运行一个HTTP服务器,将程序部署在HTTP8001端口上。
uwsgi --http :8001 --wsgi-file test.py
访问网页http:115.28.0.87:8001/, OK,显示Hello World,就说明uwsgi安装成功。
flask项目下uwsgi的配置方式
uwsgi通信接口配置的三种方式:
- socket方式
现在的大部分的web服务器(如nginx)支持uwsgi,这是一种高效的形式,socket通信速度会比HTTP块。
socket=127.0.0.1:8888
- http-socket方式
适用于web服务器不支持uwsgi时。
http-socket=127.0.0.1:8888
- http方式
HTTP方式会额外产生一个HTTP进程,如果通过nginx转发,效率是相对较低的。
http=0.0.0.0:8888
uWSGI配置文件
前面直接使用命令来启动uWSGI,在实际部署环境中,常用配置文件的方式,而非命令行的方式。UWSGI支持多种配置文件格式,比如xml,ini,json等等。
完整的配置项
- socket : 地址和端口号,例如:socket = 127.0.0.1:50000
- processes : 开启的进程数量
- workers : 开启的进程数量,等同于processes(官网的说法是spawn the specified number of workers / processes)
- chdir : 指定运行目录(chdir to specified directory before apps loading)
- wsgi-file : 载入wsgi-file(load .wsgi file)
- stats : 在指定的地址上,开启状态服务(enable the stats server on the specified address)
- threads : 运行线程。由于GIL的存在,我觉得这个真心没啥用。(run each worker in prethreaded mode with the specified number of threads)
- master : 允许主进程存在(enable master process)
- daemonize : 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器(daemonize uWSGI)。实际上最常用的,还是把运行记录输出到一个本地文件上。
- log-maxsize :以固定的文件大小(单位KB),切割日志文件。 例如:log-maxsize = 50000000 就是50M一个日志文件。
- pidfile : 指定pid文件的位置,记录主进程的pid号。
- vacuum : 当服务器退出的时候自动清理环境,删除unix socket文件和pid文件(try to remove all of the generated file/sockets)
- disable-logging : 不记录请求信息的日志。只记录错误以及uWSGI内部消息到日志中。如果不开启这项,那么你的日志中会大量出现这种记录:
[pid: 347|app: 0|req: 106/367] 117.116.122.172 () {52 vars in 961 bytes} [Thu Jul 7 19:20:56 2016] POST /post => generated 65 bytes in 6 msecs (HTTP/1.1 200) 2 headers in 88 bytes (1 switches on core 0)- log-maxsize: 日志大小,当大于这个大小会进行切分 (Byte)
- log-truncate: 当启动时切分日志
py-autoreload = 1:监控Python模块Mtime来出发重载(只在开发时使用)
lazy-apps:true时在每个worker而不是master中加载应用,false时先加载应用再fork出worker,这样可以让worker尽量共用内存,但是socket连接不支持,所以lazy-apps为false时不要在加载应用时自动创建数据连接等。
buffer-size:设置用于uwsgi包解析的内部缓存区大小为64k,默认是4k。
listen = 120:设置socket的监听队列大小,默认为100.
enable-threads=true:运行用内嵌的语言启动线程。将允许在APP程序中产生一个子线程。
max-requests=5000:为每个工作进程设置请求数的上限。当一个工作进程处理请求数达到这个值,那么该工作进程就会被回收重用(重启),可以使用这个选项来默默对抗内存泄露。
limit-as=256:限制uWSGI的进程占用虚拟内存不超过256M,如果虚拟内存达到256M,并继续申请虚拟内存则会使程序报内存错误,本次的http请求将返回500错误。
harakiri=60:一个请求花费的衰减超过了这个harakiri超时时间,那么这个请求都会被丢弃,并且当前处理这个请求的工作进程会被回收再利用(即重启)。
stats = 127.0.0.1:9191:可以使用uwsgi top监控
ini配置
[uwsgi]
socket = 0.0.0.0:6666
master = false
pythonpath = /usr/local/flask/uwsgi-test6666/
module = flask_test:app
threads = 1
enable-threads = true
uid = 1000
启动服务
uwsgi --ini config.ini
自启动
/etc/init.d/uwsgi
uwsgi的配置存在于/etc/uwsgi/中,包含两个目录:
- apps-available 存放的是真正的配置文件的地方,可以有多个。
- apps-enabled 存放apps-available中配置文件的软连接。
在/etc/uwsgi/apps-available/目录下有test_flask.ini配置文件
在/etc/uwsgi/apps-enabled/目录下有imageretrial6666.ini配置文件
部署flask
- 创建flask项目
- 创建运行flask的虚拟环境
- 安装uwsgi和nginx
- 创建一个socket用于链接nginx和uwsgi
- 配置uwsgi
- 配置nginx
nginx+uwsgi+flask自测
- 安装
uwsgi是非root用户下安装的。
pip3 install uwsgi --user #安装
pip3 uninstall uwsgi #卸载
- 安装目录
/home/xxx/.local/bin/uwsgi
- uwsgi.ini配置
uwsgi.ini的配置文件放在了项目目录下,跟flask的启动脚本放在同一目录下。
[uwsgi]
#使用nginx时需要该关键字
#socket = 0.0.0.0:7077
#不使用nginx是需要该关键字
http = 0.0.0.0:7077
pythonpath = /mnt/disk2/xxx/work/xxx/
module = flask_test:app
#起用process manager,管理worker进程,worker进程都是这个master进程的子进程
master = true
# 进程
processes = 2
# 每个worker进程中创建两个线程
threads = 2
#不设置该关键字,请求超过4k就会报错
buffer-size = 65536
#使进程在后台运行,并将日志打到指定的日志文件或udp服务器
daemonize = ./log/uwsgi.log
#指定pid文件
pidfile = ./log/uwsgi.pid
#设置最大日志文件大小
log-maxsize = 50000000
#禁用请求日志记录
#disable-logging = true
#只在开发时使用,监控项目的py文件的mtime来出发重载,py-autoreload表示多长时间检测一次,单位秒
python-autoreload = 1
#在每个worker而不是master中加载应用,默认为false,表示先加载应用,再fork出worker,这样可以让work尽量共用内存,只有当写时才copy。
#由于先加载再fork,单有些东西是不支持fork的,比如socket连接,所以lazy-apps=false时,不要在加载应用时自动创建数据连接等
lazy-apps = true
#为每个工作进程设置请求数的上限,当一个工作进程处理的请求数达到这个值,那么该工作进程就会被回收重用(重启),可以使用这个选项俩默默对抗内存泄露。
max-requests = 5000
- 运行
uwsgi.ini在项目目录下,跟启动脚本在同一目录下,所以在uwsgi.ini文件所在目录运行下面的命令。
uwsgi --ini uwsgi.ini #启动
uwsgi -d --ini uwsgi.ini #后台启动
uwsgi --reload ./log/uwsgi.pid #重启
uwsgi --stop ./log/uwsgi.pid #停止
- 查看进程是否起来
fuser -v -n tcp 端口号 #查看端口号
fuser -k 端口号/tcp #关闭端口号
- 浏览器输入测试
在uwsgi.ini中配置http方式才可以用浏览器访问,sock方式不可以。
http://ip:port/函数名?参数1&参数2
- 安装nginx
nginx在非root用户下,需要用源码安装,比较复杂,所以nginx是在root用户下安装的。
apt-get install nginx #安装
apt-get remove nginx #卸载
- 安装目录
- 主配置文件:
/etc/nginx/nginx.conf
,主要配置文件,一般不在该文件中进行配置。 - 可以用的站点配置:
/etc/nginx/sites-available
,在该目录下创建配置文件,还需要在/etc/nginx/sites-enabled/
目录下创建一个相对应的软连接,重启服务即可用; - 启用的站点配置:
/etc/nginx/sites-enabled/
,在该目录下直接创建一个文件如nginx_uwsgi,在该文件中进行配置,重启服务即可用。 - pid目录:
/var/run/nginx/nginx.pid
- 错误日志:
/var/log/nginx/error.log
- 访问日志:
/var/log/nginx/access.log
- 默认站点目录:
/usr/share/nginx/html
- 可执行文件:
/usr/sbin/nginx
- 配置Nginx,在
/etc/nginx/sites-enabled/
目录下创建nginx_uwsgi文件,并写入以下内容。
vim nginx_uwsgi #创建文件
server{
listen 8001 default_server;
listen [::]:8001 default_server;
server_name 10.27.1.20;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:7078;
}
}
- 启动nginx
cd /etc/sbin
./nginx -t #测试配置
./nginx #启动
./nginx -s reload #重新加载
./nginx -s stop #停止
- 查看进程是否起来
fuser -v -n tcp 端口号 #查看端口号
fuser -k 端口号/tcp #关闭端口号
- 访问nginx监听的ip
http://ip:port/函数名?参数1&参数2
参考资料
结合uWSGI和Nginx部署flask项目uwsgi怎么启动停止uwsgi怎么启动停止WSGI,uwsgi, uWSGI详解浅谈uWSGI, uwsgi, WSGI 的区别uWSGI详解uWSGI详解Django学习笔记之uWSGI详解nginx+uwsgi 和nginx+gunicorn区别、如何部署Ubuntu下安装Nginx+uWSGI安装,自启动设置项目部署(nginx + uwsgi + django) 和 开机自启动django项目Nginx 安装与部署配置以及Nginx和uWSGI开机自启使用uwsgi运行flask用uWSGI和Nginx部署Flask项目的方法示例uwsgi部署flask使用uwsgi部署flaskLinux+uWSGI+flask部署flask项目下的uwsgi配置方式及示例uwsgi.ini配置文件常用参数uwsgi常用配置uWSGI选项