Управление ограничениями запросов и расходов

CloudflareBeginner
Практиковаться сейчас

Введение

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

Вы создадите один временный аутентифицированный AI Gateway. Он разрешит только два запроса в коротком скользящем окне, поэтому три небольших запроса позволят продемонстрировать ответ 429 Too Many Requests без создания лишнего трафика к модели. После завершения окна вы убедитесь, что обычный инференс снова работает. Также вы добавите дневное ограничение расходов в размере пяти долларов, применимое к Workers AI и выбранной модели. Вместо того чтобы тратить деньги до исчерпания бюджета, вы прочитаете сохранённое правило.

Если вы открыли этот курс напрямую, сначала выполните лабораторную работу Connect LabEx to Your Cloudflare Account. В ней описаны терминал LabEx, авторизация устройства Wrangler и идентификатор аккаунта. Также сначала завершите лабораторную работу Route Inference Through a Gateway, поскольку в этой работе повторно используются созданные там отдельные границы шлюза и авторизации источника.

В лабораторной работе используется размещённая Cloudflare модель @cf/meta/llama-3.3-70b-instruct-fp8-fast со стандартной тарификацией Workers AI. Workers Paid, Unified Billing и учётные данные внешнего провайдера не требуются. До модели должны дойти только три небольших запроса. Если общая дневная квота Workers AI недоступна, остановитесь и не повторяйте запросы многократно.

В процессе настройки устанавливаются Node.js 22.22.0 и локальный Wrangler 4.132.0 в /home/labex/project/ai-gateway-limits. Подготавливаются независимые проверки только для чтения, но Wrangler не авторизуется, шлюз не создаётся, токен не создаётся и трафик к модели не отправляется. После завершения работы LabEx уничтожит виртуальную машину. Тем не менее вы удалите облачный шлюз и токен самостоятельно, поскольку уничтожение виртуальной машины не удаляет удалённые ресурсы.

Авторизуйте виртуальную машину и задайте имена эксперимента

На этом шаге вы подключите новую виртуальную машину к учебному аккаунту и сохраните уникальные имена принадлежащих вам ресурсов.

Каждая лабораторная работа LabEx начинается в новой виртуальной машине. Авторизация этой виртуальной машины позволит Wrangler вызывать Workers AI в вашем учебном аккаунте; сам шлюз при этом ещё не создаётся.

Перейдите в подготовленный проект, проверьте закреплённую версию CLI и запустите авторизацию устройства:

cd /home/labex/project/ai-gateway-limits
npx wrangler --version
npx wrangler login --device --browser=false --scopes account:read user:read ai:write

Откройте показанную ссылку, введите код и авторизуйте нужный учебный аккаунт. Затем просмотрите структурированные данные об идентификаторе:

npx wrangler whoami --json

Ожидайте Wrangler 4.132.0 и loggedIn: true. Замените YOUR_ACCOUNT_ID фактическим 32-символьным идентификатором нужного аккаунта:

GATEWAY_ID="labex-c09-g04-$(openssl rand -hex 6)"
TOKEN_NAME="$GATEWAY_ID-token"
cat > .labex/state.json <<JSON
{
  "accountId": "YOUR_ACCOUNT_ID",
  "gatewayId": "$GATEWAY_ID",
  "tokenName": "$TOKEN_NAME"
}
JSON
cat .labex/state.json

Эти идентификаторы не являются секретами. Сохранение идентификаторов гарантирует, что все последующие операции чтения и очистки будут обращаться только к временным ресурсам этой лабораторной работы.

Создайте шлюз с коротким ограничением запросов

На этом шаге вы настроите общий для шлюза счётчик запросов, который безопасно продемонстрирует защиту от всплеска трафика.

Ограничение частоты запросов — это счётчик, работающий в заданном временном окне. В этой лабораторной работе используется скользящее окно: в каждый момент AI Gateway просматривает предыдущие 20 секунд. После двух запросов за этот период следующий запрос отклоняется с HTTP-ответом 429 до того, как достигнет Workers AI.

Откройте Cloudflare Dashboard и выберите AI → AI Gateway → Create a custom gateway. Используйте сохранённый gatewayId. Оставьте включёнными Collect Logs и Authenticated Gateway. Включите Rate Limit Requests, выберите Change и задайте:

  • лимит: 2 запроса;
  • интервал: 20 секунд;
  • метод: sliding.

Оставьте кэширование и повторы отключёнными. Для тарификации Workers AI оставьте режим Standard, затем создайте шлюз. Сначала созданная политика запросов создаёт стабильный ресурс, к которому позже можно добавить отдельную политику расходов.

Добавьте ограничение расходов и проверьте его область действия

