Веб-розробкаE-commerce та Бізнес

Healthcheck дав 60 % запитів застосунку: що побачили в першу добу метрик

21 вересня 2026 року, у першу добу обліку запитів за маршрутами, службовий /api/health отримав 13 666 запитів — 60 % трафіку застосунку, і кожен ішов у спільну базу. Розповідаємо, які два налаштування це прибрали, яку ціну маємо за них і як перевірити свій healthcheck.

20 вересня 2026 року сайт LIONEX нарешті почав рахувати власні HTTP-запити за маршрутами. Наступного дня ми вперше подивились на повну добу даних і побачили, що найпопулярніша адреса сайту — не головна і не блог. Нею виявився /api/health, службовий маршрут, якого жодна людина ніколи не відкриває. За добу він отримав 13 666 запитів, тобто 60 % усього трафіку застосунку.

Чому метрики запитів до 20 вересня не писались узагалі, ми розповідали в статті про чотири тривоги, яких не було. Тут — перша знахідка, яку ці метрики дали, два налаштування, що її прибрали, і спосіб перевірити те саме у себе за кілька хвилин.

Що показала перша доба

Health-маршрут існує для платформи, а не для відвідувачів. Docker, налаштований через Coolify, періодично стукає на нього й за відповіддю вирішує, чи живий контейнер. Кілька поганих відповідей поспіль — і контейнер перезапускається.

Інтервал цієї перевірки стояв 5 секунд. За налаштуваннями це 17 280 викликів на добу; метрики за 21 вересня записали 13 666, менше за розрахунок, але того самого порядку. Сама частота ще не біда: відповісти «процес живий» можна майже безкоштовно. Біда сиділа в коді маршруту. На кожен виклик він робив у базу SELECT 1, тож теоретично стільки ж, 17 280 запитів на добу, база отримувала лише для того, щоб підтвердити, що вона на місці.

Ця база стоїть на тому самому сервері, що й ще десяток наших проєктів. Того дня load average сервера сягнув 8,36 при порозі тривоги 8. Скажемо прямо: яку частку цього навантаження давав healthcheck, ми не міряли, і причиною його не називаємо. Бачили ми інше — на спільній машині цілодобово крутилась зайва робота, про яку ніхто не знав.

Чому ніхто не помічав

Окремий виклик тривав мілісекунди, помилок не давав і в логах не світився. Помітити його можна було лише одним способом: порахувати запити за маршрутами. До 20 вересня цього не робили, а без такого розподілу службова адреса може забирати більшість трафіку, і жоден графік цього не покаже.

Гірше те, що поодинці все виглядало розумно. П'ять секунд були значенням у панелі деплою, їх ніхто не обирав свідомо. Запит у базу колись дописали з добрим наміром, «щоб перевірка чесно дивилась на базу»: health, який бази не торкається, може називати здоровим контейнер, що вже не здатен віддати жодної сторінки. Кожне рішення окремо захищається. Разом вони давали запит у спільну базу кожні п'ять секунд, без кінця.

Два важелі, і потрібні обидва

Перший — інтервал. 21 вересня ми змінили його з 5 на 30 секунд. Кількість спроб лишили 10, тож до перезапуску контейнер тепер має провалювати перевірки приблизно 5 хвилин (10 × 30 с). Раніше вистачало 50 секунд (10 × 5 с).

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

Другий важіль — сам маршрут. Успішний результат перевірки бази тепер пам'ятається 60 секунд у змінній процесу. Healthcheck отримує відповідь одразу, а база — щонайбільше один запит на хвилину.

Одного інтервалу було б замало: з ним кожен виклик і далі йшов би в базу, просто рідше. Один кеш прибрав би навантаження на базу, але платформа й надалі смикала б процес що п'ять секунд: 17 280 викликів на добу, кожен із запуском curl усередині контейнера. Разом вони розводять дві різні речі: як часто платформу цікавить стан і як часто відповідь справді доходить до бази.

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

Чому помилку не кешуємо

Пам'ятаємо лише успіх. Якщо база не відповіла, маршрут повертає 503 з текстом помилки, позначку успіху скидає, і наступний виклик знову йде в базу.

Логіка несиметрична навмисно. Успіх — звичайний стан, і його кешування знімає майже всю зайву роботу. Невдача — рівно той момент, коли за відповіддю платформа вирішує, чи перезапускати контейнер, тож кожна перевірка після неї має бути свіжою. Якби позначка успіху після збою лишалась, контейнер вважався б здоровим ще хвилину після падіння бази — саме тоді, коли його треба перезапускати.

