Правила маршрутизации

Настройка динамических правил маршрутизации на CEL-выражениях для управления тем, как запросы распределяются между провайдерами.

Обзор

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

В отличие от governance routing (статические веса провайдеров), правила маршрутизации используют CEL-выражения (Common Expression Language) и оценивают условия в момент запроса.


Как это работает

Поток обработки запроса

Поток обработки запроса в правилах маршрутизации

Иерархия областей действия и приоритеты

Правила маршрутизации организованы по областям действия (scope) с принципом first-match-wins:

Virtual Key (наивысший приоритет)

Team

Customer

Global (низший приоритет, применяется ко всем)

Как это работает:

  1. Когда приходит запрос с виртуальным ключом, Meridian строит цепочку scope.
  2. Правила оцениваются по порядку scope (от наивысшего к низшему).
  3. Первое совпавшее правило побеждает — дальнейшие правила не оцениваются.
  4. Внутри одного scope правила сортируются по приоритету (по возрастанию: 0 оценивается раньше 10).
  5. Если ни одно правило не совпало, используется провайдер/модель из исходного запроса без изменений.

Пример:

Виртуальный ключ (vk-123) привязан к команде (team-456),
которая принадлежит клиенту (cust-789)

Порядок оценки:
1. Правила scope = virtual_key (vk-123)
2. Правила scope = team (team-456)
3. Правила scope = customer (cust-789)
4. Правила scope = global

Первое совпадение → решение

Справочник по CEL-выражениям

Доступные переменные

Правила оценивают CEL-выражения в контексте следующих переменных.

Контекст запроса

model          // Запрошенная модель (string)
provider       // Текущий провайдер (string)
request_type   // Тип запроса (chat_completion, embedding, batch, image_generation, moderation, transcription, translation)

Заголовки и параметры

headers["header-name"]     // Заголовок запроса (поиск ключа без учёта регистра)
params["param-name"]       // Query-параметр

Примеры заголовков:

headers["x-tier"] == "premium"
headers["x-api-version"] == "v2"
headers["user-agent"].contains("mobile")

Контекст организации

virtual_key_id             // ID виртуального ключа (string, пустой если ключа нет)
virtual_key_name           // Имя виртуального ключа (string)
team_id                    // ID команды (string, пустой если не в команде)
team_name                  // Имя команды (string)
customer_id                // ID клиента (string)
customer_name              // Имя клиента (string)

Примеры:

team_name == "ml-research"
customer_id == "acme-corp"
virtual_key_name.startsWith("prod-")

Метрики потребления (в процентах: 0–100)

budget_used      // Процент использованного бюджета по провайдеру/модели (0.0–100.0)
tokens_used      // Процент использованного rate limit по токенам (0.0–100.0)
request          // Процент использованного rate limit по запросам (0.0–100.0)

Примеры:

budget_used > 80           // Маршрутизировать в fallback при использовании >80% бюджета
tokens_used < 50           // Использовать быстрого провайдера при <50% токенового лимита
request > 90               // Сменить провайдера при близком к пределу лимите запросов

Операторы и функции CEL

Операторы сравнения

==    // Равно
!=    // Не равно
>     // Больше
<     // Меньше
>=    // Больше или равно
<=    // Меньше или равно

Логические операторы

&&    // AND
||    // OR
!     // NOT

Строковые функции

.startsWith("prefix")      // Начинается с префикса
.endsWith("suffix")        // Заканчивается суффиксом
.contains("substring")     // Содержит подстроку
.matches("regex")          // Соответствует регулярному выражению

Коллекции

"value" in ["item1", "item2", "item3"]    // Проверка вхождения

Примеры выражений

Простые условия

// По заголовку
headers["x-tier"] == "premium"

// По команде
team_name == "research"

// По модели
model == "gpt-4o"

// По типу запроса
request_type == "embedding"

// Маршрут в fallback при высокой загрузке бюджета
budget_used > 80

Сложные условия (несколько критериев)

// Премиум-тариф для команды research
headers["x-tier"] == "premium" && team_name == "research"

// Высокая нагрузка ИЛИ премиум-приоритет
budget_used > 90 || headers["x-priority"] == "high"

// Конкретная команда и модель
team_name == "ml-ops" && model.startsWith("claude-")

// Регион и проверка нагрузки
headers["x-region"] == "us-east" && tokens_used < 75

