Guides 7 min lesing

Slik bygger du et helsesjekk-endepunkt (og overvåker det)

Et helsesjekk-endepunkt forteller monitorer og lastbalanserere om appen din kan betjene forespørsler. Hva du bør sjekke, hvordan du holder det raskt og trygt, kode for Laravel, Express og Flask, og hvordan du overvåker det.

Et helsesjekk-endepunkt (health check endpoint) er en URL, som regel /health, som forteller en monitor eller lastbalanserer om applikasjonen kan betjene forespørsler. Det kjører noen raske sjekker mot det appen er avhengig av, som databasen, cachen og ledig diskplass, og svarer med HTTP 200 og {«status»:»ok»} når alt fungerer, eller HTTP 503 og navnet på sjekken som feiler, når noe ikke gjør det. Hold det raskt, billig, uten cache og uten hemmeligheter, og pek deretter en oppetidsmonitor mot det som validerer svaret, ikke bare statuskoden.

Denne guiden tar for seg forskjellen på liveness og readiness, hva du bør sjekke, svarformatet, fungerende eksempler for PHP med Laravel, Node med Express og Python med Flask, og hvordan du overvåker endepunktet når det er på plass.

Hvorfor forsiden ikke er en helsesjekk

De fleste team starter med å overvåke forsiden. Det er et fornuftig første steg, men forsiden serveres ofte fra et CDN eller en sidecache, så den fortsetter å svare 200 mens databasen er nede og ingen kan logge inn eller fullføre et kjøp. Et eget endepunkt går utenom cachen og tester avhengighetene direkte. Det gir deg også én forutsigbar URL med et lite, stabilt svar som er lett å validere.

Liveness kontra readiness

Containerplattformer som Kubernetes deler helse inn i to spørsmål, og den inndelingen er nyttig overalt:

Liveness: lever prosessen, og har den ikke hengt seg opp? Hvis ikke, start den på nytt. En liveness-sjekk bør ikke teste databasen eller andre tjenester. Hvis databasen går ned og alle app-instansene feiler liveness-sjekken, starter plattformen alle sammen på nytt, noe som ikke fikser databasen og gjør gjenopprettingen tregere.

Readiness: kan denne instansen betjene ekte forespørsler akkurat nå? Hvis ikke, slutt å sende trafikk til den. Det er her avhengighetssjekkene hører hjemme.

Et vanlig oppsett er /livez eller /up for liveness, som returnerer 200 så lenge appen starter, og /health eller /readyz for readiness. For ekstern oppetidsovervåking er det readiness-endepunktet som er interessant, fordi det svarer på spørsmålet kundene bryr seg om: fungerer appen?

Hva du bør sjekke

Sjekk avhengighetene som en vanlig forespørsel ville feilet uten, og ikke noe mer:

Database: kjør SELECT 1 på den samme tilkoblingspoolen som appen bruker. Det beviser at serveren kan nås og tar imot spørringer.

Cache eller sesjonslager: skriv og les en kortlevd nøkkel i Redis eller Memcached. Hvis sesjonene ligger der, er innloggingen avhengig av det.

Disk: sjekk ledig plass på volumet appen skriver til, for opplastinger, logger eller sesjoner. Feil når den faller under en margin, for eksempel 10 prosent.

Kø: sjekk at købackenden svarer, og eventuelt at den eldste ventende jobben ikke er eldre enn en grense du velger. En voksende kø betyr at workerne har stoppet.

Vær forsiktig med tredjeparts-API-er. Hvis endepunktet ditt kaller en betalingsleverandør ved hver sjekk og leverandøren er treg, feiler helsesjekken selv om appen din er i orden, og en lastbalanserer kan ta alle instansene ut av rotasjon. Overvåk heller tredjeparter med egne monitorer, så et varsel forteller deg hvem sitt problem det er. Uptimechecks tredjepartsovervåking følger statussidene til 31 tjenester som Klarna, Swish, Shopify, Cloudflare og OpenAI, eller en hvilken som helst side som ligger på Statuspage.

Hold det raskt og billig

En helsesjekk kjøres hvert minutt fra hver monitor og lastbalanserer, døgnet rundt. Den må aldri bli det som overbelaster appen.

Gi hver avhengighetssjekk sin egen korte timeout, for eksempel ett eller to sekunder, så én tjeneste som henger, ikke får hele endepunktet til å henge.

Kjør sjekkene parallelt der språket ditt gjør det enkelt.

Bruk trivielle spørringer. Tell aldri rader i en stor tabell, og kjør aldri en rapport.

Hvis mange sjekkere treffer endepunktet, cache resultatet i minnet i noen sekunder.

Send Cache-Control: no-store og hold stien utenfor sidecacher og CDN-er, så du aldri ser en bufret «ok».

Dropp sesjoner, informasjonskapsler og autentiserings-middleware som endepunktet ikke trenger.

Ikke lekk hemmeligheter

Et offentlig helseendepunkt er synlig for alle som gjetter /health. Returner navnet og tilstanden til hver sjekk og ingenting annet. Ikke ta med feilmeldinger fra unntak, tilkoblingsstrenger, vertsnavn, interne IP-adresser, programvareversjoner eller miljøvariabler. Logg heller den detaljerte feilen på serveren. Vil du ha en rikere diagnosevisning, legg den på en egen sti bak autentisering, eller begrens den til det interne nettverket ditt.

Svarformat og statuskoder

Hold JSON-en liten og stabil:

{
«status»: «ok»,
«checks»: {
«database»: «ok»,
«cache»: «ok»,
«disk»: «ok»,
«queue»: «ok»
}
}

