Guides 7 min czytania

Jak zbudować endpoint health check (i go monitorować)

Endpoint health check mówi monitorom i load balancerom, czy Twoja aplikacja może obsługiwać żądania. Co sprawdzać, jak zachować szybkość i bezpieczeństwo, kod dla Laravela, Expressa i Flaska oraz jak go monitorować.

Endpoint health check to adres URL, zwykle /health, który mówi monitorowi lub load balancerowi, czy Twoja aplikacja może obsługiwać żądania. Wykonuje kilka szybkich testów zależności aplikacji, takich jak baza danych, cache i wolne miejsce na dysku, i odpowiada HTTP 200 z {„status”:”ok”}, gdy wszystko działa, albo HTTP 503 z nazwą nieudanego testu, gdy coś zawodzi. Niech będzie szybki, tani, bez cache’owania i bez sekretów, a potem skieruj na niego monitor dostępności, który sprawdza treść odpowiedzi, a nie tylko kod statusu.

Ten poradnik wyjaśnia różnicę między liveness a readiness, co sprawdzać, jaki format odpowiedzi przyjąć, pokazuje działające przykłady dla PHP z Laravelem, Node z Expressem i Pythona z Flaskiem oraz opisuje, jak monitorować gotowy endpoint.

Dlaczego strona główna to nie health check

Większość zespołów zaczyna od monitorowania strony głównej. To rozsądny pierwszy krok, ale strona główna często jest serwowana z CDN lub cache stron, więc odpowiada 200 nawet wtedy, gdy baza danych leży i nikt nie może się zalogować ani dokończyć zakupu. Dedykowany endpoint omija cache i bezpośrednio sprawdza zależności. Daje też jeden przewidywalny adres URL z małą, stabilną odpowiedzią, którą łatwo zweryfikować.

Liveness a readiness

Platformy kontenerowe, takie jak Kubernetes, dzielą kondycję aplikacji na dwa pytania – i ten podział przydaje się wszędzie:

Liveness: czy proces żyje i nie utknął? Jeśli nie, zrestartuj go. Test liveness nie powinien sprawdzać bazy danych ani innych usług. Jeśli baza padnie, a każda instancja aplikacji nie przejdzie testu liveness, platforma zrestartuje je wszystkie – to nie naprawi bazy, a tylko spowolni powrót do działania.

Readiness: czy ta instancja może teraz obsługiwać prawdziwe żądania? Jeśli nie, przestań kierować do niej ruch. To tutaj należą testy zależności.

Typowy układ to /livez lub /up dla liveness, zwracający 200, dopóki aplikacja się uruchamia, oraz /health lub /readyz dla readiness. Przy zewnętrznym monitorowaniu dostępności ciekawszy jest endpoint readiness, bo odpowiada na pytanie, które obchodzi Twoich klientów: czy aplikacja działa?

Co sprawdzać

Sprawdzaj zależności, bez których zwykłe żądanie by się nie powiodło – i nic ponadto:

Baza danych: wykonaj SELECT 1 na tej samej puli połączeń, z której korzysta aplikacja. To dowodzi, że serwer jest osiągalny i przyjmuje zapytania.

Cache lub magazyn sesji: zapisz i odczytaj krótkotrwały klucz w Redisie lub Memcached. Jeśli przechowujesz tam sesje, logowanie od tego zależy.

Dysk: sprawdź wolne miejsce na wolumenie, na który aplikacja zapisuje przesłane pliki, logi lub sesje. Zgłaszaj błąd, gdy spadnie poniżej marginesu, na przykład 10 procent.

Kolejka: sprawdź, czy backend kolejki odpowiada, i opcjonalnie, czy najstarsze oczekujące zadanie nie jest starsze niż wybrany przez Ciebie limit. Rosnąca zaległość oznacza, że workery przestały działać.

Uważaj na zewnętrzne API. Jeśli Twój endpoint przy każdym teście odpytuje operatora płatności, a ten działa wolno, health check zawiedzie, choć Twoja aplikacja ma się dobrze – a load balancer może wyłączyć z ruchu wszystkie instancje. Zamiast tego monitoruj usługi zewnętrzne osobnymi monitorami, żeby alert od razu mówił, czyj to problem. Monitorowanie usług zewnętrznych w Uptimecheck śledzi strony statusu 31 usług, takich jak Klarna, Swish, Shopify, Cloudflare i OpenAI, albo dowolną stronę hostowaną w Statuspage.

Niech będzie szybki i tani

Health check jest wywoływany co minutę przez każdy monitor i load balancer, przez całą dobę. Nigdy nie może stać się tym, co przeciąża aplikację.

Daj każdemu testowi zależności własny krótki timeout, na przykład sekundę lub dwie, żeby jedna zawieszona usługa nie zawiesiła całego endpointu.

Uruchamiaj testy równolegle tam, gdzie Twój język to ułatwia.

Używaj trywialnych zapytań. Nigdy nie licz wierszy w dużej tabeli ani nie generuj raportu.

Jeśli endpoint odpytuje wiele narzędzi, przechowuj wynik w pamięci przez kilka sekund.

