Health checks у Solana-сервісі — це не просто пінг до порту. Виробниче середовище вимагає перевірки реальної здатності сервісу обробляти транзакції, читати стан ланцюга та спілкуватися з індексатором. Нижче — покрокова схема від ендпоінту до інтеграції з моніторингом, без яких ваш сервіс буде здаватися здоровим, поки не почне втрачати транзакції.
Ендпоінти для перевірки здоров'я
Розділяйте два типи перевірок: liveness (процес живий і приймає з'єднання) та readiness (процес реально може виконувати корисну роботу з ланцюгом). Єдиний ендпоінт /health, який повертає 200 OK без перевірки зв'язку з мережею, у production дає хибне відчуття безпеки.
Мінімальна структура відповіді
Ендпоінт readiness має повертати структуровану відповідь із статусом кожної критичної залежності:
- rpc — статус з'єднання з RPC-вузлом;
- indexer — статус з'єднання з індексатором (якщо використовується);
- db — статус з'єднання з базою даних (якщо сервіс кешує стан);
- degraded — прапорець часткової деградації (сервіс працює, але з обмеженнями).
Код відповіді: 200 — всі залежності доступні, 503 — хоча б одна критична залежність недоступна. Якщо сервіс працює у режимі деградації (наприклад, RPC відповідає, але з затримкою понад поріг), повертайте 200, але встановіть поле degraded: true. Це дозволить системі оркестрації не перезапускати сервіс, а моніторингу — підняти попередження.
Типова помилка
Перевірка лише власного HTTP-порту без фактичного виклику до Solana. Сервіс може приймати з'єднання, але мати виснажений пул з'єднань до RPC або невірний WebSocket-підключення. Результат — балансувальник навантаження направляє туди трафік, а транзакції не проходять.
Перевірка доступності RPC та індексатора
Перевірка RPC має бути легкою, але достатньо репрезентативною. Не використовуйте getBalance для великих адрес або складні запити до індексатора — вони створять зайве навантаження як на ваш сервіс, так і на вузол.
Перевірка RPC
Використовуйте getHealth для швидкої діагностики та getSlot для перевірки актуальності даних. getHealth повертає "ok", якщо вузол синхронізований, але не гарантує, що вузол не ізольований. Тому додатково порівнюйте слот із еталонним значенням.
Алгоритм перевірки:
- Викликати
getHealthз таймаутом, що не перевищує 2 секунди. - Якщо відповідь "ok" — викликати
getSlot. - Порівняти отриманий слот із попереднім відомим слотом. Якщо різниця менша за очікувану кількість слотів за інтервал перевірки (наприклад, слот не зріс за 30 секунд) — позначити RPC як застарілий (
stale). - Якщо
getHealthповертає помилку або таймаут — позначити RPC як недоступний.
Передумова: ваш сервіс має зберігати останній успішний слот і часову мітку перевірки в пам'яті. Не робіть додаткових запитів до сторонніх сервісів для визначення "найвищого слоту" — це створює зайву залежність.
Перевірка індексатора
Якщо ваш сервіс покладається на індексатор (Helius, Triton, власний Yellowstone gRPC), перевірка залежить від типу з'єднання:
- HTTP API індексатора — виконайте легкий запит (наприклад, отримання останнього блоку або пінг-ендпоінт, якщо індексатор його надає) з таймаутом 2–3 секунди.
- gRPC-з'єднання — перевірте стан каналу через
grpc.health.v1.Health/Check. Більшість production gRPC-сервісів підтримують цей стандарт. - WebSocket-підписки — перевірте, чи отримуєте ви події (slots або logs) протягом очікуваного інтервалу. Якщо WebSocket мовчить довше за поріг — позначте індексатор як недоступний.
Критично: не ігноруйте стан WebSocket-підписки. Розірване з'єднання без повторного підключення — поширена причина мовчазних відмов, коли сервіс вважає себе здоровим, але не отримує оновлення стану.
Обмеження
Не робіть перевірки надто часто. Інтервал 10–15 секунд є типовим для production. Частіші перевірки створюють навантаження на RPC-вузол і можуть спровокувати rate limiting. Якщо ваш провайдер RPC має жорсткі ліміти, розгляньте кешування результату перевірки між викликами ендпоінту.
Автоматичний restart при відмовах
Механізм перезапуску залежить від інфраструктури. Нижче — конфігурація для поширених інструментів із конкретними параметрами, які працюють із Solana-сервісами.
Docker Compose
Використовуйте два окремих healthcheck: один для liveness (швидкий), інший для readiness (з перевіркою RPC). Docker підтримує лише один healthcheck на контейнер, тому об'єднайте їх у один скрипт, який спочатку перевіряє порт, потім — readiness-ендпоінт.
- interval — 15s;
- timeout — 5s (має бути більшим за таймаут перевірки RPC всередині ендпоінту);
- retries — 3 (тобто сервіс буде визнаний нездоровим через 45 секунд безперервних невдач);
- start_period — 30s (дає сервісу час на ініціалізацію з'єднань).
Політика перезапуску: restart: unless-stopped. Не використовуйте always без обмежень — якщо сервіс падає одразу після старту (crash loop), безперервний перезапуск ускладнить діагностику.
Kubernetes
Розділяйте livenessProbe та readinessProbe. Liveness-проба перевіряє лише те, що процес відповідає на порт. Readiness-проба викликає ваш readiness-ендпоінт і перевіряє, що всі залежності доступні.
- livenessProbe:
httpGetна/health/live,periodSeconds: 10,failureThreshold: 5. Перезапуск пода відбувається після 50 секунд невдач. - readinessProbe:
httpGetна/health/ready,periodSeconds: 10,failureThreshold: 3. Под вилучається з трафіку через 30 секунд. - startupProbe: обов'язковий, якщо ініціалізація з'єднання з RPC або базою займає більше 10 секунд.
failureThreshold: 10приperiodSeconds: 3дає 30 секунд на старт.
Ризик: якщо readiness-проба занадто агресивна (маленький failureThreshold), короткочасна затримка RPC призведе до вилучення всіх подів з трафіку і повної відмови сервісу. Завжди тестуйте конфігурацію на штучній затримці RPC перед розгортанням.
Graceful shutdown
При перезапуску сервіс має завершити обробку поточних транзакцій. Налаштуйте обробник сигналу SIGTERM: сервіс має припинити приймати нові запити, дочекатися завершення активних (з таймаутом, наприклад 10 секунд), закрити з'єднання з RPC та базою, і лише тоді завершити процес. Без цього перезапуск при health check-відмові може спричинити втрату транзакцій, які вже були відправлені в мережу, але не отримали підтвердження.
Інтеграція з інфраструктурним моніторингом
Health checks самі по собі не дають видимості трендів. Для production необхідна інтеграція з системою моніторингу (Prometheus + Grafana є типовим стеком у Solana-екосистемі).
Метрики, які має експортувати сервіс
- solana_rpc_health_status (gauge: 1 — healthy, 0 — unhealthy) — поточний статус RPC;
- solana_rpc_response_duration_seconds (histogram) — тривалість відповіді RPC по типах запитів;
- solana_rpc_slot (gauge) — останній відомий слот для відстеження прогресу синхронізації;
- solana_indexer_health_status (gauge) — статус індексатора;
- solana_indexer_lag_slots (gauge) — відставання індексатора від останнього відомого слота;
- solana_websocket_connections_active (gauge) — кількість активних WebSocket-з'єднань;
- solana_health_check_total (counter з міткою result: success/failure) — загальна кількість перевірок для розрахунку частоти відмов.
Правила алертингу
Не алертуйте на кожну відмову health check — це створить шум. Алертуйте на стани, які вимагають втручання:
- Critical: RPC unhealthy більше 2 хвилин — сервіс не може обробляти транзакції.
- Warning: відставання індексатора перевищує 100 слотів — дані можуть бути застарілими, транзакції, що залежать від недавнього стану, оброблятимуться некоректно.
- Warning: медіана
solana_rpc_response_duration_secondsперевищує 500 мс протягом 5 хвилин — деградація продуктивності, яка ще не призвела до повної відмови, але впливає на користувацький досвід. - Info: кількість активних WebSocket-з'єднань впала до нуля — можливо, всі підписки розірвано і не відновлено.
План відкату
Якщо після зміни конфігурації health checks сервіс починає циклічно перезапускатися:
- Встановіть
restart: "no"(Docker) або збільштеfailureThresholdдо 10+ (Kubernetes), щоб зупинити цикл. - Перевірте логи сервісу на етапі ініціалізації — найчастіша причина: readiness-проба починає перевіряти RPC до того, як клієнт ініціалізовано.
- Тимчасово спростіть health check до перевірки лише порту, підтвердіть стабільність, потім повертайте перевірку залежностей по одній.
- Якщо проблема в таймаутах RPC — перевірте мережеву доступність між подом/контейнером і RPC-вузлом, можливо, змінилася конфігурація firewall або DNS.
Наступний логічний крок після налаштування health checks — забезпечити надійну обробку транзакцій при тимчасових відмовах. Якщо ваш сервіс відправляє транзакції, перейдіть до матеріалу про те, як працювати з transaction retries у production.