Flask request.form.становится слишком медленным?

Я использую Flask для своего сервиса Web Api.

Обнаружив, что мои службы иногда (1/100 запросов) отвечают очень медленно (секунды), я начал отладку, которая показала мне, что иногда служба зависает при чтении поля запроса.

@app.route('/scan', methods=['POST'])
def scan():
    start_time = time.time()
    request_description = request.form.get('requestDescription')
    end_time = time.time()
    app.logger.debug('delay is ' + end_time-start_time)

Здесь я обнаружил, что задержка между start_time и end_time может составлять до 2 минут.

Я читал об использовании Werkzeug Flask в качестве рабочего сервера, поэтому в качестве альтернативы я попробовал GUnicorn - то же самое.

Я чувствую, что моя проблема чем-то похожа на эту, с той разницей, что другой сервер не решил проблему.

Я попытался профилировать приложение с помощью cProfile и SnakeViz, но с нерабочим сервером Werkzeug, так как я не понимаю, как профилировать приложения Python, работающие на GUnicorn. (может кто знает как?)

Мои запросы POST содержат описание и файл. Файл может иметь разный размер, но журналы показывают, что проблема воспроизводится независимо от размера файла.

Люди также обычно говорят, что Flask следует использовать в сочетании Nginx-[обычный сервер]-flask, но, поскольку я использую сервис внутри Openshift, я сомневаюсь, что это имеет какое-то значение. (HaProxy работает как балансировщик)

Итак, мои настройки: Alpine 3.8.1 GUnicorn: рабочие: 3 потока: 1

Что происходит под капотом, когда я вызываю это?

request.form.get('requestDescription')

Как я могу профилировать код Python в GUnicorn? Кто-нибудь еще сталкивался с такой проблемой?

Любая помощь будет оценена


person Dmitry Zuev    schedule 23.11.2018    source источник


Ответы (1)


Я тоже столкнулся с этой проблемой. Я загружал видеофайл, используя request.post(). Оказывается, проблема была не в загрузке видео.

Узким местом по времени был request.form.get(). Пока я все еще пытаюсь выяснить проблему, вы можете использовать Панель мониторинга Flask, чтобы вовремя профилировать код

Оказывается, что под капотом return self._sock.recv_into(b), если вы используете профайлер

person Kyle Nathan    schedule 28.06.2021