后端技术学习&&总结
前端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