Flask+UWSGI+Nginx提供在线预测服务

2019-03-12  本文已影响0人  王金松

背景

之前一直是通过tensorflow的cpu版本进行训练,工程化的时候需要把ckpt模型转换为.pb,然后继承到spark中运行。但是这样会有几个问题:

  1. 模型不能进行序列化,不能通过广播传递模型,也不能做唯一的加载,只能是对每个批次的数据进行预测的时候,在每个线程里面哦都要加载一次
  2. 每次加载模型时间都很长,并且检测的时候还是通过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]
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
对配置的简单说明
uWSGI启动
uwsgi --ini /export/src/http-cnn-rnn/uwsgiconfig.ini
  1. 执行之后会生成 /export/src/http-cnn-rnn/uwsgi.sock,这个需要在nginx.conf指定
  2. 以后通过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安装

安装依赖包
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
上一篇 下一篇

猜你喜欢

热点阅读