Медленные запросы на локальном сервере Flask

87

Просто начинаю играть с Flask на локальном сервере, и я замечаю, что время запроса / ответа намного медленнее, чем, как мне кажется, должно быть.

Простой сервер, подобный следующему, отвечает примерно за 5 секунд.

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "index"

if __name__ == "__main__":
    app.run()

Любые идеи? Или это просто локальный сервер?

Meroon
источник
Это не локальный сервер, но это может быть связано с другими приложениями, работающими в фоновом режиме, на какой ОС вы его используете?
gabeio
Я работаю на OS X 10.7 на i7 iMac
Meroon
1
На ваши ответы не должно уйти так много времени, но я на самом деле возился с flask, прежде чем безуспешно, я бы посоветовал Bottlepy . Хотя все еще проверяйте фоновые процессы, у вас может быть более старая версия вашего сервера, работающая в фоновом режиме, которая захватывает ваш питон и вызывает ваши медленные ответы. Также это может быть ваш браузер, это происходит в Chrome и Safari?
gabeio
2
@ Ответ Меруна был правильным для меня. Однако вместо изменения настроек хоста: Могу ли я порекомендовать просто использовать 127.0.0.1 вместо localhost? Это решило проблему без изменения конфигурации системы.
Дэвид Бернат

Ответы:

93

Хорошо, я разобрался. Похоже, это проблема с Werkzeug и ОС, поддерживающими ipv6.

С сайта Werkzeug http://werkzeug.pocoo.org/docs/serving/ :

В операционных системах, поддерживающих ipv6 и настроенных, таких как современные системы Linux, OS X 10.4 или выше, а также Windows Vista, некоторые браузеры могут быть очень медленными при доступе к вашему локальному серверу. Причина этого в том, что иногда «localhost» настроен на доступность как для сокетов ipv4, так и для ipv6, и некоторые браузеры сначала будут пытаться получить доступ к ipv6, а затем ivp4.

Итак, исправление - отключить ipv6 с локального хоста, закомментировав следующую строку из моего файла hosts:

::1             localhost 

Как только я это сделаю, проблемы с задержкой исчезнут.

Я очень копаю Flask и рад, что это не проблема с фреймворком. Я знал, что этого не может быть.