// Embeddings → дешёвый провайдер при высокой нагрузке бюджета
request_type == "embedding" && budget_used > 50

Сопоставление по шаблону

// Модели, начинающиеся с префикса
model.startsWith("gpt-4")

// Произвольные заголовки
headers["x-environment"] in ["staging", "testing"]

// Соответствие домена email
headers["x-user-email"].contains("@company.com")

// Регулярные выражения
headers["x-app-version"].matches("[0-9]+\\.[0-9]+\\.[0-9]+")

Валидация и обработка ошибок

  • Некорректный синтаксис CEL → правило логируется с предупреждением и пропускается; оценка продолжается.
  • Отсутствует заголовок/параметр → выражение возвращает false (мягкое отсутствие совпадения).
  • Несовпадение типов → логируется с предупреждением, правило пропускается.
  • Пустое выражение → правило всегда совпадает (используйте true / false для явного поведения).

Конфигурация

Раздел правил маршрутизации доступен из панели управления.

Дашборд правил маршрутизации

Дашборд правил маршрутизации

Возможности:

  • список всех правил со scope, приоритетом и статусом включения;
  • фильтрация по scope и scope_id;
  • создание/редактирование/удаление правил;
  • просмотр выражений и таргетов;
  • включение/выключение без удаления;
  • изменение приоритетов перетаскиванием.

Создание / редактирование правила

Диалог создания правила маршрутизации

Поля:

  • Name (обязательное) — уникальное имя правила.
  • Description (опционально) — внутренние пометки.
  • Enabled — включено или выключено.
  • CEL Expression — визуальный конструктор или ручной ввод выражения.
  • Targets (обязательно) — один или несколько взвешенных таргетов; у каждого: Provider (опционально), Model (опционально), API Key (опционально, требует Provider) и Weight (%). Сумма весов должна равняться 1. При нескольких таргетах один выбирается вероятностно на каждый запрос.
  • Fallbacks (опционально) — массив резервных провайдеров.
  • Scope — где применяется правило: global, customer, team, virtual_key.
  • Scope ID — обязателен, если scope не global.
  • Priority — меньше значит раньше (по умолчанию 0).

Визуальный конструктор CEL

В дашборде есть визуальный query-builder для CEL-выражений:

  • Condition Builder — выбор поля, оператора и значения;
  • Logical Operators — комбинирование условий через AND/OR;
  • Manual Mode — переключение на ручное редактирование CEL;
  • Validation — синтаксическая проверка в реальном времени;
  • Conversion — автоматическое преобразование визуального правила в CEL.

Список правил

GET /api/governance/routing-rules

# Опциональные query-параметры:
?scope=global&scope_id=<id>&from_memory=true

Ответ:

{
  "rules": [
    {
      "id": "rule-uuid-123",
      "name": "Premium Tier Route",
      "description": "Route premium users to fast provider",
      "enabled": true,
      "cel_expression": "headers[\"x-tier\"] == \"premium\"",
      "targets": [
        { "provider": "openai", "model": "gpt-4o", "weight": 0.7 },
        { "provider": "azure",  "model": "gpt-4o", "weight": 0.3 }
      ],
      "fallbacks": ["groq/gpt-3.5-turbo"],
      "scope": "global",
      "scope_id": null,
      "priority": 10,
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T10:30:00Z"
    }
  ],
  "count": 1
}

Получение правила

GET /api/governance/routing-rules/{rule_id}

Создание правила

POST /api/governance/routing-rules

Content-Type: application/json

Тело запроса:

{
  "name": "Budget Overflow Route",
  "description": "When budget is high, route to cheaper provider",
  "enabled": true,
  "cel_expression": "budget_used > 85",
  "targets": [
    { "provider": "groq", "weight": 1 }
  ],
  "fallbacks": ["openai/gpt-4o"],
  "scope": "team",
  "scope_id": "team-uuid-456",
  "priority": 5
}

Ответ: 201 Created

{
  "message": "Routing rule created successfully",
  "rule": { /* объект правила */ }
}

Обновление правила

PUT /api/governance/routing-rules/{rule_id}

Content-Type: application/json

Тело запроса (все поля опциональны):

{
  "name": "Updated Rule Name",
  "enabled": false,
  "cel_expression": "budget_used > 90",
  "priority": 20
}

