Возврат ответа «все еще загружается» с помощью Flask API

У меня есть классификатор scikit-learn, работающий как Dockerized Flask app, запущенный с помощью 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 все еще работает?

Вы хотите создать индикатор выполнения или что-то в этом роде?   —  person ajrwhite    schedule 29.01.2019

Вы можете использовать Celery для асинхронной обработки задачи joblib. Вам также необходимо установить брокера, такого как RabbitMQ или Redis, который будет служить очередью задач.   —  person ajrwhite    schedule 29.01.2019

@Montreal нет индикатора выполнения — просто HTTP-ответ на запрос POST.   —  person ajrwhite    schedule 29.01.2019

@prithajnath, это звучит интересно, но не могли бы вы объяснить, как это решает проблему? Приложение создается во время выполнения задачи joblib, а затем, если запрос поступает до того, как модель существует, мы можем вернуть ошибку?   —  person ajrwhite    schedule 29.01.2019

См. также:  Необходимость разделения файлов YAML для конвейеров
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. ajrwhite

    По сути, вы хотите вернуть два ответа на один запрос. Итак, есть две разные возможности.

    Первый — запускать трудоемкую задачу в фоновом режиме и пинговать сервер с простыми запросами 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('https://' + document.domain + ':' + location.port + '/test/');
    socket.on('result', function(msg) {
        // Process your request here
    });
    

    Для получения дополнительных сведений посетите это сообщение в блоге, < href = «https://flask-socketio.readthedocs.io/en/latest/» rel = «nofollow noreferrer»> документацию по flask-socketio для справки на стороне сервера и документация по socketio для справки на стороне клиента.

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

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: