上次我們介紹了如何 使用TensorFlow Serving進(jìn)行模型的部署斑响,但是TensorFlow Serving上的模型接受的輸入是計(jì)算圖的placeholder, 輸出的是指定的要獲取的變量菱属,因此我們需要一個中間web服務(wù)先進(jìn)行數(shù)據(jù)預(yù)處理,將轉(zhuǎn)化好的數(shù)據(jù)發(fā)送給serving舰罚,最后對從serving接收到的結(jié)果進(jìn)行后處理纽门。這篇文章就介紹一個簡單的Nginx+uwsgi+Flask的部署方案。
一营罢、概念
Flask: 輕量級web frame赏陵,用于路由和業(yè)務(wù)邏輯處理,有自帶的簡單webserver饲漾,但是是單進(jìn)程蝙搔,只適用于開發(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)注底層細(xì)節(jié)矩欠。一般提到uwsgi,也會指代uWSGI服務(wù)器悠夯。
uWSGI:是一個C實(shí)現(xiàn)的web服務(wù)器癌淮,支持WSGI協(xié)議、uwsgi協(xié)議沦补、http協(xié)議等乳蓄,是Nginx和Flask之間的連接件。多進(jìn)程夕膀,失敗可自動重啟虚倒,可做負(fù)載均衡。
Gunicorn:Green Unicorn产舞,移植自Ruby的Unicorn項(xiàng)目魂奥,也是一個python的WSGI服務(wù)器。
Nginx: Nginx收到請求后會轉(zhuǎn)發(fā)給uWSGI或Gunicorn服務(wù)器處理易猫。其實(shí)沒有Nginx也可以支撐服務(wù)耻煤,但一般加一層Nginx有一些優(yōu)點(diǎn),例如可以多個web服務(wù)都監(jiān)聽80端口擦囊,暴露在外網(wǎng)中更安全违霞,對靜態(tài)資源的處理更好,負(fù)載均衡做得更好等瞬场。
二买鸽、安裝配置
Flask
安裝Flask
pip install flask
編寫Flask程序flask_web.py,在處理業(yè)務(wù)邏輯的類YourModel中進(jìn)行數(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進(jìn)行通信,如果Nginx和uwsgi部署在同一臺機(jī)器上,直接使用127.0.0.1
#如果外部直接通過uwsgi訪問服務(wù)鸯两,需將socket改為http-socket或者h(yuǎn)ttp,將127.0.0.1改為0.0.0.0
chdir = /path/to/yourproject
#項(xiàng)目目錄
virtualenv =/path/to/venv
#虛擬環(huán)境所在路徑
wsgi-file = flask_web.py
#編寫flask代碼的py文件
callable = application
#Flask應(yīng)用對象
plugin = python
master = true
#啟動主進(jìn)程曲掰,來管理其他進(jìn)程
vacuum = true
#設(shè)置退出后清理文件
chmod-socket = 664
stats = 0.0.0.0:9191
listen = 4096
#監(jiān)聽隊(duì)列大小,默認(rèn)100,太小了一壓測隊(duì)列就滿了,調(diào)大一點(diǎn)
processes = 5
#uwsgi啟動的進(jìn)程數(shù)溜腐,可設(shè)為機(jī)器核數(shù)+1
thunder-lock = true
#防止驚群
harakiri = 60
#超時時間(秒)
daemonize = /path/to/uwsgi.log
#進(jìn)程會在后臺運(yùn)行,并輸出日志
pidfile = /path/to/uwsgi.pid
通過uwsgi啟動flask應(yīng)用時瓜喇,運(yùn)行
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