Возврат ответа «все еще загружается» с Flask API - PullRequest
0 голосов
/ 29 января 2019

У меня есть классификатор scikit-learn , работающий как Dockerised Приложение Flask , запущенное с gunicorn .Он получает входные данные в формате JSON в виде запроса POST и отвечает объектом результатов JSON.

Когда приложение впервые запускается с gunicorn, большая модель ( сериализуется с joblib )считывается из базы данных и загружается в память до того, как приложение будет готово к запросам.Это может занять 10-15 минут.

Воспроизводимый пример неосуществим, но базовая структура показана ниже:

from flask import Flask, jsonify, request, Response
import joblib
import json

def classifier_app(model_name):
    # Line below takes 10-15 mins to complete
    classifier = _load_model(model_name)
    app = Flask(__name__)

    @app.route('/classify_invoice', methods=['POST'])
    def apicall():
        query = request.get_json()
        results = _build_results(query['data'])
        return Response(response=results,
                        status=200,
                        mimetype='application/json')

    print('App loaded!')
    return app

Как настроить Flask или gunicorn для возврата 'все еще загружает ответ (или соответствующее сообщение об ошибке) на любые входящие http-запросы, пока _load_model еще работает?

1 Ответ

0 голосов
/ 29 января 2019

Как правило, вы хотите вернуть два ответа на один запрос.Таким образом, есть две разные возможности.

Первый - запускать в фоновом режиме трудоемкую задачу и пинговать сервер с простыми ajax-запросами каждые две секунды, чтобы проверить, завершена ли задача или нет.Если задача выполнена, вернуть результат, если нет, вернуть "Please standby" строку или что-то в этом роде.

Второй - использовать веб-сокеты и расширение flask-socketio.

Базовый код сервера будет выглядеть примерно такэто:

from threading import Thread
from flask import Flask

app = Flask(__name__)
socketio = SocketIO(app)

def do_work():
    result = your_heavy_function()
    socketio.emit("result", {"result": result}, namespace="/test/")

@app.route("/api/", methods=["POST"])
def start():
    socketio.start_background_task(target=do_work)
    # return intermediate response
    return Response()

На стороне клиента вы должны сделать что-то вроде этого

var socket = io.connect('http://' + document.domain + ':' + location.port + '/test/');
socket.on('result', function(msg) {
    // Process your request here
});

Для получения дополнительной информации посетите этот пост в блоге , flask-документация socketio для справки на стороне сервера и документация socketio для справки на стороне клиента.

PS Используя веб-сокеты, вы также можете сделать прогресс-бар.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...