Health Checks — /health endpoint, DbContext, Redis check
Muammodan boshlaylik
Tunda PostgreSQL serveri to'ldi va to'xtadi. API jarayoni esa ishlab turibdi — port ochiq, ping javob beradi. Load balancer "server tirik" deb trafikni yuborishda davom etadi; har bir so'rov 30 soniya kutib, 500 qaytaradi. Ertalab mijozlar shikoyatidan bilasiz.
"Jarayon ishlayapti" va "ilova ishlashga tayyor" — turli narsalar.
Hayotiy o'xshatma
Smenaga kelgan haydovchi. U ishxonaga kelgan (jarayon tirik) — lekin mashinaga o'tirishdan oldin tekshiruvdan o'tadi: qon bosimi, hushyorlik (o'zi), mashinada yoqilg'i va tormoz (bog'liqliklar). Hammasi joyida bo'lsa — reysga chiqadi. Biror narsa noto'g'ri bo'lsa — dispetcher uni yo'lga chiqarmaydi va boshqa haydovchini yuboradi.
Asosiy sozlash
builder.Services.AddHealthChecks();
var app = builder.Build();
app.MapHealthChecks("/health");
GET /health
200 OK
Healthy
Holatlar:
| Holat | HTTP | Ma'nosi |
|---|---|---|
Healthy |
200 | Hammasi joyida |
Degraded |
200 | Ishlayapti, lekin muammo bor (sekin, ixtiyoriy servis yo'q) |
Unhealthy |
503 | Ishlay olmaydi |
Bog'liqliklarni tekshirish
Baza
dotnet add package Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore
builder.Services.AddHealthChecks()
.AddDbContextCheck<DokonDbContext>("baza", tags: ["ready"]);
DbContext orqali bazaga ulanish (CanConnectAsync) tekshiriladi.
Tayyor paketlar
dotnet add package AspNetCore.HealthChecks.NpgSql
dotnet add package AspNetCore.HealthChecks.Redis
builder.Services.AddHealthChecks()
.AddNpgSql(builder.Configuration.GetConnectionString("Dokon")!, name: "postgres", tags: ["ready"])
.AddRedis(builder.Configuration.GetConnectionString("Redis")!, name: "redis",
failureStatus: HealthStatus.Degraded, tags: ["ready"]);
Redis — cache (68-dars); u yiqilsa ilova sekinlashadi, lekin ishlaydi → Degraded, Unhealthy emas.
O'z tekshiruvingiz
public class TolovProvayderCheck(IHttpClientFactory f) : IHealthCheck
{
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext ctx, CancellationToken ct = default)
{
try
{
var http = f.CreateClient("tolov");
using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct);
cts.CancelAfter(TimeSpan.FromSeconds(3));
var javob = await http.GetAsync("/status", cts.Token);
return javob.IsSuccessStatusCode
? HealthCheckResult.Healthy()
: HealthCheckResult.Degraded(quot;Provayder {(int)javob.StatusCode} qaytardi");
}
catch (Exception ex)
{
return HealthCheckResult.Degraded("Provayder javob bermadi", ex);
}
}
}
builder.Services.AddHealthChecks().AddCheck<TolovProvayderCheck>("tolov", tags: ["ready"]);
Liveness va Readiness
Kubernetes va boshqa orkestratorlar ikki xil savol beradi:
| Liveness — "tirikmisan?" | Readiness — "trafik qabul qila olasanmi?" | |
|---|---|---|
| Tekshiradi | Jarayon osilib qolmaganmi | Baza, Redis, bog'liqliklar |
| Muvaffaqiyatsiz bo'lsa | Konteyner qayta ishga tushiriladi | Trafik yuborilmaydi, qayta ishga tushirilmaydi |
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
Predicate = _ => false // hech qanday tekshiruv — jarayon javob bersa, tirik
});
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = c => c.Tags.Contains("ready")
});
[!WARNING] Liveness ga baza tekshiruvini qo'ymang. Baza 2 daqiqa ishlamasa — barcha API konteynerlari "o'lik" deb hisoblanib, ketma-ket qayta ishga tushiriladi; baza qaytganda esa hammasi bir vaqtda ishga tushib, uni yana bo'g'adi. Bog'liqliklar — faqat readiness da.
Batafsil JSON javob
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = c => c.Tags.Contains("ready"),
ResponseWriter = async (ctx, report) =>
{
ctx.Response.ContentType = "application/json";
await ctx.Response.WriteAsJsonAsync(new
{
holat = report.Status.ToString(),
davomiylikMs = report.TotalDuration.TotalMilliseconds,
tekshiruvlar = report.Entries.Select(e => new
{
nomi = e.Key,
holat = e.Value.Status.ToString(),
tavsif = e.Value.Description,
davomiylikMs = e.Value.Duration.TotalMilliseconds
})
});
}
});
{
"holat": "Degraded",
"davomiylikMs": 42.7,
"tekshiruvlar": [
{ "nomi": "postgres", "holat": "Healthy", "tavsif": null, "davomiylikMs": 12.1 },
{ "nomi": "redis", "holat": "Unhealthy", "tavsif": "Connection refused", "davomiylikMs": 30.2 }
]
}
Ochiq health endpoint da batafsil ma'lumot (versiyalar, xato matnlari) bermang — faqat ichki tarmoqqa yoki autentifikatsiya bilan:
app.MapHealthChecks("/health/batafsil", ...).RequireAuthorization("Admin");
Qayerda ishlatiladi
- Docker —
HEALTHCHECK(80-dars) - Kubernetes —
livenessProbe,readinessProbe - Load balancer — sog'lom bo'lmagan serverga trafik yubormaslik
- Monitoring (UptimeRobot, Grafana) — ogohlantirishlar
Health endpoint lari rate limit va autentifikatsiyadan ozod qilinadi ([AllowAnonymous], DisableRateLimiting) — aks holda orkestrator ularni tekshira olmaydi.
Tez-tez uchraydigan xatolar
Faqat /health → 200 — bog'liqliklar tekshirilmaydi, foydasi kam.
Og'ir tekshiruvlar (to'liq so'rov, katta jadval) — har 10 soniyada bazani yuklaydi; yengil SELECT 1.
Timeout siz tashqi tekshiruv — health endpoint o'zi osilib qoladi.
Xulosa
Health check — ilova va bog'liqliklar ishlashga tayyorligini bildiruvchi endpoint: AddHealthChecks + MapHealthChecks; Healthy (200), Degraded (200), Unhealthy (503). Bog'liqliklar: AddDbContextCheck, AddNpgSql, AddRedis; o'zingizniki — IHealthCheck.
Liveness (jarayon tirikmi — bog'liqliksiz) va readiness (trafikka tayyormi — teglar bilan) — alohida endpoint lar. Ixtiyoriy bog'liqlik — Degraded. Batafsil javob — faqat himoyalangan; tekshiruvlar yengil va timeout bilan.
Keyingi dars
75-dars: Minimal API — MapGet, endpoint filter, MapGroup