Når en sjekk feiler, setter du verdien dens til «fail», setter statusen på toppnivå til «fail» og endrer HTTP-statuskoden:

200 OK når alle påkrevde sjekker godkjennes.

503 Service Unavailable når en påkrevd sjekk feiler. Det er koden lastbalanserere og monitorer forventer for «kan midlertidig ikke betjene».

Eventuelt 200 med «status»:»degraded» for en valgfri avhengighet som er nede mens kjernen fortsatt fungerer. Bestem på forhånd hvilke sjekker som er påkrevde.

Unngå å returnere 200 med «status»:»fail» i svaret. Mange verktøy leser bare statuskoden. Se HTTP-statuskoder for overvåking for hvordan hver kode vanligvis behandles.

Eksempel: PHP og Laravel

Nyere Laravel-versjoner leveres med en enkel /up-rute som bekrefter at appen starter, og den fungerer godt som liveness-sjekk. For readiness legger du til en rute som sjekker avhengighetene:

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’);
});

Registrer den utenfor middleware-grupper som starter sesjoner, og sett en kort tilkoblingstimeout for databasen i konfigurasjonen.

Eksempel: Node og 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 });
});

Sjekkene kjører parallelt, hver med en grense på to sekunder, så endepunktet svarer innen rundt to sekunder selv når en avhengighet henger.

Eksempel: Python og 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»}

Legg til en Redis-sjekk på samme måte hvis du bruker det til sesjoner eller en oppgavekø.

Test feilscenarioet

En helsesjekk som aldri har feilet, har aldri blitt testet. Stopp databasen i staging, eller pek appen mot feil cache-vert, og bekreft at endepunktet returnerer 503 innenfor timeouten og navngir riktig sjekk. Bekreft deretter at svaret ikke inneholder feiltekst. Det tar ti minutter og forteller deg at endepunktet vil være ærlig når det gjelder.

Overvåk endepunktet

Et endepunkt ingen sjekker utenfra, er bare halve jobben. Pek en HTTP-monitor mot det fra utsiden av nettverket ditt, så den også fanger opp problemer med DNS, TLS, brannmur og lastbalanserer:

Overvåk https://lumenanalytics.io/health med GET hvert minutt.

Forvent status 200 og valider at svaret inneholder «status»:»ok». En feilside fra en proxy som tilfeldigvis returnerer 200, feiler da fortsatt sjekken.

Send en egen user agent-header, så overvåkingstrafikken er lett å filtrere ut av analyser og logger.

Følg med på historikken for responstid. En helsesjekk som kryper fra 40 ms til 900 ms, er et tidlig varsel om en database som sliter.

Send varselet til de som eier tjenesten.

API-overvåking i Uptimecheck støtter egne metoder og headere (inkludert basic auth eller et bearer-token) og validerer forventet status, nøkkelord og JSON-felt, så dette oppsettet tar et minutt. Ha i tillegg en vanlig oppetidsmonitor på forsiden og den viktigste konverteringssiden; sjekklisten for API-overvåking tar for seg de andre endepunktene som er verdt å følge med på.

Kø-workere og planlagte oppgaver kjører ofte utenfor webprosessen, så et helseendepunkt kan ikke se om de har stoppet. Gi dem heller heartbeats: workeren pinger en URL med noen minutters mellomrom, og et ping som uteblir, utløser varselet.

Sjekkliste for helsesjekk-endepunkt

Skill liveness (prosessen lever) fra readiness (avhengighetene fungerer).

Sjekk databasen, cachen, disken og køen appen trenger for å betjene en forespørsel.

Gi hver sjekk en kort timeout, og hold spørringene trivielle.

Returner 200 når alt er friskt og 503 når en påkrevd sjekk feiler.

Returner bare navn og tilstand for sjekkene. Ingen feil, versjoner eller vertsnavn.

Slå av caching for stien.

Overvåk det hvert minutt utenfra, med validering av svaret.

Uptimecheck overvåker helseendepunkter, API-er, servere og planlagte jobber i én konto. Start en gratis prøveperiode på 14 dager, uten kredittkort.

Spørsmål

Hva bør et helsesjekk-endepunkt returnere?

Et lite JSON-svar med en samlet status og tilstanden til hver sjekk, med HTTP 200 når alt påkrevd fungerer, og HTTP 503 når en påkrevd sjekk feiler.

Bør en helsesjekk teste databasen?

Readiness-sjekken bør det, med en triviell spørring som SELECT 1 og en kort timeout. En liveness-sjekk bør ikke det, for da ville et databaseavbrudd starte alle app-instansene på nytt.

Er det trygt å gjøre et helseendepunkt offentlig?

Ja, hvis det bare returnerer navn og tilstand for sjekkene. Hold feilmeldinger, versjoner, vertsnavn og tilkoblingsdetaljer utenfor svaret, og logg dem heller på serveren.

Hvor ofte bør et helsesjekk-endepunkt overvåkes?

Hvert minutt for tjenester i produksjon. Valider at svaret inneholder forventet status i tillegg til statuskoden, så en bufret side eller en feilside fra en proxy ikke blir godkjent.

Les videre

Guides 7 min lesing

Slik reduserer du falske varsler i oppetidsovervåkingen

Falske varsler lærer team å ignorere overvåkingen. Slik kutter du støyen: bekreft hver feil med en ny sjekk, sett fornuftige tidsavbrudd, valider riktig URL og send varslene til de som kan handle.

Les

Nedetid er fortid.

Sett opp din første monitor på under ett minutt, eller se deg rundt i livedemoen først.

14 dagers gratis prøveperiode · Deretter gratis for 5 monitorer · Uten kredittkort