Одна межа лишається й так: між останньою вдалою перевіркою і наступним справжнім запитом до бази минає до 60 секунд, і збій у цьому проміжку health побачить не одразу. На тлі п'ятихвилинного вікна до перезапуску ми вважаємо це прийнятним.

Перевірка

Спочатку локально: 13 викликів підряд дали один запит у базу, а виклик через 65 секунд знову пішов у базу. 22 вересня тести маршруту переписали: старий тест описував версію, якої давно не існувало, і взагалі не запускався, бо проєкту бракувало пакета jsdom. Нові перевіряють відповідь 200 і «ok», коли база на місці; відсутність другого запиту в базу протягом 60 секунд; 503 з текстом помилки, коли база недоступна; і те, що помилка не кешується.

Конфіг контейнера того ж дня: Interval 30 с, Timeout 5 с, Retries 10.

Цифри «після» і частка, яка майже не змінилась

22 вересня Prometheus за 15 хвилин поза вікном деплою показав 31,5 запиту до /api/health (дріб — наслідок того, як Prometheus рахує приріст лічильника на відрізку). Це близько 126 на годину, або приблизно 3 000 на добу замість 13 666.

Запитів у базу за побудовою кешу не більше одного на хвилину, тобто не більше 1 440 на добу замість 17 280. Ця цифра розрахована з налаштувань, окремо запити до бази ми не міряли.

Частка ж майже не зрушила. За ті самі 15 хвилин health дав 31,5 із 55 запитів застосунку, тобто досі більшість. Трафік сайту агенції невеликий, і службова адреса займає в ньому помітне місце за будь-якого інтервалу. Проблема ніколи не полягала в частці. Вона полягала в тому, що кожен із цих викликів ішов у спільну базу.

Пастка заміру: деплой у вікні

Перша спроба виміряти «після» дала 690 запитів за годину, наче ми нічого не змінили. Причина знайшлась у самому вікні: туди потрапив деплой нового образу. Під час розгортання платформа сама часто опитує health нового контейнера, а в системі метрик якийсь час живуть дві серії, старого й нового контейнера. За 15 хвилин після деплою вийшло 31,5.

Висновок простий: міряти поза вікном деплою, інакше легко «довести», що правка не спрацювала.

Як перевірити в себе

  1. Подивіться інтервал. Для Docker:

    docker inspect -f '{{json .Config.Healthcheck}}' <контейнер>
    

    Interval там у наносекундах: 5000000000 — це 5 секунд. У Kubernetes те саме лежить у periodSeconds для liveness і readiness.

  2. Прочитайте код health-маршруту. Що він робить на кожен виклик: іде в базу, у Redis, у зовнішній API? Помножте кожну таку дію на кількість викликів за добу:

    викликів на добу = 86 400 / інтервал у секундах
    86 400 / 5 = 17 280
    
  3. Розведіть «процес живий» і «готовий обслуговувати». Kubernetes прямо розділяє liveness і readiness. У Docker перевірка одна, тому робочий компроміс такий: кешувати успіх і не кешувати помилку.

  4. Хоч раз порахуйте запити за маршрутами — з логів проксі або з метрик застосунку. Без цього такі речі не видно в принципі.

  5. Помножте Retries на Interval. Результат — скільки часу контейнер працює зламаним до перезапуску. Це число варто обрати свідомо, а не отримати в спадок від значень за замовчуванням.

Межі

Усе описане стосується одного сайту на одній платформі, Coolify з Docker. Цифри «до» взяті за одну добу, «після» — за 15 хвилин плюс конфіг контейнера. Кількість запитів до бази після правки розрахована, а не виміряна.

І головне обмеження: ми не стверджуємо, що сайт став швидшим або що навантаження сервера впало. Цього ми не міряли. Прибрали ми зайву постійну роботу, якої ніхто не бачив, і більше нічого.

Якщо хочете, щоб хтось переглянув healthcheck, тривоги й облік запитів на вашому сайті, це частина роботи з моніторингу доступності. Налаштування контейнерів і самого сервера входять в адміністрування сервера.

Для себе ми винесли одне правило: службовий маршрут теж трафік, і рахувати його треба так само, як сторінки для людей.

Теги

PerformanceАналітика

Вам сподобалась стаття?

Ваша думка допомагає нам створювати кращий контент

Поділіться з друзями

Знайшли щось корисне?

Допоможіть іншим дізнатись про це — поділіться статтею в соціальних мережах

Дякуємо, що допомагаєте нам рости

