背景
之前一直是通过tensorflow的cpu版本进行训练,工程化的时候需要把ckpt模型转换为.pb,然后继承到spark中运行。但是这样会有几个问题:
- 模型不能进行序列化,不能通过广播传递模型,也不能做唯一的加载,只能是对每个批次的数据进行预测的时候,在每个线程里面哦都要加载一次
- 每次加载模型时间都很长,并且检测的时候还是通过cpu,所以数据量小没什么问题,如果数据量太大,肯定会受影响
之后有了gpu的机器,所以安装了tensorflow-gpu,参考tensorflow安装(GPU版本)。如果有了gpu,当然检测的时候希望也能通过gpu检测,所以有了这篇文章,通过Flask框架提供web接口,然后远程调用接口进行预测。
Flask
Flask安装
pip install flask
Flask代码
[admin@A01-R15-I47-118-0825868 http-cnn-rnn]$ pwd
/export/src/http-cnn-rnn
[admin@A01-R15-I47-118-0825868 http-cnn-rnn]$ vim rest.py
from flask import Flask,request,jsonify
import json
from cnn_model import TCNNConfig, TextCNN
from predict import CnnModel
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 #16MB
cnn_model = CnnModel()
@app.route("/predict", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
data = request.get_data().decode('utf-8')
return predict(data)
elif request.method == 'GET':
#data = request.form.get('data')
data = request.args.get('data')
#return ">>>>"
return predict(data)
else:
return jsonify({"not support":"400"})
def predict(data):
data = json.loads(data)
ret = {}
for url in data:
predict_ret = cnn_model.predict(url)
ret[url] = predict_ret
ret = jsonify(ret)
return ret
if __name__ == '__main__':
app.run(host='0.0.0.0',port=8081, debug=False, threaded=True)
UWSGI
安装
pip install uwsgi
配置
- uWSGI是一个由python实现的web容器,可以兼容性比较好地发布Django,Flask等pythonweb框架的应用。因为本质上来说uwsgi是python的一个模块,所以可以用pip install uwsgi直接来安装它。
- 安装完成之后可以在一个合适的目录建立一个uwsgi服务器的配置文件。比如我选择在项目的根目录建立了一个uwsgiconfig.ini的文件。顺便一提,除了ini格式的配置,uwsgi还支持json,xml等多种多样的配置格式。这里以ini格式为例
[uwsgi]
socket = /export/src/http-cnn-rnn/uwsgi.sock
pythonpath = /export/src/http-cnn-rnn
module = rest
wsgi-file = /export/src/http-cnn-rnn/rest.py
callable = app
processes = 1
threads = 2
daemonize = /export/src/http-cnn-rnn/server.log
对配置的简单说明
- pythonpath指出了项目的目录,module指出了项目启动脚本的名字而紧接着的wsgi-file指出了真正的脚本的文件名。callable指出的是具体执行.run方法的那个实体的名字,一般而言都是app=Flask(name)的所以这里是app。processes和threads指出了启动uwsgi服务器之后,服务器会打开几个并行的进程,每个进程会开几条线程来等待处理请求,显然这个数字应该合理,太小会使得处理性能不好而太大则会给服务器本身带来太大负担。daemonize项的出现表示把uwsgi服务器作为后台进程启动,项的值指向一个文件表明后台中的所有输出都重定向到这个日志中去
- http-socket:使用的通讯协议,除了这个协议之外,还有http和socket,这三者的区别是,http和http-socket都是http协议,两者的区别我也没怎么分,官方文档推荐使用http-socket,socket就是uwsgi协议,官方解释是uwsgi协议通讯效率更高,这里我暂且先使用更加简单的http协议吧。另外如果用socket协议的话,nginx的配置会有所不同,后面会再说。
uWSGI启动
uwsgi --ini /export/src/http-cnn-rnn/uwsgiconfig.ini
- 执行之后会生成 /export/src/http-cnn-rnn/uwsgi.sock,这个需要在nginx.conf指定
- 以后通过nginx访问flask,flask的记录信息在daemonize的配置中,即/export/src/http-cnn-rnn/server.log
开机自启动(可以不操作,忽略)
$ vi /etc/rc.local
/usr/local/bin/uwsgi -ini /var/www/demo/demo_uwsgi.ini
Nginx安装
安装依赖包
- Nginx与Redis一样,都是C语言开发的,所以都需要在Linux上使用C语言编译后才能使用,所以得先安装用于编译的c环境
sudo yum install -y gcc-c++
sudo yum install -y pcre pcre-devel
sudo yum install -y zlib zlib-devel
sudo yum install -y openssl openssl-devel
下载 Nginx&&解压
下载地址:http://nginx.org/download/nginx-1.13.0.tar.gz
wget http://nginx.org/download/nginx-1.13.0.tar.gz
tar -zxvf nginx-1.13.0.tar.gz
cd nginx-1.13.0
编译安装
$ ./configure --prefix=/usr/local/nginx
$ make
$ sudo make install
./configure --prefix=/usr/local/nginx \
--sbin-path=/usr/local/nginx/sbin/nginx \
--conf-path=/usr/local/nginx/conf/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=nginx \
--group=nginx
我在执行的时候只是指定了 --prefix/--error-log-path/--http-log-path,主要原因是为了指定日志到一个比较大的磁盘
查看nginx版本
[admin@A01-R15-I47-121-0825870 sbin]$ pwd
/usr/local/nginx/sbin
[admin@A01-R15-I47-121-0825870 sbin]$ ./nginx -v
nginx version: nginx/1.4.2
[admin@A01-R15-I47-121-0825870 sbin]$
到此,nginx安装完成。
nginx.conf配置
server {
listen 80;
server_name localhost;
#charset koi8-r;
access_log /export/log/access.log;
error_log /export/log/error.log;
location /predict {
include uwsgi_params;
uwsgi_pass unix://export/src/http-cnn-rnn/uwsgi.sock;
}
}
####主要是location的内容
nginx启动
sudo /usr/local/nginx/nginx
sudo /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
重新载入配置文件
/usr/local/webserver/nginx/sbin/nginx -s reload
重启 Nginx
/usr/local/webserver/nginx/sbin/nginx -s reopen
停止 Nginx
/usr/local/webserver/nginx/sbin/nginx -s stop
踩坑
post数据限制
安装成功之后,因为需要测试大数据量的POST 的效率,所以发送了一个json数组,差不多50K,然后报错
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
很明显,这是因为post的数据量太大了,是flask的限制,在入口方法中添加配置如下:
from flask import Flask,request,jsonify
import json
from cnn_model import TCNNConfig, TextCNN
from predict import CnnModel
app = Flask(__name__)
###添加以下配置
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 #16MB
网友评论