uWSGI Application Setup
Prerequisite
- keep alive the tensorflow serving model server
$ cd src/serving
$ bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server \
--model_name=slim_inception_resnet_v2 \
--model_base_path=$PWD/tf_servables/slim/inception-resnet-v2 \
--port=9000 &
$ bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server \
--model_name=slim_inception_v4 \
--model_base_path=$PWD/tf_servables/slim/inception-v4 \
--port=9090 &
$ ps aux | grep tensorflow_serving
$ cd ..
Create REST API Target
# note: `src` is the root dir in code snippets in default, unless specified via `cd` in context.
create python scripts and configuration file
$ [sudo] mkdir -p rest
$ [sudo] touch rest/slim_unified_client_rest.py
$ [sudo] touch rest/slim_unified_client_rest.ini
ceate a standalone copy of tensorflow_serving.apis
from slim_unified_client.runfiles
# slim_unified_client.runfiles contains protobuf specification of predict_pb2 and prediction_service_pb2
# note: i assume one can compile these protobuf directly, but i haven't tried and tested on that approach
# ...
# from tensorflow_serving.apis import predict_pb2
# from tensorflow_serving.apis import prediction_service_pb2
# ...
# add -L to create a standalone copy
# note this tensorflow_serving directory contains classification_pb2.py, predict_pb2.py, regression_pb2.py,
# prediction_service_pb2, and etc, which are same and so useful for most of service from tensorflow serving
$ cp -rL ./serving/bazel-bin/tensorflow_serving/example/slim_unified_client.runfiles/tf_serving/tensorflow_serving ./rest
$ [sudo] rm -r ./rest/tensorflow_serving/example
$ cd rest
slim_unified_client_rest.py
...
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
# python2
from urllib2 import urlopen
# python3
# from urllib.request import urlopen
import json
from multiprocessing.pool import ThreadPool
import numpy as np
import tensorflow as tf
# This is a placeholder for a Google-internal import.
from grpc.beta import implementations
from google.protobuf import json_format, text_format
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2
...
slim_unified_client_rest.ini
[uwsgi]
project = slim_unified_client_rest
# user and group
uid = www-data
gid = www-data
# project base directory
base = <git-repo-base>/src/rest
# project wsgi application
chdir = %(base)
module = slim_unified_client_rest:application
plugins = python
# python home directory
pyhome = /usr
# pythonpath = /usr/lib/python2.7
enable-threads = true
# route the static
# route = /static/(.*) static:%(base)/dist/$1
# master and worker
master = true
processes = 5
# socket
socket = /run/uwsgi/%(project).sock
chown-socket = %(uid):%(gid)
chmod-socket = 666
vaccum = true
die-on-term = true
development with --touch-reload
# in case of further development: make changes on .py file will cause uwsgi reload so to have instant effect
$ sudo uwsgi --http-socket :80 --ini slim_unified_client_rest.ini --touch-reload slim_unified_client_rest.py
$ sudo uwsgi --http-socket :8080 \
--ini slim_unified_client_rest.ini \
--touch-reload slim_unified_client_rest.py
# in case /run/uwsgi not exists
$ sudo mkdir /run/uwsgi
$ sudo chown www-data:www-data /run/uwsgi
$ sudo chmod 0666 /run/uwsgi
# inspect the uwsgi application
$ curl -X POST 127.0.0.1:80 -d '{"image_urls": ["<image_url_0>","<image_url_1>","<image_url_2>"]}'
$ curl -X POST 127.0.0.1:80 -d '{
"image_urls": [
"https://upload.wikimedia.org/wikipedia/commons/d/d9/First_Student_IC_school_bus_202076.jpg",
"https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Labrador_Retriever_portrait.jpg/1200px-Labrador_Retriever_portrait.jpg",
"https://upload.wikimedia.org/wikipedia/commons/f/fd/Qantas_a380_vh-oqa_takeoff_heathrow_arp.jpg"
]
}'
Deploy to uWSGI systemd
create a systemd daemon
for uWSGI
$ sudo touch /etc/systemd/system/uwsgi.service
/etc/systemd/system/uwsgi.service
[Unit]
Description=uWSGI Emperor service
[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown www-data:www-data /run/uwsgi'
ExecStart=/usr/bin/uwsgi --emperor /etc/uwsgi/apps-enabled
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all
[Install]
WantedBy=multi-user.target
create symbolic link in system to configuration file
$ sudo ls /etc/uwsgi
> apps-available/ apps-enabled/
# in case no apps-available and apps-enabled dir seen
# $ sudo mkdir -p /etc/uwsgi/apps-available/ /etc/uwsgi/apps-enabled/
# $ sudo ln -s $PWD/slim_unified_client_rest.ini /etc/uwsgi/apps-available/slim_unified_client_rest.ini
$ sudo ln -s $PWD/slim_unified_client_rest.ini /etc/uwsgi/apps-enabled/slim_unified_client_rest.ini
start uwsgi.service
via systemd
$ sudo systemctl daemon-reload
$ sudo systemctl start uwsgi.service
$ sudo systemctl status uwsgi.service
$ sudo systemctl restart uwsgi.service