ping проходит, curl / отвечает 200, а пользователи видят ошибки:
часть запросов падает или идёт секундами. Проверка «жив ли сервер»
этого не видит. Видит журнал запросов, если сосчитать, сколько
запросов прошло хорошо и как быстро.
SLI (service level indicator, показатель уровня обслуживания) —
измеренная доля хороших событий: хороших ответов из всех, быстрых
ответов из всех. SLO (service level objective, цель уровня
обслуживания) — какой SLI считается нормой за окно времени: «99,5 %
ответов без 5xx за 30 дней». Разница между целью и 100 % — бюджет
ошибок: сколько плохих запросов цель ещё допускает.
SLI: доля хороших запросов
SLI = хорошие ÷ все. Что считать хорошим, решают заранее по тому,
что видит пользователь, и записывают рядом с SLO:
| Ответ |
Для SLI доступности |
| 2xx, 3xx |
хороший |
| 4xx |
обычно хороший: ошибся клиент, сервис ответил верно |
| 5xx |
плохой: не справился сервер |
| 499 в nginx |
клиент закрыл соединение, не дождавшись ответа |
Код 499 пишет только nginx. Если клиенты уходят из-за медленного
сервера, 499 — тоже плохой ответ; если это обрывы сети у клиентов —
его не считают вовсе.
Два частых SLI:
- доступность — доля ответов без 5xx;
- задержка — доля ответов быстрее порога («быстрее 300 мс») или
перцентиль времени ответа («p95 не больше 1 с», ниже).
Считают по журналу того, кто стоит первым на пути запроса: nginx или
балансировщика перед приложением. Он видит и те запросы, до которых
приложение не дошло: 502 и 504 — ответы самого nginx, в журнале
приложения их нет (nginx).
Окно времени
SLI всегда считают за период: час, сутки, 30 дней. Сто ошибок — это
7 % за час, в котором было 1400 запросов, и 0,01 % за месяц с тем же
потоком. Окно задают двумя метками времени: начало включительно,
конец нет. Тогда соседние окна не считают одну строку дважды.
Время в формате combined — $time_local вида
[22/Oct/2026:10:03:58 +0000]: месяц словом, такие метки как текст
не сравнить. Для окна в конец строки журнала добавляют $msec —
секунды unix-времени с миллисекундами, число:
… "GET /api HTTP/1.1" 500 21 "-" "curl/8.5.0" 0.004 1792677901.123
Здесь 0.004 — $request_time, время ответа в секундах, а
1792677901.123 — $msec. Номера полей awk считают от конца
строки, $(NF-1) и $NF: user-agent с пробелами сдвигает номера от
начала. Как задать такой формат — nginx. Окно — сравнение
числом: $NF >= начало && $NF < конец, а начало и конец даёт
date -d '…' +%s.
Перцентиль: p50, p95, p99
Среднее время ответа прячет хвост. 95 ответов по 0,05 с и 5 ответов
по 10 с дают в среднем 0,55 с, хотя каждый двадцатый ждал 10 секунд.
Перцентиль p95 — время, за которое уложились 95 % ответов. p50 —
медиана, p99 — граница худшего процента. Считают так: времена
сортируют по возрастанию и берут значение с номером ⌈0,95 × N⌉,
округлённым вверх (метод ближайшего ранга). Из 100 значений это 95-е,
из 1400 — 1330-е, из 7 — 7-е.
Другие программы считают с интерполяцией между соседними значениями:
так делает histogram_quantile в promql. На малой выборке
результаты расходятся, поэтому метод записывают вместе с SLO.
SLO и SLA
SLO — цель для SLI за окно: «99,5 % ответов без 5xx за 30 дней»,
«95 % ответов быстрее 1 с за сутки». Цель ставят ниже 100 %: каждая
выкладка, перезапуск и сбой сети тратят её часть.
SLA (service level agreement) — договор с клиентом, где за
нарушение есть последствия: возврат денег, штраф. В SLA ставят цифру
мягче своего SLO, чтобы команда узнала о проблеме до нарушения
договора.
Сколько простоя допускает цель:
| SLO |
За 30 дней |
За сутки |
| 99 % |
7 ч 12 мин |
14 мин 24 с |
| 99,5 % |
3 ч 36 мин |
7 мин 12 с |
| 99,9 % |
43 мин 12 с |
1 мин 26 с |
| 99,95 % |
21 мин 36 с |
43 с |
| 99,99 % |
4 мин 19 с |
9 с |
Минуты простоя — упрощение: оно верно, если в сбой падают все
запросы, а нагрузка ровная. По журналу бюджет считают в запросах.
Бюджет ошибок
допустимо = (1 − SLO) × всего запросов за окно
потрачено = плохих запросов за окно
осталось = допустимо − потрачено (в % — осталось ÷ допустимо)
При SLO 99,5 % и 400 000 запросах за 30 дней можно 2000 плохих.
Вчерашний сбой дал 1400 ответов 5xx: потрачено 70 %, осталось 600
запросов, 30 % бюджета. Сколько запросов придёт до конца окна, ещё
неизвестно: берут ожидаемое число по прошлым окнам или сравнивают
доли — долю плохих за окно с 1 − SLO.
Бюджет — правило для решений. Остался — можно выкатывать и
рисковать. Кончился — рискованные изменения ждут, команда чинит то,
что его тратит. Правило записывают заранее (политика бюджета ошибок),
во время сбоя его не обсуждают.
Скорость расхода
Скорость расхода (burn rate) — во сколько раз доля плохих
запросов больше допустимой: доля плохих за последнее окно ÷ (1 − SLO).
- 1 — бюджет кончится ровно к концу 30 дней;
- 2 — за 15 дней;
- 14 — сбой с 7 % ошибок при SLO 99,5 % (
0,07 ÷ 0,005): бюджет 30
дней уйдёт за два дня, час сбоя съедает 2 % бюджета.
На скорость расхода ставят алерты. Быстрый — скорость выше 14,4 за
последний час: за час ушло 2 % бюджета, нужен дежурный. Медленный —
выше 6 за 6 часов: ушло 5 %, задача на рабочий день. Как пишут
правило — prometheus, доля 5xx на PromQL —
promql.