У меня проблема, которую я не могу понять. У меня есть служба API, созданная с использованием FastAPI, и когда я пытаюсь вызвать любую конечную точку из другого скрипта Python на моем локальном компьютере, ответ занимает 2+ секунды. Когда я отправляю тот же запрос через cURL или встроенную документацию Swagger, ответ почти мгновенный.

Весь сценарий сервера таков:

from fastapi import FastAPI
import uvicorn

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

if __name__ == '__main__':
    uvicorn.run(app, host='0.0.0.0', port=8000)

Затем я вызываю его из тестового сценария с использованием HTTPX. Я также пробовал с пакетом запросов, и результат тот же.

import httpx
r = httpx.get('http://localhost:8000/')
print(r.elapsed)

Это напечатает что-то вроде: 0:00:02.069705

Затем я делаю то же самое, используя cURL:

curl -w "@curl-format.txt" -o /dev/null -X 'GET' 'http://localhost:8000/'

Это печатает:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    32  100    32    0     0    941      0 --:--:-- --:--:-- --:--:--   969
     time_namelookup:  0.006436s
        time_connect:  0.006747s
     time_appconnect:  0.000000s
    time_pretransfer:  0.006788s
       time_redirect:  0.000000s
  time_starttransfer:  0.034037s
                     ----------
          time_total:  0.034093s

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

Я попытался проверить запрос, чтобы увидеть, есть ли в нем заголовки или что-то подобное, которые могли бы его замедлить, но ничего. Когда я снова пытаюсь использовать заголовки, сгенерированные HTTPX, он по-прежнему выполняется быстро:

curl -w "@curl-format.txt" -o /dev/null -X 'GET' \
  'http://localhost:8000/events' \
  -H 'accept: */*' \
  -H 'host: localhost:8000' \
  -H 'accept-encoding: gzip, deflate' \
  -H 'connection: keep-alive' \
  -H 'user-agent: python-httpx/0.20.0'

Вот скриншот запроса в PyCharm, его, к сожалению, нельзя напрямую выгрузить в JSON. введите описание изображения здесь

Я начинаю думать, что это как-то связано с Uvicorn и тем, как оно запускает приложение, но я не могу понять, почему.

3
Johannes Mols 28 Ноя 2021 в 00:24
1
У меня нет решения предложить, но я пытался использовать 127.0.0.1 вместо localhost? Однажды у меня были похожие проблемы, когда моей машине с Windows требовалось полсекунды или больше, чтобы разрешить имя хоста, прежде чем он сделает фактический запрос.
 – 
thisisalsomypassword
28 Ноя 2021 в 00:49
Ну, сам питон может быть узким местом. Не могли бы вы попробовать отладить запрос на сайте клиента? Может быть проблема с HTTP / 1 против HTTP / 2
 – 
Michał Darowny
28 Ноя 2021 в 00:53
О боже, ты прав. Переход на 127.0.0.1 буквально решает эту проблему. Я не могу вас отблагодарить, я уже потратил на это несколько часов. Однако на самом деле этого не должно происходить.
 – 
Johannes Mols
28 Ноя 2021 в 00:55
Я боялся предложить это, но это слишком напомнило мне мою проблему. Однако я делал запрос из javascript в браузере. Тогда он не стал вдаваться в подробности, так что извините, у меня нет решения. Но, возможно, это сузит круг поиска.
 – 
thisisalsomypassword
28 Ноя 2021 в 00:59
1
Что ж, рад, что помог.
 – 
thisisalsomypassword
28 Ноя 2021 в 01:03

1 ответ

Лучший ответ

Попробуйте использовать «127.0.0.1» вместо «localhost» для обозначения вашего компьютера. Однажды у меня была аналогичная проблема, когда поиск DNS для localhost в Windows занимал полсекунды или дольше. У меня нет объяснения такому поведению, но, по крайней мере, еще один человек в SO, похоже, боролся с этим, поскольку хорошо…

1
thisisalsomypassword 28 Ноя 2021 в 01:15