От чего зависит разрыв соединения при HTTP запросах
Что проверяют
Понимаете ли вы, что соединение рвут несколько независимых участников, и умеете ли по симптому определить, кто именно. Для питониста вопрос сразу практический: почти все случаи всплывают в requests, httpx и aiohttp в виде конкретных исключений.
Как отвечать
Разложите причины по уровням:
- таймауты клиента: отдельно на установку соединения и на чтение ответа. У
requestsпараметраtimeoutпо умолчанию нет вовсе, и вызов может висеть бесконечно; - простой соединения: у сервера свой таймаут keep-alive, у балансировщика и прокси свой, у NAT таблица трансляций. Случай самый неприятный: пакета с разрывом не приходит совсем, и клиент узнаёт о нём только по таймауту чтения;
- устаревший сокет из пула: сессия переиспользует соединение, которое сервер уже закрыл. Симптом узнаваемый,
RemoteDisconnectedили сброс на первом же запросе после паузы; - сервер: перезапуск и выкладка, заголовок
Connection: close, лимит числа запросов на воркера, ограничение на размер тела,GOAWAYв HTTP/2.
Практическая часть ответа: всегда задавать timeout явно, ходить через сессию с настроенным Retry и паузой между попытками, различать ConnectTimeout и ReadTimeout.
s = requests.Session()
s.mount("https://", HTTPAdapter(max_retries=Retry(total=3, backoff_factor=0.5)))
r = s.get(url, timeout=(3.05, 10))Где спотыкаются
Не ставят таймаут. Один подвисший вызов выедает воркер, за ним второй, и сервис перестаёт отвечать целиком, хотя падения нигде не видно.
Повторяют после таймаута чтения любой запрос подряд. Ответ мог не дойти, но обработаться: повтор POST без ключа идемпотентности создаёт дубль платежа или заказа.
Валят всё на сеть, не посмотрев на симптом. Мгновенный сброс, обрыв ровно через минуту простоя и обрыв на середине большого тела означают разных виновников, и лечатся они по-разному.