Сравните тайм-аут установления соединения и тайм-аут ожидания ответа внешнего сервиса: какой сбой выявляет каждый из них?
Тайм-аут установления соединения ограничивает время, за которое вызывающая сторона должна установить сетевое соединение с внешним сервисом. Тайм-аут ожидания ответа ограничивает время после установления соединения, в течение которого система ждёт данные от сервиса. Первый выявляет проблемы доступности сети или точки назначения, второй — слишком медленную обработку, зависание или перегрузку внешнего сервиса.
Разделение тайм-аутов появилось из-за того, что сетевой вызов состоит из нескольких последовательных этапов. Установка соединения и ожидание результата имеют разные причины задержек и требуют разных реакций.
Без отдельных ограничений приложение могло бесконечно ждать недоступный узел или зависшую обработку. Это приводило к накоплению занятых потоков, соединений и запросов, а затем — к отказу уже самого вызывающего сервиса.
Внешний сервис может быть недоступен из-за ошибки маршрутизации, отказа узла, сетевого фильтра или исчерпания ресурсов. В другом случае соединение устанавливается успешно, но зависимость долго выполняет запрос и не присылает ответ.
Если использовать один неограниченный или неправильно выбранный тайм-аут, система не сможет различать эти ситуации. Слишком большой лимит увеличивает время отказа для пользователя, а слишком маленький создаёт ложные ошибки при нормальных, но долгих операциях.
Тайм-аут не отменяет автоматически уже выполняемую операцию во внешней системе. Вызывающая сторона может перестать ждать, тогда как внешний сервис продолжит обработку; поэтому повторная отправка может создать дубликат, если операция не защищена идемпотентностью.
При установлении соединения система сначала ограничивает время поиска маршрута, подключения к узлу и, в зависимости от протокола и клиента, выполнения связанных сетевых этапов. Истечение этого лимита означает, что до нормального обмена данными дело не дошло.
После установления соединения применяется тайм-аут ожидания ответа. Его нужно понимать точно: в разных библиотеках он может означать ожидание первого байта, ожидание очередного фрагмента данных или общий лимит чтения. Поэтому в техническом контракте следует явно указать семантику используемого клиента.
Обычно задают как минимум:
Общий дедлайн должен ограничивать весь пользовательский сценарий, а не каждый повтор отдельно. Иначе несколько попыток с собственным большим тайм-аутом могут превысить приемлемое время ответа.
При истечении тайм-аута систему нельзя безусловно считать операцию неисполненной. Если запрос успел попасть во внешний сервис, результат мог быть успешно сформирован, но не доставлен клиенту. Для безопасных повторов применяют идемпотентный ключ, проверку статуса операции или иной механизм сверки результата.
Значения тайм-аутов выбирают по требованиям к задержке, наблюдаемым метрикам внешнего сервиса и допустимой цене ожидания. Тайм-ауты должны сопровождаться метриками по типу сбоя, зависимостям и процентилям задержки; одно среднее значение не показывает редкие долгие запросы.
Ограничение времени ожидания снижает риск исчерпания ресурсов, но не заменяет circuit breaker, ограничение параллелизма и контроль нагрузки. Эти механизмы решают связанные, но разные задачи: тайм-аут прекращает ожидание конкретного вызова, а остальные предотвращают массовое повторение или накопление таких вызовов.
Платёжный сервис вызывает внешний сервис проверки адреса. В тестовой среде команда установила один тайм-аут в 30 секунд. При сетевой ошибке каждый запрос ждал 30 секунд, а при перегрузке проверки адреса десятки рабочих потоков также оставались занятыми; очередь запросов быстро росла.
Рассматривались два варианта. Уменьшить единый тайм-аут было просто, но это смешивало сетевую недоступность с медленной обработкой и создавало риск преждевременных ошибок. Оставить 30 секунд сохраняло шанс дождаться редкого медленного ответа, но делало отказ слишком долгим и не защищало сервис от накопления ожиданий.
Выбрали раздельные лимиты: короткий тайм-аут установления соединения, более длительный тайм-аут ответа и общий дедлайн операции. После истечения дедлайна запрос переводился в явно определённое состояние, а повтор разрешался только для операций, защищённых идемпотентным ключом.
В результате команда смогла отдельно видеть сетевые сбои и медленную зависимость, ограничила время отказа и избежала автоматических повторов, которые могли бы повторно запустить уже принятую платёжную операцию.
Нет. Тайм-аут сообщает только, что вызывающая сторона не получила ожидаемый результат в установленный срок. Внешний сервис мог принять запрос, завершить его и отправить ответ, который не дошёл или не был вовремя прочитан.
Поэтому повтор безопасен только при наличии идемпотентности либо способа узнать состояние первоначальной операции. Для финансовых и иных побочных операций это принципиально: ошибка ожидания не равна подтверждённому отказу.
При наличии повторов каждый вызов может уложиться в свой лимит, но суммарное время превысит допустимое время пользовательского запроса. Общий дедлайн передаётся через цепочку вызовов и не позволяет отдельной зависимости израсходовать весь бюджет задержки.
Перед новой попыткой нужно проверить оставшееся время. Если его недостаточно для минимально разумного вызова, повтор следует прекратить и вернуть контролируемый результат.
Нет. Тайм-аут освобождает ресурс после истечения ожидания, но до этого множество запросов может одновременно обращаться к зависимому сервису. Кроме того, без ограничения повторов отказ может вызвать шторм запросов.
Для защиты обычно дополняют тайм-ауты ограничением параллелизма, контролируемыми повторами с задержкой и случайным разбросом, а также circuit breaker. Конкретный набор зависит от критичности операции, возможности повторения и требований к согласованности.