На этом шаге вы добавите к тому же шлюзу бюджет расходов и точно ограничите запросы, которые к нему относятся.

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

Откройте вкладку Settings нового шлюза. Включите Spend Limits, выберите Add rule и настройте одно правило:

  • лимит расходов: $5;
  • окно: 1 day;
  • метод: Sliding;
  • фильтр провайдера: workers-ai;
  • фильтр модели: meta/llama-3.3-70b-instruct-fp8-fast.

Сохраните правило, затем проверьте оба ограничения. Поле модели использует формат author/model, поскольку провайдер уже выбран отдельно; в последующем URL инференса по-прежнему используется полное имя Workers AI, начинающееся с @cf/.

В настройках шлюза отображаются скользящее ограничение в два запроса и одно включённое правило ограничения расходов

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

Откройте My Profile → API Tokens, выберите Create Token → Create Custom Token и используйте сохранённое значение tokenName. Добавьте два разрешения аккаунта: AI Gateway — Edit и AI Gateway — Run, затем укажите только нужный учебный аккаунт. Разрешение Edit позволяет лабораторной работе прочитать и позже удалить именно этот шлюз; разрешение Run используется для авторизации трафика инференса. Отдельные учётные данные Workers AI для источника предоставляет Wrangler.

Проверьте сводку и создайте токен. Cloudflare покажет его один раз внутри команды проверки. Скопируйте только значение токена после Bearer, а не окружающую команду curl, и сохраните его с помощью скрытого ввода:

bash -c '
while :; do
  read -ersp "Paste the AI Gateway token: " GATEWAY_TOKEN
  printf "\n"
  [ -n "$GATEWAY_TOKEN" ] && break
  printf "Token cannot be empty; paste it again.\n" >&2
done
umask 077
printf "%s" "$GATEWAY_TOKEN" > .labex/gateway-token
unset GATEWAY_TOKEN
chmod 600 .labex/gateway-token
'

Прочитайте важные несекретные поля через API управления:

ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS \
  -H "Authorization: Bearer $GATEWAY_TOKEN" \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
  > .labex/gateway.json
unset GATEWAY_TOKEN
node - <<'NODE'
const b=require('./.labex/gateway.json'), g=b.result||{}, spend=g.spend_limits||{};
console.log(JSON.stringify({
  success:b.success,
  id:g.id,
  rate:{limit:g.rate_limiting_limit,interval:g.rate_limiting_interval,technique:g.rate_limiting_technique},
  spend_limits:{enabled:spend.enabled,rules:spend.rules}
},null,2));
NODE

Ожидайте правило ограничения частоты: два запроса за 20 секунд со скользящим окном, а также одно включённое дневное правило расходов в размере пяти долларов с фильтрами провайдера и модели. Эта проверка подтверждает конфигурацию, но не означает, что бюджет уже израсходован.

Наблюдайте отклонение запросов при трёх вызовах

На этом шаге вы отправите три небольших запроса, чтобы проверить политику подсчёта запросов без создания большого всплеска трафика.

Теперь отправьте три последовательных небольших запроса. Первые два будут разрешены. Третий должен получить ответ 429 и не достигнуть модели. Это безопаснее и дешевле, чем создавать большой всплеск трафика.

Сохраните короткоживущий токен Wrangler для авторизации Workers AI на уровне источника:

umask 077
npx wrangler auth token --json \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).token))' \
  > .labex/upstream-token
chmod 600 .labex/upstream-token