Удаление правила

DELETE /api/governance/routing-rules/{rule_id}

Ответ: 200 OK

{
  "message": "Routing rule deleted successfully"
}

Правила маршрутизации задаются в config.json в секции governance:

Структура:

{
  "governance": {
    "routing_rules": [
      {
        "id": "rule-uuid-123",
        "name": "Premium Tier Route",
        "description": "Route premium users to fast provider",
        "enabled": true,
        "cel_expression": "headers[\"x-tier\"] == \"premium\"",
        "targets": [
          { "provider": "openai", "model": "gpt-4o", "weight": 0.7 },
          { "provider": "azure",  "model": "gpt-4o", "weight": 0.3 }
        ],
        "fallbacks": ["groq/gpt-3.5-turbo"],
        "scope": "global",
        "scope_id": null,
        "priority": 10
      },
      {
        "id": "rule-uuid-456",
        "name": "Budget Overflow Route",
        "description": "Route to cheaper provider when budget is high",
        "enabled": true,
        "cel_expression": "budget_used > 85",
        "targets": [
          { "provider": "groq", "model": "llama-2-70b", "weight": 1 }
        ],
        "fallbacks": [],
        "scope": "team",
        "scope_id": "team-ml-ops",
        "priority": 5
      }
    ]
  }
}

Поля:

  • id (string, генерируется автоматически) — уникальный идентификатор (UUID).
  • name (string, обязательное) — имя правила (уникальное в пределах scope).
  • description (string, опционально) — внутренняя документация.
  • enabled (boolean) — активно ли правило.
  • cel_expression (string) — CEL-выражение для проверки совпадения.
  • targets (array, обязательное) — один или несколько таргетов. У каждого:
    • provider (string, опционально) — целевой провайдер; пропустите, чтобы оставить провайдера из исходного запроса;
    • model (string, опционально) — целевая модель; пропустите, чтобы оставить модель из запроса;
    • key_id (string, опционально) — UUID API-ключа, который нужно зафиксировать; требует заданного provider; пропустите для load-balanced выбора ключа;
    • weight (number, обязательное) — вероятностный вес; сумма весов в правиле должна равняться 1 (например, 0.7 + 0.3 = 1.0).
  • fallbacks (array[string]) — резервные провайдеры в формате "provider/model".
  • scope (string) — global, customer, team или virtual_key.
  • scope_id (string, опционально) — ID соответствующей сущности (null для global).
  • priority (number) — порядок оценки внутри scope (меньше значит раньше).

Загрузка из config.json: правила загружаются автоматически при старте из секции governance. Изменения требуют перезапуска приложения.

Пример с несколькими правилами:

{
  "governance": {
    "routing_rules": [
      {
        "id": "tier-based",
        "name": "Premium Tier Fast Track",
        "enabled": true,
        "cel_expression": "headers[\"x-tier\"] == \"premium\"",
        "targets": [
          { "provider": "openai", "model": "gpt-4o", "weight": 1 }
        ],
        "fallbacks": ["azure/gpt-4o"],
        "scope": "global",
        "priority": 0
      },
      {
        "id": "capacity-failover",
        "name": "Budget Exhaustion Fallback",
        "enabled": true,
        "cel_expression": "budget_used > 90",
        "targets": [
          { "provider": "groq", "model": "llama-2-70b", "weight": 1 }
        ],
        "fallbacks": [],
        "scope": "global",
        "priority": 5
      },
      {
        "id": "team-preference",
        "name": "ML Team Anthropic Route",
        "enabled": true,
        "cel_expression": "team_name == \"ml-research\"",
        "targets": [
          { "provider": "anthropic", "model": "claude-3-opus-20240229", "weight": 1 }
        ],
        "fallbacks": ["bedrock/claude-3-opus"],
        "scope": "team",
        "scope_id": "team-ml-research",
        "priority": 0
      }
    ]
  }
}

Сценарии использования

Когда применять правила маршрутизации:

  • динамическая маршрутизация по заголовкам или параметрам;
  • маршрутизация по нагрузке (fallback при росте бюджета или rate limit);
  • организационная маршрутизация (разные правила для команд и клиентов);
  • A/B-тесты и canary-деплои;
  • условное переопределение провайдера на основе сложной логики.

Сценарий 1: Маршрутизация по тарифу