Wysyłaj Cache-Control: no-store i wyłącz tę ścieżkę z cache stron i CDN, żeby nigdy nie zobaczyć „ok” z pamięci podręcznej.

Pomiń sesje, ciasteczka i middleware uwierzytelniania, których endpoint nie potrzebuje.

Nie ujawniaj sekretów

Publiczny endpoint health check zobaczy każdy, kto zgadnie /health. Zwracaj nazwę i stan każdego testu – i nic więcej. Nie umieszczaj w odpowiedzi komunikatów wyjątków, connection stringów, nazw hostów, wewnętrznych adresów IP, wersji oprogramowania ani zmiennych środowiskowych. Szczegółowy błąd zapisuj w logach na serwerze. Jeśli chcesz bogatszego widoku diagnostycznego, umieść go pod osobną ścieżką za uwierzytelnianiem albo ogranicz dostęp do sieci wewnętrznej.

Format odpowiedzi i kody statusu

Niech JSON będzie mały i stabilny:

{
„status”: „ok”,
„checks”: {
„database”: „ok”,
„cache”: „ok”,
„disk”: „ok”,
„queue”: „ok”
}
}

Gdy test zawiedzie, ustaw jego wartość na „fail”, ustaw status najwyższego poziomu na „fail” i zmień kod statusu HTTP:

200 OK, gdy przechodzą wszystkie wymagane testy.

503 Service Unavailable, gdy wymagany test zawiedzie. Tego kodu load balancery i monitory oczekują w sytuacji „chwilowo nie mogę obsługiwać żądań”.

Opcjonalnie 200 z „status”:”degraded”, gdy nie działa opcjonalna zależność, a rdzeń aplikacji wciąż działa. Z góry zdecyduj, które testy są wymagane.

Unikaj zwracania 200 z „status”:”fail” w treści. Wiele narzędzi odczytuje tylko kod statusu. Jak zwykle traktowany jest każdy kod, opisuje artykuł Kody statusu HTTP w monitorowaniu.

Przykład: PHP i Laravel

Nowsze wersje Laravela mają wbudowaną prostą trasę /up, która potwierdza, że aplikacja się uruchamia – to dobry test liveness. Dla readiness dodaj trasę, która sprawdza zależności:

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;

