Архитектура высоконагруженных веб-приложений
10 / 1191%
Мониторинг: метрики как оружие, алерты как контракты
100 минут
Для кого: инженеры, которых бесит узнавать о падении из Twitter. Если у вас нет SLO, алерты либо молчат, либо орут без причины — эта глава заставит вас сделать мониторинг, который работает.
Провокация №1: вы знаете, кто сейчас down?
- Откройте
http://prometheus/api/v1/query?query=up. Если есть сервисы со значением0и вы об этом не знаете — мониторинг мёртв. - Минимум: дашборд «up/down» по всем службам + алерт
up == 0> 1 минута.
1. Три столпа Observability — но за деньги
1.1 Metrics
- Prometheus + exporters.
prometheus.ymlобязательно содержитscrape_interval,evaluation_interval, rule files.
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "recording_rules.yml"
- "alerting_rules.yml"
scrape_configs:
- job_name: "api"
static_configs:
- targets: ["api:3000"]
metrics_path: "/metrics"- Recording rules для «золотых сигналов».
# recording_rules.yml
groups:
- name: api_recordings
rules:
- record: job:http_request_duration_seconds:p95
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
- record: job:http_request_error_rate
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))1.2 Logs
- Структурированные, JSON. Корелляционный ID обязателен.
logger.info("order_created", {
traceId: req.headers["x-trace-id"],
userId: req.user.id,
orderId: order.id,
amount,
});1.3 Traces
- OpenTelemetry SDK + Jaeger/Tempo. Пробрасываем заголовок
traceparent.
const span = tracer.startSpan("checkout", { attributes: { userId } });
res.set("traceparent", span.context().traceId);Провокация №2: у вас есть SLO?
- Если нет числа «мы гарантируем X% latency», вы не можете говорить о качестве.
2. SLI/SLO/SLА
| Сервис | SLI | SLO | SLA |
|---|---|---|---|
| API | P95 latency < 400ms | 99.5% | 99.9% |
| Checkout | Error rate < 0.3% | 99.7% | 99.95% |
Error budget:
def error_budget(total_requests: int, slo: float) -> int:
return int(total_requests * (1 - slo))
# Пример: 1M запросов/месяц, SLO 99.9% → 1000 ошибок в месяц- Используйте error budget, чтобы решать, можно ли выпускать релиз.
Провокация №3: у вас алерты привязаны к SLO?
- «CPU > 80%» — мусор. Алерт должен говорить: «SLO нарушается через 2 часа».
3. Alerting Rules
# alerting_rules.yml
groups:
- name: api_alerts
rules:
- alert: APIErrorBudgetBurn
expr: rate(http_requests_total{status=~"5.."}[5m]) > 5 * (1 - 0.999) * rate(http_requests_total[5m])
for: 5m
labels:
severity: critical
annotations:
summary: "API error budget burning >5x"
runbook: "https://wiki/runbooks/api-error-budget"- Severity уровни: page (critical), ticket (warning), log (info).
Провокация №4: алерты доставляются?
- Проверяйте:
curl -XPOST https://pagerduty/...— работает? Нет? Значит, PagerDuty вас не спасёт.
4. Grafana как боевой экран
- Four Golden Signals: latency, traffic, errors, saturation.
{
"dashboard": {
"title": "API Golden Signals",
"panels": [
{
"title": "RPS",
"targets": [{ "expr": "rate(http_requests_total[5m])" }]
},
{
"title": "P95 Latency",
"targets": [{ "expr": "job:http_request_duration_seconds:p95" }]
},
{
"title": "Error Rate",
"targets": [{ "expr": "job:http_request_error_rate" }]
},
{
"title": "CPU",
"targets": [{ "expr": "rate(process_cpu_seconds_total[5m])" }]
}
]
}
}Провокация №5: у вас есть runbooks?
- Алерт без runbook — издевательство над on-call.
Runbook пример
Alert: Redis lag > 500ms
Steps:
1. Проверить `info replication`
2. Если `master_link_status=down` > 30s — переключить трафик на master-only
3. Уведомить #oncall-redis
4. Создать инцидент в Jira/StatusPageПровокация №6: тестируете ли вы мониторинг?
- Chaos engineering: «выключите dependency» и убедитесь, что алерт сработал, runbook помог.
Chaos сценарий
# Уронить dependency
kubectl scale deploy payment-api --replicas=0
# Должен сработать алерт "Payment API down"Провокация №7: логирование не утопит вас в счёте?
- Управляйте retention, sampling.
loki:
chunk_target_size: 1048576
retention_period: 7dПровокация №8: trace sampling?
- 100% sampling = дорого. Используйте dynamic sampling (например, ошибки всегда 100%, нормальные 10%).
const sampler = new TraceIdRatioBasedSampler({ ratio: 0.1 });Практика
- SLI/SLO расчёт:
- Выберите ключевой сервис, посчитайте monthly error budget, оформите SLO документ.
- Golden Signals Dashboard:
- Создайте Grafana дашборд с latency/traffic/errors/saturation + алерты, привязанные к runbook.
- Alert storm simulation:
- Намеренно вызовите 5 разных алертов на staging, оцените шум, оптимизируйте правила (aggregation, deadman switch).
- Tracing drill:
- Инструментируйте цепочку из 3 сервисов через OpenTelemetry, найдите trace конкретного запроса.
- Runbook + Chaos:
- Напишите runbook для «DB lag > 500ms». Проведите столбовую проверку: отключите реплику на staging, следуйте runbook, проверьте, что всё работает.
Безопасность: логи и трейсы не должны содержать PII без шифрования. Chaos-тесты только на staging, и только после согласования.
Что дальше
Архитектурные паттерны и решения: теперь, когда вы умеете измерять и реагировать, пора принимать системные решения (финальная глава).