后端技术学习&&总结
前端Vue.js,后端Flask+Uwsgi+Nginx+Redis+mysql,项目配了TF+Keras两个模型。对学习的后端技术进行总结,分为下面几部分
- 安装&&踩坑
- 配置&&踩坑
- 作用&&解析
安装&&踩坑
Uwsgi安装
安装其实很简单的一条命令:pip install uwsgi,但通常ubuntu用户安装时编译会报错,如下:
1 | fatal error: bytecode stream generated with LTO version x.0 instead of the expected x.x |
首先建议使用conda的环境,避免是没有类似python-dev这样基础的环境包导致报错。
然后这个报错写着是LTO版本不对,但官方文档上说asd,可以看下这里,其实应该是gcc版本不对,太高了。
解决方法:降低gcc版本(我的16.04原来gcc版本是5.4)
1 | #安装 |
Redis安装
首先在Ubuntu上安装Redis,安装完成后Redis服务会自动启动
1 | sudo apt-get update |
手动启动则输入redis-server即可
Nginx安装
简单点,apt-get安装
1 | apt-get install nginx |
配置
概要:配置uwsgi.ini,启动uwsgi。
Uwsgi配置
Uwigi最重要的配置就是uwsgi.ini了,配置首先第一步是touch创建uwsgi.ini后放在项目根目录。
几个基本参数
pythonpath:python环境目录。如果是conda的环境就不用配置这个了,shell里source activate YourEnv即可。如果是自己创的虚拟环境,则配置到python环境bin目录下的python,e.g:1
2# 指定python环境
pythonpath = /home/applex/conda/envs/myproject/bin注:还有两个参数
home和一个指定虚拟环境env啥的,容易报一个Encoding错,建议别用。http参数,http协议对客户端开发的端口号,客户端通过此端口访问flask web服务接口。如果设置了该参数其实等同与同时设置了1
2protocol = http #设置默认的通信协议(uwsgi,http,fastcgi)
socket = 127.0.0.1:5000 #5000是举个例子wsgi-file和chdir。wsgi-file是web应用python主程序。chdir是项目根目录,即当前工作台。我的项目根目录为/home/kavin/rjb/,主程序为app.py,shell开在项目根目录,所以这里该这么写:1
2chdir = /home/kavin/rjb/
wsgi-file = app.py #看shell位置设置打注:这里的设置不对很容易报错
unable to load app 0......。还有个坑就是项目的module或者app都得有__init__.py这个文件,不然也会报这个错(这坑躺了挺久…)master参数。启动主进程,来管理其他进程,其它的uwsgi进程都是这个master进程的子进程,如果kill这个master进程,相当于重启所有的uwsgi进程。下面说说我遇到的问题,通常博客给的设置里
master=true,但是我做的项目里运行tf+keras模型,一设置该参数就报一个CUDA的错。所以行tf+keras模型时将该参数去掉。buffer_size参数,设置用于uwsgi包解析的内部缓存区大小为64k。默认是4k,即4096Bit。但如果先项目运行tf+keras模型,则建议修改为:1
buffer-size = 327680
其他几个常用参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器
daemonize = /var/log/myapp_uwsgi.log
#设置最大日志文件大小
log-maxsize = 5000000
#指定pid文件
pidfile = /var/run/uwsgi.pid
#当服务器退出的时候自动删除unix socket文件和pid文件
vacuum = true
#启动2个工作进程,生成指定数目的worker/进程
processes = 2
#启动10个工作线程
threads = 10
# 一般在主运行程序 run_app.py 里指定 app = Flask(__name__)
callable = app下面给出我的基础配置
1
2
3
4
5
6
7
8
9
10[uwsgi]
master = true
http = 127.0.0.1:5000 # 不开nginx代理时使用
socket = 127.0.0.1:5000 # 开nginx代理时使用
chdir = /home/kavin/rjb/
wsgi-file = app.py
callable = app
processes = 1
threads = 3
buffer-size = 327680
几个命令
然后启动uwsgi.ini。
启动
1
uwsgi --ini uwsgi.ini
查看
uwsgi是否运行1
ps -aux | grep uwsgi
查看端口号占用
1
netstat -anp | grep 7878 # 上一步查出来的
结束
uwsgi进程1
pgrep uwsgi | xargs kill -s 9
Nginx配置
概要:配置nginx.conf,检测配置文件,启动。
首先简单看一下nginx的文件结构。
/usr/sbin/nginx:主程序/etc/nginx:存放配置文件/usr/share/nginx:存放静态文件/var/log/nginx:存放日志
可以先使用sudo /etc/init.d/nginx start启动默认的配置试试~
然后在项目根目录创建nginx.conf,编辑如下(附带解释):
1 | Flask dataV api |
注意!配置完毕后我们萌新常犯一个错误,直接这样启动nginx:
1 | sudo nginx /home/kavin/rjb/nginx.conf |
会报错:
1 | nginx: [emerg] "server" directive is not allowed here in /home/kavin/rjb/nginx.conf:1 |
按照英文提示,我们应该将配置存放在允许的地方。我推荐按照下面两部走:
首先,删除默认配置并将项目配置文件软链接到目的地
1
2sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /home/kavin/rjb/nginx.conf /etc/nginx/conf.d/其次,检测配置文件是否正确
1
nginx -t -c /etc/nginx/nginx.conf
若无问题,则可以启动Nginx。
我的一些习惯命令是:
1 | sudo /etc/init.d/nginx start |
Redis配置
概要:修改程序主文件,启动Redis。Redis是高性能的key-value数据库.flask也提供了缓存模块flask-cache,该模块可以连接Redis数据库进行缓存。具体来说,可以缓存以下几个方面:
1 | 1、缓存视图函数 |
以下是参考的博客的经验总结:
1 | 一般在项目中,因为业务的复杂性,一般使用缓存api自定义缓存,这样更加灵活。比如电商的首页的商品分类和模块栏,一般都是不变的,这样的内容可以缓存起来。 |
我们项目这里采用了Redis结合Flask-cache来缓存视图,具体如下(附解释):
1 | from flask_cache import Cache |
几个基本命令
- 执行命令访问Redis客户端:\redis-cli**
- 设置键值对命令:\set key value**
- 取出键值对命令:\get key**
- 启动命令:\redis-server**
然后启动Redis,界面怪好看的~
作用&&解析
我的项目生产环境配置是Flask+Uwsgi+Nginx+Redis+mysql,前端找大哥用Vue写的,项目内调用了tf+keras的模型。
项目一开始成型的时候其实只有Flask+mysql,在本地也能跑的挺好哒,那为什么需要配置这些呢?下面是我在配置中的学习记录和理解。
Uwsgi理解
若直接使用Flask自带的WSGI(Web服务器):Werkzeug,会提示Not in preducting enviroment...,可能会觉得没啥问题。
但是对于大项目来说,flask自带的开发Web服务器表现很差,响应慢,而且直接通过nginx进行反向代理,经常无法响应请求。有两个可以在生产环境中使用、性能良好且支持Flask程序的服务器,分别是Gunicorn和uWSGI,但是这两个模块不提供对windows的支持。
uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。
uWSGI的主要特点是:
- 超快的性能
- 低内存占用
- 多
app管理 - 详尽的日志功能(可以用来分析
app的性能和瓶颈) - 高度可定制(内存大小限制,服务一定次数后重启等)
要注意WSGI / uwsgi / uWSGI这三个概念的区分
WSGI是一种通信协议。uwsgi是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器的数据通信。- 而
uWSGI是实现了uwsgi和WSGI两种协议的Web服务器。
uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。
为什么使用uWSGI?uWSGI的好处?
一下摘自知乎:
1 | 通常最好在与主Web服务器分开的过程中运行Python。这样,Web服务器可以有很多细小的线程,它们可以非常快速地为静态内容提供服务,而单独的Python进程将会很大并且很重量级,并且每个都会运行他们自己的Python解释器。所以普通WSGI是不好的,因为它用一个大的Python解释器膨胀了你的每一个nginx线程。 |
uWSGI服务器自己实现了基于uwsgi协议的server部分,我们只需要在uwsgi的配置文件中指定application的地址,uWSGI就能直接和应用框架中的WSGI application通信。
Nginx理解
搬运自博客:
1 | Nginx 是高效的 Web 服务器和反向代理服务器,可以用作负载均衡(当有 n 个用户访问服务器时,可以实现分流,分担服务器的压力),与 Apache 相比,Nginx 支持高并发,可以支持百万级的 TCP 连接,十万级别的并发连接,部署简单,内存消耗少,成本低,但 Nginx 的模块没有 Apache 丰富。Nginx 支持 uWSGI 的 uwsgi 协议,因此我们可以将 Nginx 与 uWSGI 结合起来,Nginx 通过 uwsgi_pass 将动态内容交给 uWSGI 处理。 |
Redis理解
下面是对Redis简单的介绍。
Redis是一个高性能的key-value数据库;将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用;Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储;Redis支持数据的备份,即master-slave模式的数据备份。
而类似Django框架,Flask提供了flask-cache模块去链接Redis数据库,来提高访问速度和减少服务器负载,具体来说Flask使用Redis可以缓存:
1 | 1、缓存视图函数 |
在前面配置部分已经给出,请见前。
感受
写的挺浅滴,是为了项目所用的,之后有空继续深入。附一下运行我的项目所有步骤:
1 | 先开一个shell用于redis |
参考
1 | uwsgi |
TODO
深度解析:
WSGI,uWSGI原理层面。Nginx参数配置和解析Redis使用和解析
——Kevin