Отправьте три вызова. Каждый из них содержит синтетические метаданные, чтобы запросы было легко найти в журналах; само правило расходов сопоставляет их по фильтрам провайдера Workers AI и модели:

ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
MODEL='@cf/meta/llama-3.3-70b-instruct-fp8-fast'
GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(cat .labex/upstream-token)
for NUMBER in 1 2 3; do
  METADATA=$(printf '{"lab":"g04-limits","request":"burst-%s","synthetic":true}' "$NUMBER")
  STATUS=$(curl --http1.1 -sS \
    -o ".labex/burst-$NUMBER-response.json" -w '%{http_code}' \
    -H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
    -H "Authorization: Bearer $UPSTREAM_TOKEN" \
    -H "cf-aig-metadata: $METADATA" \
    -H 'Content-Type: application/json' \
    --data "{\"prompt\":\"Reply with the number $NUMBER.\",\"max_tokens\":4}" \
    "https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
  printf '%s\n' "$STATUS" | tee ".labex/burst-$NUMBER-status.txt"
done
unset GATEWAY_TOKEN UPSTREAM_TOKEN METADATA

Ожидайте:

200
200
429

Ответ 429 означает успешную работу защиты. Запрос был остановлен на шлюзе, поэтому он не создал дополнительный инференс модели и не увеличил счётчик расходов.

Дождитесь восстановления после скользящего окна

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

Ограничение частоты должно защищать от всплесков, но не отключать приложение навсегда. Подождите немного дольше 20-секундного окна, затем отправьте ещё один небольшой запрос:

sleep 22
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
MODEL='@cf/meta/llama-3.3-70b-instruct-fp8-fast'
GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(cat .labex/upstream-token)
STATUS=$(curl --http1.1 -sS \
  -o .labex/recovery-response.json -w '%{http_code}' \
  -H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
  -H "Authorization: Bearer $UPSTREAM_TOKEN" \
  -H 'cf-aig-metadata: {"lab":"g04-limits","request":"recovery","synthetic":true}' \
  -H 'Content-Type: application/json' \
  --data '{"prompt":"Reply only with recovered.","max_tokens":4}' \
  "https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset GATEWAY_TOKEN UPSTREAM_TOKEN
printf '%s\n' "$STATUS" | tee .labex/recovery-status.txt
node -e 'const b=require("./.labex/recovery-response.json"); console.log(b.result?.response ?? b.result)'

Ожидайте HTTP 200 и короткий сгенерированный ответ. Восстановление подтверждает, что ответ 429 был вызван настроенным временным окном, а не неверными учётными данными или неисправной моделью.

Сопоставьте политику с данными в Dashboard

На этом шаге вы сопоставите результаты API и HTTP с ограничениями и журналами, отображаемыми в Dashboard.

Вернитесь в AI → AI Gateway, выберите сохранённый шлюз и откройте Settings. Убедитесь, что ограничение частоты по-прежнему задаёт два запроса, 20 секунд и скользящий режим. В разделе Spend Limits проверьте единственное правило: расходы в размере пяти долларов, скользящее однодневное окно и фильтры провайдера и модели.

В выбранном шлюзе отображаются сохранённые ограничения частоты запросов и ограничение расходов с заданной областью действия

Затем откройте Logs. После обычной задержки распространения журналов там должны появиться два первоначальных успешных запроса и восстановленный запрос. Третий отклонённый запрос может отображаться иначе, поскольку он остановился до инференса у провайдера; сохранённый HTTP-статус является достоверным подтверждением ограничения частоты.

Журналы шлюза показывают только небольшие разрешённые вызовы Workers AI во время проверки ограничения частоты

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

Удалите временный шлюз

На этом шаге вы удалите только шлюз, указанный в инвентаре лабораторной работы, и подтвердите его отсутствие, пока авторизация ещё доступна.

Удалите шлюз, пока токен управления ещё может подтвердить, что нужный ресурс действительно исчез:

ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS -X DELETE \
  -H "Authorization: Bearer $GATEWAY_TOKEN" \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const b=JSON.parse(s);if(!b.success)process.exit(1);console.log("gateway deletion accepted")})'
unset GATEWAY_TOKEN

GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS \
  -H "Authorization: Bearer $GATEWAY_TOKEN" \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways" \
  > .labex/gateways-after-delete.json
unset GATEWAY_TOKEN
node -e 'const b=require("./.labex/gateways-after-delete.json"),id=process.argv[1],found=(b.result||[]).some(g=>g.id===id);console.log("gateway absent:",!found);if(found)process.exit(1)' "$GATEWAY_ID"

Ожидайте gateway absent: true. Проверка авторизованного списка отличает настоящее удаление от сетевой ошибки или потери доступа к странице.

Отзовите токен и выйдите из системы

На этом шаге вы отзовёте оставшийся токен Dashboard, удалите обе копии токенов на виртуальной машине и отключите Wrangler.

В Cloudflare Dashboard откройте My Profile → API Tokens. Найдите сохранённый tokenName, откройте Actions, выберите Delete, проверьте подтверждение и удалите только этот токен. Теперь его можно безопасно отозвать, поскольку удаление шлюза уже подтверждено.

Удалите обе временные копии токенов и отключите Wrangler:

shred -u .labex/gateway-token .labex/upstream-token
npx wrangler logout
npx wrangler whoami --json || true
test ! -e .labex/gateway-token -a ! -e .labex/upstream-token \
  && echo "local token files removed"

Ожидайте loggedIn: false и local token files removed. Сеанс Dashboard является отдельным и останется активным. После завершения лабораторной работы LabEx уничтожит эту временную виртуальную машину, а не сохранит её.

Итоги

Вы применили два взаимодополняющих ограничения AI Gateway. Скользящее окно на два запроса отклонило третий небольшой запрос с HTTP-ответом 429, а после завершения окна автоматически снова разрешило трафик. Отдельное дневное правило расходов в размере пяти долларов было ограничено Workers AI и одной моделью. Его сохранённая конфигурация была проверена без лишнего использования модели.

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