Засновник LIONEX

Владислав Чистяков

Пише про те, що робить руками: інтернет-магазини на OpenCart, застосунки на Next.js, інтеграції та швидкість сайтів. У статтях — заміри й перевірки, які читач може повторити на своєму проєкті, а не загальні поради. Комерційна розробка з 2015 року.

Питання

Часті запитання

Відповіді на популярні питання по темі

Чому healthcheck може давати більшість запитів до сайту?

Бо платформа опитує його цілодобово з фіксованим інтервалом, а відвідувачів у невеликого сайту небагато. У нас 21 вересня 2026 року, у першу добу обліку запитів за маршрутами, /api/health отримав 13 666 запитів — 60 % усього трафіку застосунку. Інтервал стояв 5 секунд, а маршрут на кожен виклик робив у базу SELECT 1.

Як дізнатися, як часто Docker перевіряє контейнер?

Виконайте docker inspect -f '{{json .Config.Healthcheck}}' <контейнер>. Interval там указаний у наносекундах: 5000000000 означає 5 секунд. Кількість викликів на добу — 86 400 поділити на інтервал у секундах; для 5 секунд це 17 280. У Kubernetes те саме задає periodSeconds у liveness і readiness.

Чи не почне сайт пізніше помічати збої, якщо збільшити інтервал healthcheck?

Почне, і цю ціну треба приймати свідомо. Ми змінили інтервал з 5 на 30 секунд при тих самих 10 спробах, тож до перезапуску контейнера тепер минає приблизно 5 хвилин замість 50 секунд. Для сайту агенції без черги замовлень це прийнятно, для платіжного сервісу — може й ні.

Чому кешувати можна лише успішну перевірку бази, а помилку — ні?

Бо за відповіддю health платформа вирішує, чи перезапускати контейнер, і після збою кожна перевірка має бути свіжою. У нас успіх пам'ятається 60 секунд, а невдача повертає 503, скидає позначку успіху, і наступний виклик знову йде в базу. Інакше контейнер вважався б здоровим ще хвилину після падіння бази. Такий кеш працює в довгоживучому сервері Node, у serverless він нічого не запам'ятає.

Чому замір після змін показав, що нічого не змінилось?

Бо у вікно заміру потрапив деплой нового образу. Під час розгортання платформа часто опитує health нового контейнера, а в метриках якийсь час живуть дві серії — старого й нового. Перша спроба дала 690 запитів за годину, а 15 хвилин поза вікном деплою — 31,5 запиту, близько 126 на годину. Міряти треба поза деплоєм.

Отримуйте найкращі статті на пошту

Підпишіться на нашу розсилку та отримуйте корисні поради, інсайти та новини про веб-розробку, маркетинг та бізнес.

Ми поважаємо вашу приватність. Відписатись можна в будь-який момент.

Далі в блозі

Схожі статті

154 помилки типів, які викидала збірка: що в них знайшлосьВеб-розробка

154 помилки типів, які викидала збірка: що в них знайшлось

21 вересня 2026 року перевірка типів на нашому сайті показала 154 помилки, хоча збірка щоразу була зеленою: результат перевірки просто викидався. Усередині знайшлись нулі в статистиці посилань і в експорті аналітики, сортування, що не сортувало, і тести, які не запускались. Розповідаємо, як розбирали, що змінили і як перевірити свій проєкт.

Читати далі
Сертифікати продовжуються самі: TLS на 116 сайтах і один, що не продовживсяВеб-розробка

Сертифікати продовжуються самі: TLS на 116 сайтах і один, що не продовжився

22 вересня 2026 року ми перевірили HTTPS-сертифікати на 116 сайтах, які вже міряли для ринкових вимірів, і для 104 з них порівняли стан із серпневим. Усі 116 пройшли перевірку, 108 стоять на 89- і 90-денних безкоштовних сертифікатах, і лише в одного сайту сертифікат досі не продовжився, хоча за типових налаштувань уже мав би. Розбираємо заміри, межі методу й показуємо, як перевірити свій сайт однією командою.

Читати далі
Чотири тривоги, яких не було: моніторинг, що жив лише в документаціїВеб-розробка

Чотири тривоги, яких не було: моніторинг, що жив лише в документації

5 вересня 2026 року ми відкрили Grafana, щоб перевірити чотири правила тривог, які наша документація обіцяла з 17 січня. Правил там було нуль, метрики під ними — порожні, канал доставки — заглушка. Розповідаємо, що поставили замість, і як за пів години перевірити свій моніторинг.

Читати далі