Маршрутизация запросов в зависимости от тарифа клиента через заголовки:

{
  "name": "Premium Tier Fast Track",
  "cel_expression": "headers[\"x-tier\"] == \"premium\"",
  "targets": [
    { "provider": "openai", "model": "gpt-4o", "weight": 1 }
  ],
  "fallbacks": ["azure/gpt-4o"],
  "scope": "global",
  "priority": 10
}

Сценарий 2: Failover при исчерпании бюджета

Перевод трафика на более дешёвого провайдера при росте использования бюджета:

{
  "name": "Budget Exhaustion Fallback",
  "cel_expression": "budget_used > 90",
  "targets": [
    { "provider": "groq", "model": "llama-2-70b", "weight": 1 }
  ],
  "fallbacks": [],
  "scope": "global",
  "priority": 5
}

Сценарий 3: Маршрутизация по команде

Запросы конкретной команды направляются на её предпочтительного провайдера:

{
  "name": "ML Team Anthropic Preference",
  "cel_expression": "team_name == \"ml-research\"",
  "targets": [
    { "provider": "anthropic", "model": "claude-3-opus-20240229", "weight": 1 }
  ],
  "fallbacks": ["bedrock/claude-3-opus"],
  "scope": "team",
  "scope_id": "team-ml-research-uuid",
  "priority": 0
}

Сценарий 4: Сложная многокритериальная маршрутизация

Сочетание нескольких условий:

{
  "name": "Production Premium Route",
  "cel_expression": "headers[\"x-environment\"] == \"production\" && headers[\"x-priority\"] == \"high\" && tokens_used < 75",
  "targets": [
    { "provider": "openai", "model": "gpt-4o", "weight": 1 }
  ],
  "fallbacks": ["azure/gpt-4o"],
  "scope": "global",
  "priority": 5
}

Сценарий 5: Вероятностное A/B-тестирование

Деление трафика между провайдерами по весам — для canary-деплоев или оптимизации стоимости:

{
  "name": "Split Traffic OpenAI vs Groq",
  "cel_expression": "true",
  "targets": [
    { "provider": "openai", "model": "gpt-4o",        "weight": 0.7 },
    { "provider": "groq",   "model": "llama-3.1-70b", "weight": 0.3 }
  ],
  "scope": "global",
  "priority": 15
}

Каждый запрос, попадающий под это правило, с вероятностью 70 % уходит в OpenAI и с вероятностью 30 % — в Groq. Сумма весов всегда должна быть равна 1.

Сценарий 6: Региональная маршрутизация

Маршрутизация по заголовку региона:

{
  "name": "EU Data Residency",
  "cel_expression": "headers[\"x-region\"] == \"eu\"",
  "targets": [
    { "provider": "azure", "model": "gpt-4o", "weight": 1 }
  ],
  "fallbacks": [],
  "scope": "global",
  "priority": 0
}

Взаимодействие с governance и балансировкой

С governance routing

Правила маршрутизации выполняются до выбора провайдера в governance и могут переопределить его.

Если правило совпало:

1. Правила маршрутизации → оценка CEL (first-match-wins)
2. Совпадение → таргет выбирается вероятностно из массива targets
3. provider/model/key_id/fallbacks переопределяются из выбранного таргета
4. Governance provider_configs → ПРОПУСКАЕТСЯ
5. Балансировка → выбирает оптимальный ключ (если key_id не зафиксирован)

Если ни одно правило не совпало:

1. Правила маршрутизации → оценка CEL
2. Совпадений нет → продолжаем
3. Governance routing → выбор provider/model (взвешенный random)
4. Балансировка → выбирает оптимальный ключ

Пример:

  • Governance настроен: 70 % Azure, 30 % OpenAI.
  • Существует правило budget_used > 85 → groq.
  • Приходит запрос с budget_used = 90 %.
  • Результат: правилом выбран Groq, governance provider_configs игнорируется.

С балансировкой

Правила определяют провайдера до того, как сработает adaptive load balancing:

1. Сначала оцениваются правила → определяют провайдера (если совпало)
   ИЛИ
2. Governance выбирает провайдера (если правил нет)

3. Load Balancing уровня 1 — пропускается (провайдер уже определён правилом или governance)
4. Load Balancing уровня 2 — выбор ключа (по производительности внутри выбранного провайдера)

