Как диагностировать проблему, когда HTTP-запрос не получает ответа (висит или таймаут)?

«Как диагностировать проблему, когда HTTP-запрос не получает ответа (висит или таймаут)?» — вопрос из категории API тестирование, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Проблема может быть на стороне клиента, сети или сервера. Необходима последовательная диагностика.

Схема диагностики:

  1. Проверка клиента и запроса:

    • Увеличьте таймаут (если это допустимо в контексте теста).
    • Убедитесь, что запрос корректно сформирован (URL, метод, заголовки, тело). Используйте инструменты вроде Postman или Charles Proxy для независимой проверки.
    • Проверьте логи клиентского приложения на предмет ошибок.
  2. Проверка сети и доступности:

    • Выполните ping и traceroute (или tcptraceroute) до хоста сервера для проверки базовой сетевой связности и задержек.
    • Убедитесь, что не срабатывают файрволы или прокси-серверы.
  3. Проверка сервера:

    • Изучите логи серверного приложения (например, tail -f application.log). Ищите ошибки обработки запроса.
    • Проверьте метрики сервера (CPU, память, диски) — возможно, он перегружен.
    • Убедитесь, что нужный сервис или порт запущен (netstat -tulpn | grep :443).

Пример кода с обработкой таймаута и повторными попытками (retry):

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# Настраиваем стратегию повторных попыток
retry_strategy = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[429, 500, 502, 503, 504],
    allowed_methods=["GET", "POST"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)

session = requests.Session()
session.mount("https://", adapter)
session.mount("http://", adapter)

try:
    # Устанавливаем общий таймаут (соединение + чтение)
    response = session.get("https://api.example.com/data", timeout=(3.05, 10))
    response.raise_for_status()  # Вызовет исключение для HTTP 4xx/5xx
    print("Успешный ответ:", response.json())
except requests.exceptions.Timeout:
    print("ОШИБКА: Превышено время ожидания ответа от сервера.")
except requests.exceptions.RequestException as e:
    print(f"ОШИБКА сетевого запроса: {e}")

Для автоматизированных тестов всегда реализуйте обработку таймаутов и логирование, чтобы такие инциденты не оставались незамеченными.