Route::get(’/health’, function () {
$checks = [];

try {
DB::select(’SELECT 1′);
$checks[’database’] = 'ok’;
} catch (\Throwable $e) {
report($e);
$checks[’database’] = 'fail’;
}

try {
Cache::put(’health-check’, 'ok’, 10);
$checks[’cache’] = Cache::get(’health-check’) === 'ok’ ? 'ok’ : 'fail’;
} catch (\Throwable $e) {
report($e);
$checks[’cache’] = 'fail’;
}

$path = storage_path();
$checks[’disk’] = disk_free_space($path) / disk_total_space($path) > 0.10 ? 'ok’ : 'fail’;

$healthy = ! in_array(’fail’, $checks, true);

return response()
->json([’status’ => $healthy ? 'ok’ : 'fail’, 'checks’ => $checks], $healthy ? 200 : 503)
->header(’Cache-Control’, 'no-store’);
});

Zarejestruj ją poza grupami middleware, które uruchamiają sesje, i ustaw w konfiguracji krótki timeout połączenia z bazą danych.

Przykład: Node i Express

const withTimeout = (promise, ms) =>
Promise.race([
promise,
new Promise((_, reject) => setTimeout(() => reject(new Error(’timeout’)), ms)),
]);

const check = (fn) => withTimeout(fn(), 2000).then(() => 'ok’, () => 'fail’);

app.get(’/health’, async (req, res) => {
const [database, cache] = await Promise.all([
check(() => pool.query(’SELECT 1′)),
check(() => redis.ping()),
]);

const checks = { database, cache };
const healthy = Object.values(checks).every((v) => v === 'ok’);

res
.set(’Cache-Control’, 'no-store’)
.status(healthy ? 200 : 503)
.json({ status: healthy ? 'ok’ : 'fail’, checks });
});

Testy działają równolegle, każdy z limitem dwóch sekund, więc endpoint odpowiada w ciągu około dwóch sekund nawet wtedy, gdy któraś zależność się zawiesi.

Przykład: Python i Flask

import shutil
from flask import jsonify
from sqlalchemy import text

@app.get(„/health”)
def health():
checks = {}

try:
db.session.execute(text(„SELECT 1”))
checks[„database”] = „ok”
except Exception:
app.logger.exception(„health: database”)
checks[„database”] = „fail”

usage = shutil.disk_usage(„/”)
checks[„disk”] = „ok” if usage.free / usage.total > 0.10 else „fail”

healthy = all(value == „ok” for value in checks.values())
body = {„status”: „ok” if healthy else „fail”, „checks”: checks}
return jsonify(body), 200 if healthy else 503, {„Cache-Control”: „no-store”}

W ten sam sposób dodaj test Redisa, jeśli używasz go do sesji lub kolejki zadań.

Przetestuj scenariusz awarii

Health check, który nigdy nie zawiódł, nigdy nie został przetestowany. Na środowisku stagingowym zatrzymaj bazę danych albo skieruj aplikację na błędny host cache i potwierdź, że endpoint zwraca 503 w ramach Twojego timeoutu i wskazuje właściwy test. Następnie upewnij się, że odpowiedź nie zawiera treści błędu. Zajmuje to dziesięć minut i daje pewność, że endpoint powie prawdę wtedy, gdy będzie to ważne.

Monitorowanie endpointu

Endpoint, którego nikt nie sprawdza z zewnątrz, to tylko połowa pracy. Skieruj na niego monitor HTTP spoza Twojej sieci, żeby wychwytywał też problemy z DNS, TLS, firewallem i load balancerem:

Monitoruj https://lumenanalytics.io/health metodą GET co minutę.

Oczekuj statusu 200 i sprawdzaj, czy treść zawiera „status”:”ok”. Wtedy strona błędu proxy, która przypadkiem zwraca 200, i tak nie przejdzie testu.

Wysyłaj własny nagłówek User-Agent, żeby ruch z monitoringu łatwo było odfiltrować z analityki i logów.

Obserwuj historię czasu odpowiedzi. Health check, który powoli rośnie z 40 ms do 900 ms, to wczesne ostrzeżenie, że baza danych nie nadąża.

Kieruj alert do osób odpowiedzialnych za usługę.

Monitorowanie API w Uptimecheck obsługuje własne metody i nagłówki (w tym basic auth lub token bearer) oraz sprawdza oczekiwany status, słowa kluczowe i pola JSON, więc taka konfiguracja zajmuje minutę. Obok utrzymuj zwykły monitor dostępności strony głównej i najważniejszej strony konwersji; lista kontrolna monitorowania API opisuje inne endpointy, które warto obserwować.

Workery kolejek i zadania cykliczne często działają poza procesem webowym, więc endpoint health check nie widzi, czy przestały działać. Zamiast tego daj im heartbeaty: worker co kilka minut wywołuje adres URL, a brak takiego sygnału uruchamia alert.

Lista kontrolna endpointu health check

Oddziel liveness (proces żyje) od readiness (zależności działają).

Sprawdzaj bazę danych, cache, dysk i kolejkę, których aplikacja potrzebuje do obsługi żądania.

Daj każdemu testowi krótki timeout i używaj trywialnych zapytań.

Zwracaj 200, gdy wszystko działa, i 503, gdy wymagany test zawiedzie.

Zwracaj tylko nazwy i stany testów. Żadnych błędów, wersji ani nazw hostów.

Wyłącz cache’owanie dla tej ścieżki.

Monitoruj endpoint co minutę z zewnątrz, z weryfikacją odpowiedzi.

Uptimecheck monitoruje endpointy health check, API, serwery i zadania cykliczne w jednym koncie. Rozpocznij 14-dniowy darmowy okres próbny, bez karty kredytowej.

Pytania

Co powinien zwracać endpoint health check?

Niewielki JSON z ogólnym statusem i stanem każdego testu, z kodem HTTP 200, gdy działa wszystko, co wymagane, i HTTP 503, gdy wymagany test zawiedzie.

Czy health check powinien sprawdzać bazę danych?

Test readiness – tak, trywialnym zapytaniem, takim jak SELECT 1, z krótkim timeoutem. Test liveness – nie, bo wtedy awaria bazy danych zrestartowałaby wszystkie instancje aplikacji.

Czy endpoint health check może być publiczny?

Tak, jeśli zwraca tylko nazwy i stany testów. Nie umieszczaj w odpowiedzi komunikatów błędów, wersji, nazw hostów ani danych połączeń – zapisuj je w logach na serwerze.

Jak często monitorować endpoint health check?

Co minutę w przypadku usług produkcyjnych. Sprawdzaj nie tylko kod statusu, ale też to, czy treść zawiera oczekiwany status, żeby strona błędu z cache lub proxy nie przeszła testu.

Czytaj dalej

Guides 7 min czytania

Jak ograniczyć fałszywe alerty w monitorowaniu dostępności

Fałszywe alerty uczą zespoły ignorować monitoring. Jak ograniczyć szum: potwierdzaj każdą awarię drugim testem, ustaw rozsądne limity czasu, sprawdzaj właściwy adres URL i kieruj alerty do osób, które mogą zareagować.

Czytaj

Guides 5 min czytania

Checklista monitorowania API: co sprawdzać poza 200 OK

API może zwracać 200 i mimo to nie działać. Praktyczna checklista monitorowania API: metody, nagłówki, treść żądań, uwierzytelnianie, oczekiwane odpowiedzi i progi czasu odpowiedzi.

Czytaj

Guides 4 min czytania

Koszt niedostępności strony: jak obliczyć swój

Ile naprawdę kosztuje godzina przestoju? Prosty wzór na bezpośrednie i ukryte koszty niedostępności, przykłady obliczeń i to, co procenty dostępności oznaczają w pieniądzach.

Czytaj

Przestoje to przeszłość.

Skonfiguruj pierwszy monitor w niecałą minutę albo najpierw rozejrzyj się w demo na żywo.

14 dni za darmo · Potem 5 monitorów gratis · Bez karty kredytowej