Ключевой момент. Уровень 2 балансировки (выбор ключа) выполняется всегда, независимо от того, кто определил провайдера — правила или governance. То есть автоматическая оптимизация на уровне ключа работает в обоих случаях.

Цепочка fallback

Правила могут задавать fallback'и, которые подхватываются балансировкой:

{
  "provider": "openai",
  "fallbacks": ["azure/gpt-4o", "groq/gpt-3.5-turbo"]
}

Если OpenAI откажет:

  1. Уровень 2 балансировки оценит ключи Azure.
  2. Если все ключи Azure упадут — пробуется Groq.

Выполнение и производительность

Компиляция CEL

  • Первая оценка — CEL-выражение компилируется в bytecode-программу.
  • Последующие оценки — программа кешируется и переиспользуется.
  • Производительность — оценка кешированной программы быстрая (микросекунды).
  • Память — скомпилированные программы хранятся в памяти до перезапуска Meridian.

Приоритеты и порядок

Правила одного scope оцениваются по возрастанию приоритета:

Priority 0 → Priority 5 → Priority 10 → Priority 100 (first match wins)

Лучшая практика: приоритеты 0–10 — для критичных правил, 100+ — для fallback.

Советы по оптимизации

  1. Сортируйте правила по вероятности срабатывания — часто совпадающие должны идти первыми.
  2. Используйте узкие scope — глобальный scope медленнее (чем уже scope, тем быстрее).
  3. Избегайте дорогих строковых операций== дешевле .matches() с регулярным выражением.
  4. Держите выражения простыми — сложные условия увеличивают время оценки.
  5. Оставляйте промежутки в приоритетах (0, 10, 20) — это упрощает последующее переупорядочивание.

Лучшие практики


Поиск и устранение неполадок

Правило не совпадает

Симптом. Выражение правила корректно, но не срабатывает.

Диагностика:

  1. Проверьте, что правило включено (enabled: true).
  2. Убедитесь, что scope соответствует запросу (проверьте иерархию team/customer виртуального ключа).
  3. Проверьте приоритет правила относительно других в том же scope (меньше — раньше).
  4. Убедитесь, что значения переменных соответствуют ожиданиям. Используйте from_memory=true для отладки.

Решение:

# Получить текущие правила в памяти
GET /api/governance/routing-rules?from_memory=true

# Проверьте, выставлены ли нужные переменные
# Например, действительно ли team_name установлен?
# Помните: ключи заголовков в CEL должны быть в нижнем регистре.

Ошибка компиляции выражения

Симптом: Failed to compile rule: invalid CEL syntax.

Частые причины:

  • незакрытые кавычки: headers["x-tier (нет закрывающей кавычки);
  • недопустимые операторы: headers["x"] ?? (это не стандартный CEL);
  • ошибки экранирования: headers["x-\type"].

Решение:

  1. Используйте визуальный CEL-конструктор, чтобы избежать опечаток.
  2. Тестируйте выражение по частям.
  3. Сверяйтесь со списком операторов выше.
  4. Сложные выражения оборачивайте в скобки: (A && B) || (C && D).

Выбран не тот провайдер

Симптом. Запрос ушёл к неожиданному провайдеру.

Диагностика:

  1. Совпали ли несколько правил? (first-match-wins означает, что более раннее правило побеждает.)
  2. Был ли провайдер уже выбран governance? (Проверьте иерархию scope.)
  3. Изменила ли балансировка ключ? (Правило задаёт провайдера, балансировка — ключ.)

Решение:

  1. Понизьте приоритет совпадающих правил.
  2. Проверьте порядок precedence по scope (Virtual Key > Team > Customer > Global).
  3. Убедитесь, что нет другого правила с более низким приоритетом, которое срабатывает раньше.
  4. Изучите логи: [RoutingEngine] Rule matched! Decision: provider=....

Заголовок или параметр не найден

Симптом: ошибка no such key при оценке CEL.

Это нормальное поведение — Meridian трактует отсутствующие заголовки как «не совпадает»:

headers["x-optional"] == "value"  // Возвращает false, если заголовка нет

Чтобы явно проверить наличие заголовка:

headers["x-optional"] != ""  // True только если заголовок есть и не пустой

Отладка через логи

Включите debug-логи, чтобы увидеть оценку правил:

[RoutingEngine] Starting rule evaluation for provider=openai, model=gpt-4o
[RoutingEngine] Scope chain: [virtual_key(vk-123) team(team-456) customer(cust-789) global]
[RoutingEngine] Evaluating scope=virtual_key, scopeID=vk-123, ruleCount=2
[RoutingEngine] Evaluating rule: id=rule-1, name=Premium Route, expression=headers["x-tier"]=="premium"
[RoutingEngine] Rule rule-1 evaluation result: matched=false
[RoutingEngine] Evaluating rule: id=rule-2, name=Budget Fallback, expression=budget_used>80
[RoutingEngine] Rule rule-2 evaluation result: matched=true
[RoutingEngine] Rule matched! Selected target: provider=groq, model=gpt-3.5-turbo (weight=1), fallbacks=[azure/gpt-4o]

Справочник API

Примеры запросов и ответов

Создание правила по нагрузке

curl -X POST http://localhost:8080/api/governance/routing-rules \
  -H "Content-Type: application/json" \
  -d '{
    "name": "High Budget Fallback",
    "description": "Switch to cheaper provider when budget >85%",
    "enabled": true,
    "cel_expression": "budget_used > 85",
    "targets": [
      { "provider": "groq", "model": "llama-2-70b", "weight": 1 }
    ],
    "fallbacks": ["openai/gpt-3.5-turbo"],
    "scope": "global",
    "priority": 10
  }'

