Короткий ответ
Единого шаблона нет — нужно явно решить, измерять ли SLI "изнутри" (включая деградацию от внешних зависимостей как часть ответственности сервиса) или "с поправкой" на известные ограничения зависимостей, и SLO итогового сервиса математически не может быть строже комбинации SLA его критичных внешних зависимостей без дополнительных мер отказоустойчивости (fallback, кэширование, graceful degradation).
Как это работает подробнее
если сервис синхронно зависит от трёх внешних API с SLA 99.9%, 99.95% и 99.9% каждый, и падение любого из них ведёт к полному отказу запроса, комбинированная теоретическая доступность (без дополнительных мер) не превысит произведение этих вероятностей успеха, что даёт величину ниже 99.9% для итогового сервиса — попытка пообещать клиентам SLO 99.95% для такого сервиса математически необоснованна без изменения архитектуры зависимостей.
Компромисс: закладывать избыточную отказоустойчивость (кэши, fallback, дублирование критичных зависимостей через несколько провайдеров) повышает достижимый SLO, но увеличивает сложность системы, стоимость и объём кода, который нужно поддерживать и тестировать; принятие SLO, напрямую ограниченного слабейшей зависимостью, проще, но может быть недостаточным для бизнес-требований. Решение должно явно обсуждать, какие конкретно зависимости достаточно критичны, чтобы инвестировать в устойчивость к их сбоям, basируясь на их реальном влиянии на пользователя и бюджет проекта, а не на абстрактном желании "99.99% для всего".
Пример кода
Внешние зависимости сервиса "checkout":
- payment-gateway (hard, SLA 99.9%)
- recommendation-service (soft, SLA 99.5%)
- fraud-check-service (hard, SLA 99.95%)
SLI (core): успешная оплата без учёта рекомендаций = f(payment-gateway, fraud-check)
SLI (enhanced): полный ответ с рекомендациями = f(core, recommendation-service)
При недоступности recommendation-service checkout отдаёт core-ответ без рекомендаций (graceful degradation),
поэтому core SLO (99.9%) не зависит от soft-зависимости напрямую.Что использовать на практике
- Практика. чтобы повысить собственный SLO выше ограничений, налагаемых слабейшей зависимостью, применяют graceful degradation (отдавать частичный или кэшированный ответ вместо полного отказа при недоступности некритичной зависимости), таймауты и circuit breaker (чтобы недоступная зависимость не блокировала весь запрос дольше необходимого), и разделение SLI на "core" (не зависит от необязательных внешних систем) и "enhanced" (с учётом всех фич). Важно явно задокументировать, какие зависимости являются hard (без них сервис физически не может ответить) и soft (без них сервис может ответить в ограниченном режиме).
- Практика. Такое разделение позволяет честно объявить SLO 99.9% для основной функции checkout, несмотря на то что одна из зависимостей (recommendation-service) имеет более слабый SLA, так как её сбой не приводит к полному отказу, а только к деградации неосновной функциональности.
Подводные камни
- Частые ошибки. декларировать SLO выше, чем математически возможно при текущей архитектуре зависимостей, что создаёт постоянно нарушаемую и бессмысленную цель; мониторить SLI только на уровне итогового ответа клиенту без разбивки по причине отказа (собственный код vs конкретная внешняя зависимость), из-за чего невозможно понять, на какую зависимость тратится error budget; не пересматривать SLO при смене или ухудшении SLA одной из внешних зависимостей, продолжая обещать прежнюю цель без архитектурных изменений.