Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Навіщо тайм-аути й повторні спроби при викликах інших сервісів і як їх налаштувати?

У розподіленій системі мережа ненадійна: запити губляться, сервіси перезапускаються, тимчасово перевантажуються. Код, що викликає інший сервіс, має бути готовий до цього.

Тайм-аут - обов'язковий для кожного мережевого виклику. Без нього запит до сервісу, що «завис», може чекати хвилини. Процес PHP зайнятий, наступні запити теж чекають - і за кілька хвилин вичерпано всі воркери застосунку через проблему іншого сервісу.

Http::connectTimeout(3)   // встановлення з'єднання
    ->timeout(10)          // уся відповідь
    ->get('https://inventory.internal/api/stock/42');

Значення - з урахуванням очікуваного часу відповіді, а не «з запасом на всяк випадок»: 10 секунд для виклику, що зазвичай займає 100 мс, означає, що користувач чекатиме 10 секунд при кожній проблемі.

Повторні спроби - для тимчасових помилок:

Http::timeout(5)
    ->retry([200, 500, 1000], when: fn (Throwable $e) =>
        $e instanceof ConnectionException
        || ($e instanceof RequestException && $e->response->serverError()))
    ->get($url);

Що повторювати, а що ні:

  • так: тайм-аути з'єднання, помилки мережі, 502, 503, 504, 429 (з урахуванням Retry-After);
  • ні: 400, 401, 403, 404, 422 - повтор дасть той самий результат;
  • обережно: неідемпотентні операції (POST створення, списання коштів) - лише з ключем ідемпотентності, інакше повтор створить дублікат.

Правила повторів:

  • експоненційна затримка (200 мс, 400 мс, 800 мс...) замість миттєвих повторів;
  • випадковий розкид (jitter) - щоб тисячі клієнтів після збою не повторювали синхронно й не «добили» сервіс, що відновлюється;
  • обмеження кількості спроб і загальний бюджет часу на операцію;
  • повтори не на кожному рівні: якщо клієнт повторює 3 рази, сервіс A повторює виклик B 3 рази, а B - виклик C 3 рази, один збій C перетворюється на 27 запитів (шторм повторів).

Для фонових операцій - повтори через чергу: tries і backoff у джобі, а не цикл повторів усередині HTTP-запиту.

Коли повтори не допомагають (сервіс лежить надовго) - потрібен circuit breaker, що перестає надсилати запити до несправного сервісу на певний час.

Докладніше в документації: Azure: патерн Retry

Схожі питання