13
0
0
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники
Назад

RED, USE и Four Golden Signals на .NET

Время чтения 14 минут
Нет времени читать?
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники
13
0
0
Нет времени читать?
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники

В SRE есть три устоявшихся набора метрик: RED, USE и Four Golden Signals (Google SRE Book). Их часто противопоставляют, пытаясь выбрать один из них. На практике же они дополняют друг друга, потому что смотрят на систему с трех разных позиций: со стороны клиента, ресурса и SLO.

В этой статье я разберу, откуда каждый набор взялся и какую слепую зону закрывает; покажу на .NET 8 API, как они сосуществуют; в конце — рабочий репозиторий с инцидентом, который воспроизводится одной командой docker compose up.

RED, USE и Four Golden Signals на .NET

Зачем в SRE паттерны

Представьте, что вы настраиваете мониторинг с нуля. Открываете документацию, а там сотни доступных метрик: latency, CPU, GC, heap, connections, queue length. Что выбрать?

Обычно берут то, что кажется важным. В итоге получается дашборд на два экрана, алерты на всё подряд — и полная каша в момент реального инцидента, потому что непонятно, куда смотреть.

Паттерны RED, USE и Four Golden Signals позволяют не думать о том, какие метрики выбрать. Они показывают, на какие вопросы должен отвечать дашборд и что служит хорошим направлением для выбора метрик.

SLI, SLO, SLA

SLI (Service Level Indicator) — измеримая характеристика поведения сервиса. Доля успешных запросов за последние 5 минут, p99 latency, процент времени, когда сервис был доступен, — всё это SLI. По сути, любая метрика, которую ты снимаешь с системы и которая что-то говорит о качестве обслуживания.

SLO (Service Level Objective) — целевое значение для SLI. Не просто latency, а «p99 latency ≤ 300 мс». Не просто «доля ошибок», а «доля ошибок < 0,1% за скользящее окно 30 дней». SLO — это внутреннее обещание команды самой себе: вот граница, за которой начинается «что-то пошло не так».

SLA (Service Level Agreement) — договор с пользователем или клиентом, основанный на SLO. Если SLO нарушается достаточно долго, наступают последствия: возврат денег, штраф, разговор с аккаунт-менеджером.

Связь между ними простая: SLI — измеряем, SLO — договариваемся внутри, SLA — договариваемся снаружи.

Обзор фреймворков

RED — взгляд со стороны клиента

RED придумали в компании Weaveworks. Она делала инструменты для Kubernetes, где основная работа происходила с подами. Компании нужен был способ мониторить сервисы, отсюда:

  • Rate — запросов в секунду.
  • Errors — доля или количество упавших подов.
  • Duration — распределение latency (гистограммой, не средним).

Слепая зона RED: нет saturation. Сервис может отвечать быстро и без ошибок, но при этом тред-пул копит очередь, и через 30 секунд всё рухнет. RED этого не покажет.

Saturation — это степень заполненности ресурса. Показывает, насколько ресурс близок к своему пределу и есть ли у него отложенная работа, которую он не успевает выполнить прямо сейчас.

USE — взгляд со стороны ресурса

Фреймворк USE возник в эпоху классического хостинга с понятными ресурсами (CPU, диск, сеть). Админы смотрели на систему со стороны железа:

  • Utilization — процент времени, что ресурс занят.
  • Saturation — длина очереди / отложенная работа.
  • Errors — счетчик ошибок ресурса.

Ключевая фишка USE — это не три обособленные метрики, а набор из трех метрик для каждого ресурса отдельно: для CPU, диска, ThreadPool, пула соединений HttpClient или БД.

Слепая зона USE: нет latency со стороны пользователя. Ресурс может быть недогружен (utilization 30%, queue пустая, errors нулевые), но пользователь всё равно ждет, потому что медленный, например, внешний API, который USE-метрик хоста не касается вообще.

Four Golden Signals — взгляд со стороны SLO

Четыре золотых сигнала придумали в Гугле (SRE Book, 2016) — это описание того, что Гугл эмпирически считает важным мониторить для user-facing сервисов:

  • Latency — время ответа, причем отдельно для успешных и неуспешных запросов.
  • Traffic — нагрузка в единицах, релевантных сервису (RPS для API, MB/s для стриминга).
  • Errors — доля упавших запросов.
  • Saturation — насколько ресурс близок к лимитам.

Гибрид RED и USE, но с двумя ключевыми различиями. Первое — деление latency по статусу. Второе — saturation определена через связь с пользовательским опытом, а не как абстрактная «длина очереди». То есть Four Golden Signals отвечают на вопрос «При каком уровне saturation начинается просадка для пользователей?».