Создание правила с вероятностным сплитом

curl -X POST http://localhost:8080/api/governance/routing-rules \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Premium Tier Split",
    "cel_expression": "headers[\"x-tier\"] == \"premium\"",
    "targets": [
      { "provider": "openai", "model": "gpt-4o", "weight": 0.7 },
      { "provider": "azure",  "model": "gpt-4o", "weight": 0.3 }
    ],
    "scope": "global",
    "priority": 5
  }'

Создание правила с зафиксированным API-ключом

curl -X POST http://localhost:8080/api/governance/routing-rules \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pin Production Key for Premium Tier",
    "description": "Always use the dedicated production key for premium requests",
    "enabled": true,
    "cel_expression": "headers[\"x-tier\"] == \"premium\"",
    "targets": [
      {
        "provider": "openai",
        "model": "gpt-4o",
        "key_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "weight": 1
      }
    ],
    "scope": "global",
    "priority": 5
  }'

Список правил по team scope

curl http://localhost:8080/api/governance/routing-rules \
  -H "Authorization: Bearer your-token" \
  -G \
  --data-urlencode "scope=team" \
  --data-urlencode "scope_id=team-uuid-123"

Получение in-memory правил (отладка)

curl http://localhost:8080/api/governance/routing-rules?from_memory=true \
  -H "Authorization: Bearer your-token"

Содержание

ОбзорКак это работаетПоток обработки запросаИерархия областей действия и приоритетыСправочник по CEL-выражениямДоступные переменныеКонтекст запросаЗаголовки и параметрыКонтекст организацииМетрики потребления (в процентах: 0–100)Операторы и функции CELОператоры сравненияЛогические операторыСтроковые функцииКоллекцииПримеры выраженийПростые условияСложные условия (несколько критериев)Сопоставление по шаблонуВалидация и обработка ошибокКонфигурацияВизуальный конструктор CELСписок правилПолучение правилаСоздание правилаОбновление правилаУдаление правилаСценарии использованияСценарий 1: Маршрутизация по тарифуСценарий 2: Failover при исчерпании бюджетаСценарий 3: Маршрутизация по командеСценарий 4: Сложная многокритериальная маршрутизацияСценарий 5: Вероятностное A/B-тестированиеСценарий 6: Региональная маршрутизацияВзаимодействие с governance и балансировкойС governance routingС балансировкойЦепочка fallbackВыполнение и производительностьКомпиляция CELПриоритеты и порядокСоветы по оптимизацииЛучшие практикиПоиск и устранение неполадокПравило не совпадаетОшибка компиляции выраженияВыбран не тот провайдерЗаголовок или параметр не найденОтладка через логиСправочник APIПримеры запросов и ответовСоздание правила по нагрузкеСоздание правила с вероятностным сплитомСоздание правила с зафиксированным API-ключомСписок правил по team scopeПолучение in-memory правил (отладка)