上次我們介紹了如何 使用TensorFlow Serving進行模型的部署,但是TensorFlow Serving上的模型接受的輸入是計算圖的placeholder, 輸出的是指定的要獲取的變量,因此我們需要一個中間web服務(wù)先進行數(shù)據(jù)預(yù)處理,將轉(zhuǎn)化好的數(shù)據(jù)發(fā)送給serving,最后對從serving接收到的結(jié)果進行后處理。這篇文章就介紹一個簡單的Nginx+uwsgi+Flask的部署方案。
一、概念
Flask: 輕量級web frame,用于路由和業(yè)務(wù)邏輯處理,有自帶的簡單webserver,但是是單進程,只適用于開發(fā)模式,無法支撐生產(chǎn)環(huán)境。類似的web框架還有django,tornado,webpy,bottle等。
WSGI:Web Server Gateway Interface(網(wǎng)絡(luò)服務(wù)器網(wǎng)關(guān)接口)的縮寫,是一種描述web server如何與web application通信的規(guī)范。
uwsgi: 是一種uWSGI自有的協(xié)議,用于定義傳輸信息的類型,能夠?qū)eb請求的參數(shù)/屬性,轉(zhuǎn)換成python中相應(yīng)的數(shù)據(jù)結(jié)構(gòu),以便于上層的Python代碼不用關(guān)注底層細節(jié)。一般提到uwsgi,也會指代uWSGI服務(wù)器。
uWSGI:是一個C實現(xiàn)的web服務(wù)器,支持WSGI協(xié)議、uwsgi協(xié)議、http協(xié)議等,是Nginx和Flask之間的連接件。多進程,失敗可自動重啟,可做負載均衡。
Gunicorn:Green Unicorn,移植自Ruby的Unicorn項目,也是一個python的WSGI服務(wù)器。
Nginx: Nginx收到請求后會轉(zhuǎn)發(fā)給uWSGI或Gunicorn服務(wù)器處理。其實沒有Nginx也可以支撐服務(wù),但一般加一層Nginx有一些優(yōu)點,例如可以多個web服務(wù)都監(jiān)聽80端口,暴露在外網(wǎng)中更安全,對靜態(tài)資源的處理更好,負載均衡做得更好等。
二、安裝配置
Flask
安裝Flask
pip install flask
編寫Flask程序flask_web.py,在處理業(yè)務(wù)邏輯的類YourModel中進行數(shù)據(jù)預(yù)處理、從TensorFlow Serving獲取結(jié)果、結(jié)果后處理等操作。
from concurrent import futures
from flask import Flask, request
from flask import jsonify
from filename import YourModel
#filename.py中的YourModel類中封裝了對數(shù)據(jù)、模型和結(jié)果的所有操作
application = Flask(__name__)
model = YourModel()
@application.route('/recognize', methods=['POST'])
def reply():
req_msg = request.form['msg']
entities = model.recognize(req_msg)
return jsonify({'entity': entities})
if __name__ == '__main__':
# 本地測試時可用127.0.0.1,要對外開放時改為0.0.0.0
application.run(host='0.0.0.0', port=5000)
2.安裝配置uwsgi
pip install uwsgi
如果使用了virtualenv,則在激活虛擬環(huán)境后安裝uwsgi,并且需要再uwsgi的配置文件中指明虛擬環(huán)境路徑。下面是一個基礎(chǔ)的uwsgi配置文件,命名為uwsgi.ini:
[uwsgi]
socket = 127.0.0.1:8081
#由于外部還要嵌套Nginx,這里可以使用socket進行通信,如果Nginx和uwsgi部署在同一臺機器上,直接使用127.0.0.1
#如果外部直接通過uwsgi訪問服務(wù),需將socket改為http-socket或者http,將127.0.0.1改為0.0.0.0
chdir = /path/to/yourproject
#項目目錄
virtualenv =/path/to/venv
#虛擬環(huán)境所在路徑
wsgi-file = flask_web.py
#編寫flask代碼的py文件
callable = application
#Flask應(yīng)用對象
plugin = python
master = true
#啟動主進程,來管理其他進程
vacuum = true
#設(shè)置退出后清理文件
chmod-socket = 664
stats = 0.0.0.0:9191
listen = 4096
#監(jiān)聽隊列大小,默認100,太小了一壓測隊列就滿了,調(diào)大一點
processes = 5
#uwsgi啟動的進程數(shù),可設(shè)為機器核數(shù)+1
thunder-lock = true
#防止驚群
harakiri = 60
#超時時間(秒)
daemonize = /path/to/uwsgi.log
#進程會在后臺運行,并輸出日志
pidfile = /path/to/uwsgi.pid
通過uwsgi啟動flask應(yīng)用時,運行
uwsgi --ini uwsgi.ini
3.安裝配置Nginx
在mac上安裝nginx可使用homebrew
brew install nginx
配置nginx,配置文件為/usr/local/etc/nginx/nginx.conf
server {
listen XXXX default_server;#指定監(jiān)聽的端口
charset utf-8;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name XX.XXX.XXX.XXX; # ip地址
location /recognize {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8081;
uwsgi_param UWSGI_PYHOME /path/to/venv;
uwsgi_param UWSGI_CHDIR /path/to/project;
uwsgi_param UWSGI_SCRIPT flask_web:application;
uwsgi_read_timeout 300;
uwsgi_connect_timeout 300;
uwsgi_send_timeout 300;
}
}
#配置uwsgi時,UWSGI_CHDIR和UWSGI_SCRIPT這兩條命令順序敏感,如果腳本在目錄上一行也會導(dǎo)致服務(wù)無法啟動。
將nginx命令加入環(huán)境變量
# ~/.bash_profile文件中添加一行
export PATH=${PATH}:/usr/local/Cellar/nginx/1.12.1/bin/
啟動服務(wù)
nginx
或
nginx -s reload