Слабое место Four Golden Signals: saturation определена мутно. Гугл в книге сама признает — это hardest to measure. Для каждого ресурса метрика своя, порог свой, способ нормализации свой. На практике это означает, что Four Golden Signals не работают без USE-слоя под ними: нужно сначала собрать USE-метрики со всех ресурсов, а потом из них создать композитный saturation для дашборда.

Демо

Постановка задачи

Один эндпоинт — POST /payments. Принимает платеж, делает HTTP-запрос во внешнюю «платежную систему» (заглушка с настраиваемой latency), возвращает результат.


app.MapPost("/payments", async (PaymentRequest req, IExternalProcessor processor) =>
{
    var result = await processor.ChargeAsync(req);
    return Results.Ok(result);
});

 

IExternalProcessor — это HttpClient, который ходит в фейковую внешнюю систему. У нее есть параметр SET_LATENCY_MS, через который я в нужный момент включу деградацию.

Стек

  • .NET 8 Minimal API.
  • OpenTelemetry с Prometheus exporter — основной выбор для метрик.
  • Prometheus + Grafana в docker-compose с pre-provisioned дашбордом.

docker-compose.yml:


services:
  external-processor:
    build:
      context: .
      dockerfile: src/ExternalProcessor/Dockerfile
    ports:
      - "8081:8080"
    environment:
      - ASPNETCORE_URLS=http://+:8080
      - ASPNETCORE_ENVIRONMENT=Production
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/healthz"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s
 
  payments-api:
    build:
      context: .
      dockerfile: src/PaymentsApi/Dockerfile
    ports:
      - "8080:8080"
    environment:
      - ASPNETCORE_URLS=http://+:8080
      - ASPNETCORE_ENVIRONMENT=Production
      - ExternalProcessorUrl=http://external-processor:8080
    depends_on:
      external-processor:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/healthz"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 40s
    deploy:
      resources:
        limits:
          cpus: "2"
          memory: 512m
 
  prometheus:
    image: prom/prometheus:latest
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --enable-feature=exemplar-storage
      - --storage.tsdb.retention.time=1d
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
    depends_on:
      payments-api:
        condition: service_healthy
 
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_USERS_ALLOW_SIGN_UP=false
      - GF_AUTH_ANONYMOUS_ENABLED=false
      - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/etc/grafana/provisioning/dashboards/red-use-golden.json
    volumes:
      - ./grafana/provisioning:/etc/grafana/provisioning:ro
    depends_on:
      - prometheus

 

Минимальный набор метрик

Program.cs:


builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics
        .AddAspNetCoreInstrumentation()    // RED-слой
        .AddHttpClientInstrumentation()    // USE-слой (исходящие)
        .AddRuntimeInstrumentation()       // USE-слой (ThreadPool, GC)
        .AddProcessInstrumentation()       // USE-слой (CPU)
        .AddPrometheusExporter());
 
app.MapPrometheusScrapingEndpoint();

 

Четыре строчки инструментации — это весь набор метрик, на котором собирается дашборд.

Что мы получаем:

Инцидент

Сценарий

  1. Запускаем генератор нагрузки: 200 RPS на POST /payments.
  2. Первые 30 секунд внешний API отвечает за ~100 мс, всё стабильно.
  3. На 30-й секунде меняем условия — внешний API начинает отвечать за 2 секунды.
  4. Запросы копятся, ThreadPool начинает разгребать очередь, p99 latency растет.
  5. В конце концов Kestrel начнет отбивать новые соединения.

Что показывает каждый ряд

RED:

  • Duration p99 растет с 150 мс до 2,1 с.
  • Rate стабилен — 50 RPS.
  • Errors = 0 (внешний API не вернул ни одной ошибки).

USE:

  • process.runtime.dotnet.thread_pool.queue.length растет.
  • CPU utilization при этом низкий, около 40% — потоки заняты ожиданием, а не работой.
  • GC ведет себя нормально.

Four Golden Signals видят:

  • Latency: растет, как в RED.
  • Traffic: стабилен.
  • Errors: пока 0.
  • Saturation: 100% — и очень скоро мы начнем падать. 

Заключение

Мы разобрали паттерны в SRE — RED, USE, Four Golden Signals, а также посмотрели на их применение в инциденте. 

Спасибо за прочтение! Кроме того, я веду телеграм-канал Flexible Coding, где рассказываю о программировании и не только.

Комментарии0
Тоже интересно
Комментировать
Поделиться
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники