← Cloudflare Queues / queues / tutorials
Обработка ограничений частоты запросов внешних API
В этом руководстве описано, как использовать Queues для обработки ограничений частоты запросов внешних API на примере приложения, которое отправляет уведомления по электронной почте с помощью Resend ↗. Однако этот подход можно использовать для обработки ограничений скорости запросов любого внешнего API.
Resend является сервисом, который позволяет отправлять электронные письма из вашего приложения через API. У Resend по умолчанию установлен лимит скорости ↗ в размере двух запросов в секунду. Вы будете использовать Queues, чтобы соблюдать это ограничение скорости Resend.
Предварительные требования
- Зарегистрируйтесь для получения Аккаунт Cloudflare ↗.
- Установка
Node.js↗.
менеджер версий Node.js
Используйте менеджер версий Node, например Volta ↗ или nvm ↗ чтобы избежать проблем с правами доступа и переключать версии Node.js. Wrangler, о котором пойдёт речь далее в этом руководстве, требует версию Node 16.17.0 или более поздней версии.
-
Зарегистрируйтесь для Resend ↗ и создать ключ API, следуя руководству на Документация Resend ↗.
-
Кроме того, вам потребуется доступ к Cloudflare Queues.
Стоимость Queues уже включена в ежемесячную стоимость подписки на тарифный план Workers Paid, а плата взимается на основе операций с вашими очередями. Ограниченная версия Queues также доступна на тарифе Workers Free. См. Цены для дополнительных сведений.
Прежде чем использовать Queues, необходимо включить её через панель управления Cloudflare ↗. Для использования Queues необходим тарифный план Workers Paid.
Чтобы включить Queues:
-
На панели управления Cloudflare перейдите к разделу Queues страницу.
Перейдите в Queues ↗ -
Выберите Включить Queues.
1. Создание нового приложения Workers
Для начала создайте приложение Worker с помощью create-cloudflare CLI ↗. Откройте окно терминала и выполните следующую команду:
npm create cloudflare@latest -- resend-rate-limit-queueДля настройки выберите следующие параметры:
- Для С чего вы хотите начать?, выберите
Hello World example. - Для Какой шаблон вы хотите использовать?, выберите
Worker only. - Для Какой язык вы хотите использовать?, выберите
TypeScript. - Для Хотите использовать git для контроля версий?, выберите
Yes. - Для Хотите развернуть приложение?, выберите
No(мы внесём некоторые изменения перед развёртыванием).
Затем перейдите в только что созданный каталог:
cd resend-rate-limit-queue2. Настройка очереди
Вам нужно создать очередь и привязку к вашему Worker. Выполните следующую команду, чтобы создать очередь с именем rate-limit-queue:
npx wrangler queues create rate-limit-queueCreating queue rate-limit-queue.
Created queue rate-limit-queue.Добавление привязок Queue в конфигурационный файл Wrangler
В файле Wrangler добавьте следующее:
{
"queues": {
"producers": [
{
"binding": "EMAIL_QUEUE",
"queue": "rate-limit-queue"
}
],
"consumers": [
{
"queue": "rate-limit-queue",
"max_batch_size": 2,
"max_batch_timeout": 10,
"max_retries": 3
}
]
}
}[[queues.producers]]
binding = "EMAIL_QUEUE"
queue = "rate-limit-queue"
[[queues.consumers]]
queue = "rate-limit-queue"
max_batch_size = 2
max_batch_timeout = 10
max_retries = 3Важно указать max_batch_size для очереди потребителя, равное двум, важно, поскольку API Resend по умолчанию ограничивает скорость двумя запросами в секунду. Такой размер пакета позволяет очереди обрабатывать сообщения пакетами по два. Если размер пакета меньше двух, очередь будет ждать 10 секунд, чтобы собрать следующее сообщение. Если больше сообщений нет, очередь обработает сообщение, находящееся в пакете. Дополнительную информацию см. на документация по пакетной обработке, повторным попыткам и задержкам
Итоговый файл Wrangler должен выглядеть примерно так, как в примере ниже.
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "resend-rate-limit-queue",
"main": "src/index.ts",
// Set this to today's date
"compatibility_date": "2026-08-28",
"compatibility_flags": [
"nodejs_compat"
],
"queues": {
"producers": [
{
"binding": "EMAIL_QUEUE",
"queue": "rate-limit-queue"
}
],
"consumers": [
{
"queue": "rate-limit-queue",
"max_batch_size": 2,
"max_batch_timeout": 10,
"max_retries": 3
}
]
}
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "resend-rate-limit-queue"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-08-28"
compatibility_flags = [ "nodejs_compat" ]
[[queues.producers]]
binding = "EMAIL_QUEUE"
queue = "rate-limit-queue"
[[queues.consumers]]
queue = "rate-limit-queue"
max_batch_size = 2
max_batch_timeout = 10
max_retries = 33. Добавление привязок в окружение
Добавление привязок в интерфейс окружения, в worker-configuration.d.ts, чтобы TypeScript корректно типизировал привязки. Тип очереди задаётся как Queue<Message>, где Message определяется на следующем шаге.
interface Env {
EMAIL_QUEUE: Queue<Message>;
}4. Отправка сообщения в очередь
Приложение отправляет сообщение в очередь, когда Worker получает запрос. Для простоты в качестве сообщения в очередь будет отправляться адрес электронной почты. Новое сообщение будет отправлено в очередь с задержкой в одну секунду.
export default {
async fetch(req, env, ctx): Promise<Response> {
try {
await env.EMAIL_QUEUE.send(
{ email: await req.text() },
{ delaySeconds: 1 },
);
return new Response("Success!");
} catch (e) {
return new Response("Error!", { status: 500 });
}
},
} satisfies ExportedHandler<Env>;Это будет принимать запросы на любой подпуть и передавать тело запроса. Предполагается, что тело запроса содержит только адрес электронной почты. В продакшене следует проверять, что запрос был POST . Кроме того, не следует отправлять такие конфиденциальные данные (адрес электронной почты) напрямую в очередь. Вместо этого можно отправить в очередь сообщение с уникальным идентификатором пользователя. Затем очередь потребителя сможет использовать этот идентификатор, чтобы найти адрес электронной почты в базе данных и отправить письмо.
5. Обработка сообщений в очереди
После отправки сообщения в очередь его обрабатывает Worker-потребитель. Он обрабатывает сообщение и отправляет письмо.
Поскольку вы ещё не настроили Resend, сообщение будет выводиться в консоль. После настройки Resend вы сможете использовать его для отправки письма.
Добавьте queue() обработчик, как показано ниже:
interface Message {
email: string;
}
export default {
async fetch(req, env, ctx): Promise<Response> {
try {
await env.EMAIL_QUEUE.send(
{ email: await req.text() },
{ delaySeconds: 1 },
);
return new Response("Success!");
} catch (e) {
return new Response("Error!", { status: 500 });
}
},
async queue(batch, env, ctx): Promise<void> {
for (const message of batch.messages) {
try {
console.log(message.body.email);
// After configuring Resend, you can send email
message.ack();
} catch (e) {
console.error(e);
message.retry({ delaySeconds: 5 });
}
}
},
} satisfies ExportedHandler<Env, Message>;Приведённый выше queue() обработчик выведет адрес электронной почты в консоль и отправит письмо. Он также повторит обработку сообщения, если отправка письма завершится ошибкой. delaySeconds установлен равным пяти секундам, чтобы не отправлять письмо слишком быстро.
Чтобы протестировать приложение, выполните следующую команду:
npm run devИспользуйте следующую команду cURL, чтобы отправить запрос к приложению:
curl -X POST -d "[email protected]" http://localhost:8787/[wrangler:inf] POST / 200 OK (2ms)
QueueMessage {
attempts: 1,
body: { email: '[email protected]' },
timestamp: 2024-09-12T13:48:07.236Z,
id: '72a25ff18dd441f5acb6086b9ce87c8c'
}6. Настройка Resend
Чтобы вызвать Resend API, необходимо настроить ключ Resend API. Создайте .dev.vars файл в корне проекта и добавьте в него следующее:
RESEND_API_KEY='your-resend-api-key'Замените your-resend-api-key на ваш фактический ключ API Resend.
Далее обновите Env интерфейс в worker-configuration.d.ts чтобы включить RESEND_API_KEY переменную.
interface Env {
EMAIL_QUEUE: Queue<Message>;
RESEND_API_KEY: string;
}Наконец, установите resend пакет ↗ с помощью следующей команды:
npm i resendТеперь вы можете использовать RESEND_API_KEY переменную в коде.
7. Отправка письма через Resend
В вашем src/index.ts файле импортируйте пакет Resend и обновите queue() обработчик для отправки письма.
import { Resend } from "resend";
interface Message {
email: string;
}
export default {
async fetch(req, env, ctx): Promise<Response> {
try {
await env.EMAIL_QUEUE.send(
{ email: await req.text() },
{ delaySeconds: 1 },
);
return new Response("Success!");
} catch (e) {
return new Response("Error!", { status: 500 });
}
},
async queue(batch, env, ctx): Promise<void> {
// Initialize Resend
const resend = new Resend(env.RESEND_API_KEY);
for (const message of batch.messages) {
try {
console.log(message.body.email);
// send email
const sendEmail = await resend.emails.send({
from: "[email protected]",
to: [message.body.email],
subject: "Hello World",
html: "<strong>Sending an email from Worker!</strong>",
});
// check if the email failed
if (sendEmail.error) {
console.error(sendEmail.error);
message.retry({ delaySeconds: 5 });
} else {
// if success, ack the message
message.ack();
}
message.ack();
} catch (e) {
console.error(e);
message.retry({ delaySeconds: 5 });
}
}
},
} satisfies ExportedHandler<Env, Message>; queue() обработчик теперь отправит письмо через Resend API. Он также проверяет, не завершилась ли отправка письма ошибкой, и в этом случае повторит обработку сообщения.
Итоговый скрипт приведён ниже:
import { Resend } from "resend";
interface Message {
email: string;
}
export default {
async fetch(req, env, ctx): Promise<Response> {
try {
await env.EMAIL_QUEUE.send(
{ email: await req.text() },
{ delaySeconds: 1 },
);
return new Response("Success!");
} catch (e) {
return new Response("Error!", { status: 500 });
}
},
async queue(batch, env, ctx): Promise<void> {
// Initialize Resend
const resend = new Resend(env.RESEND_API_KEY);
for (const message of batch.messages) {
try {
// send email
const sendEmail = await resend.emails.send({
from: "[email protected]",
to: [message.body.email],
subject: "Hello World",
html: "<strong>Sending an email from Worker!</strong>",
});
// check if the email failed
if (sendEmail.error) {
console.error(sendEmail.error);
message.retry({ delaySeconds: 5 });
} else {
// if success, ack the message
message.ack();
}
} catch (e) {
console.error(e);
message.retry({ delaySeconds: 5 });
}
}
},
} satisfies ExportedHandler<Env, Message>;Чтобы протестировать приложение, запустите сервер разработки с помощью следующей команды:
npm run devИспользуйте следующую команду cURL, чтобы отправить запрос к приложению:
curl -X POST -d "[email protected]" http://localhost:8787/В панели управления Resend вы должны увидеть, что письмо было отправлено на указанный адрес электронной почты.
8. Развёртывание Worker
Чтобы развернуть Worker, выполните следующую команду:
npx wrangler deployНаконец, добавьте API-ключ Resend с помощью следующей команды:
npx wrangler secret put RESEND_API_KEYВведите значение вашего ключа API. Ваш ключ API будет добавлен в проект. Теперь вы можете использовать RESEND_API_KEY переменную в коде.
Вы успешно создали Worker, который может отправлять электронные письма через Resend API с соблюдением ограничений по частоте запросов.
Чтобы протестировать Worker, можно использовать следующий запрос cURL. Замените <YOUR_WORKER_URL> на URL-адрес развёрнутого Worker.
curl -X POST -d "[email protected]" <YOUR_WORKER_URL>См. репозиторий GitHub ↗ полный код для этого руководства. Если вы используете Hono ↗, вы можете обратиться к Пример с Hono ↗.