Meroon
источник
2
Я нашел их полезными: Windows techunboxed.com/2012/08/how-to-disable-ipv6-in-windows-8.html Ubuntu noobslab.com/2012/05/disable-ipv6-if-your-internet-is. html
Ларри Эйтель
большое спасибо! внезапно тестирование разработчиков стало быстрым и отзывчивым! мой единственный вопрос: поскольку файл хостов Mac указывает, что удаление localhost может повлиять на работу моего Mac, мне интересно, относится ли он к этой строке (или к той, которая просто размещает localhost в 127.0.0.1
Дэвид Б.
в моей системе Windows 10 в файле hosts закомментированы обе записи (ip4 и ip6); они разрешаются системой DNS. Я получил огромное увеличение скорости, когда я запустил сервер на «127.0.0.1» вместо «localhost» (с 2,0 до 0,003 секунды для простых вызовов)
Ларс
Спасибо за такой ответ! Хотя моя ситуация была немного другой (насморк2 против aiosmtpd), ваш ответ подсказал мне: когда я отключаю IPv6 на своем ноутбуке с Windows 10, это ускоряет работу, например, в 10 или 100 раз !!
pepoluan
87

Добавьте «threadaded = True» в качестве аргумента в app.run (), как предлагается здесь: http://arusahni.net/blog/2013/10/flask-multithreading.html

Например: app.run(host="0.0.0.0", port=8080, threaded=True)

Решение с отключением ipv6 у меня не сработало, но это сработало.

Саджид Сиддики
источник
5
Переход --threadedна мое manage.pyиспользование Flask-Scriptтоже сработал.
Snorfalorpagus
7
Предупреждаем тех, у кого это "исправлено" включением потоков! В этом случае задержка была вызвана неправильным закрытием предыдущего запроса, поэтому теперь фактически просто складывается много потоков .
kbtz
Спасибо, сэр, что заставил мой локальный хост работать невероятно быстро.
Benjaminz
@snolflake: Есть ли способ узнать, правильно ли закрываются запросы?
Килотан
1
Я использовал командную строку, flask run --with-threadsкоторая решила мою проблему.
arno_v
13

Решение от @ sajid-siddiqi технически правильное, но имейте в виду, что встроенный сервер WSGI в Werkzeug (который упакован во Flask и для чего он используется app.run()) является только однопоточным.

Установите сервер WSGI, чтобы иметь возможность обрабатывать многопоточное поведение. Я провел кучу исследований производительности различных серверов WSGI . Ваши потребности могут различаться, но если вы используете только Flask , я бы порекомендовал один из следующих веб-серверов.

Обновление (2020-07-25): похоже, gevent начал поддерживать python3 5 лет назад, вскоре после того, как я прокомментировал, что это не так, поэтому вы можете использовать gevent сейчас.

Gevent

Вы можете установить gevent через pip с помощью команды pip install geventили pip3 с помощью команды pip3 install gevent. Инструкции о том, как соответствующим образом изменить ваш код, находятся здесь: https://flask.palletsprojects.com/en/1.1.x/deploying/wsgi-standalone/#gevent

Meinheld

gevent лучше, но из всех тестов, которые я просмотрел, которые включают тестирование в реальном мире, meinheld кажется самым простым и упрощенным сервером WSGI . (Вы также можете взглянуть на uWSGI, если не возражаете против дополнительных настроек.)

Вы также можете установить meinheld через pip3 с помощью команды pip3 install meinheld. Оттуда посмотрите на образец, предоставленный в источнике meinheld для интеграции Flask : https://github.com/mopemope/meinheld/blob/master/example/flask_sample.py

* ПРИМЕЧАНИЕ. Из-за того, что я использовал PyCharm , строка from meinheld import serverвыделяется как ошибка, но сервер будет работать, поэтому вы можете игнорировать ошибку.

Микехо
источник
У меня были серьезные проблемы с производительностью с Flask, выполнение даже самых простых запросов занимало около 0,5 секунды. Просто перешел на gevent и все работает безупречно, спасибо!
gronostaj 07
7

Вместо звонка http://localhost:port/endpointзвоните http://127.0.0.1:port/endpoint. Это устранило для меня начальную задержку в 500 мс.

LangeTreeDorpie
источник
для меня он удалил что-то вроде 3 секунд (я переместил форму с 0.0.0.0 на 127.0.0.1). Может кто-нибудь объяснить, почему и как это работает?
Роткив
Почему, во имя богов, это работает? Пошло с 2,06 секунды до 0,002 секунды. Браузер может использовать localhost без проблем, но для разрешения request.get на localhost требуется 2 секунды.
Xevion
7

Моя проблема была решена с помощью «threadaded = True», но я хочу дать некоторую предысторию, чтобы отличить мою проблему от других, для которых это может не сработать.

  1. Моя проблема возникла только при запуске Flask с python3. При переходе на python2 у меня больше не было этой проблемы.
  2. Моя проблема проявлялась только при доступе к api с помощью Chrome, и в этот момент Chrome отображал ожидаемый экран, но все остальное зависало (curl, ffx и т.д.), пока я не перезагрузил или не закрыл вкладку Chrome, после чего все остальное, что ожидало вокруг вернул результат.

Я предполагаю, что Chrome пытался сохранить сеанс открытым, а Flask блокировал последующие запросы. Как только соединение из Chrome было остановлено или сброшено, все остальное обработалось.

В моем случае это исправила многопоточность. Конечно, сейчас я просматриваю некоторые ссылки, которые предоставили другие, чтобы убедиться, что это не вызовет никаких других проблем.

ChePazzo
источник
4

threaded=Trueработает для меня, но, наконец, я понял, что проблема связана с foxyproxy в firefox. Поскольку, когда приложение flask работает на локальном хосте, медленный ответ происходит, если

  • foxyproxy включен в firefox

медленный ответ не произойдет, если

  • foxyproxy отключен в Firefox

  • заходить на сайт через другие браузеры

Единственное решение, которое я нашел, - это отключить foxyproxy, попытаться добавить localhost в черный список прокси и настроить параметры, но ни один из них не работал.

Эдвард
источник
2

Я использовал ответ Михеко, чтобы решить свою проблему.

::1 localhost был уже закомментирован в моем файле hosts, и настройка Threaded=true у меня не сработала. Каждый запрос REST обрабатывался не мгновенно, а занимал 1 секунду.

Я использую python 3.6, и у меня есть flask, чтобы быстро реагировать на запросы REST, заставив flask использовать gevent в качестве своего WSGI.

Чтобы использовать gevent, установите его с помощью pip install gevent

Впоследствии я использовал https://gist.github.com/viksit/b6733fe1afdf5bb84a40#file-async_flask-py-L41 чтобы настроить колбу на использование gevent.

Если ссылка не работает, вот важные части скрипта:

from flask import Flask, Response
from gevent.pywsgi import WSGIServer
from gevent import monkey

# need to patch sockets to make requests async
# you may also need to call this before importing other packages that setup ssl
monkey.patch_all()

app = Flask(__name__) 


# define some REST endpoints... 

def main():

    # use gevent WSGI server instead of the Flask
    # instead of 5000, you can define whatever port you want.
    http = WSGIServer(('', 5000), app.wsgi_app) 

    # Serve your application
    http.serve_forever()


if __name__ == '__main__':
    main()
Али Мизан
источник
threadaded = True не работает (с использованием python 3.6.7 и почтальона), я получаю VersionConflict: (greenlet 0.4.13 (c: \ anaconda3 \ lib \ site-packages), Requirement.parse ('greenlet> = 0.4. 14; platform_python_implementation == "CPython" ')), могу ли я узнать, как решить эту проблему, спасибо
hanzgs
0

Я получил эту ошибку при работе на других хостах, кроме localhost , поэтому для некоторых различные проблемы могут проявлять одни и те же симптомы.

Я переключил большинство вещей, которые я использовал, на Tornado, и, как ни странно, это помогло. У меня было несколько медленных загрузок страниц, но в целом все кажется более отзывчивым. Кроме того, очень анекдотично, но я, кажется, заметил, что только Flask со временем замедляется, а Flask + Tornado - меньше. Я представляю себе использование Apache и mod_wsgiсделаю это еще лучше, но Tornado действительно прост в настройке (см. Http://flask.pocoo.org/docs/deploying/others/ ).

(Также связанный с этим вопрос: приложение Flask иногда зависает )

Gatoatigrado
источник
0

У меня здесь было другое решение. Я просто удалил все .pycиз каталога сервера и снова запустил. Кстати, localhost уже был закомментирован в моем файле hosts (Windows 8).

Сервер все время зависал и теперь снова работает нормально.

Erickrf
источник