跳转到内容
搜索文档

处理外部 API 的速率限制

如何使用 Queues 处理外部 API 速率限制的示例。

最后更新 查看 MarkdownAgent 设置

本教程说明如何使用 Queues 通过构建使用 Resend ↗ 发送邮件通知的应用程序来处理外部 API 的速率限制。但是,您可以使用此模式处理任何外部 API 的速率限制。

Resend 是一项允许您通过 API 从应用程序发送邮件的服务。Resend 默认速率限制 ↗为每秒两次请求。您将使用 Queues 来处理 Resend 的速率限制。

前提条件

  1. 注册 Cloudflare 账户 ↗。
  2. 安装 Node.js ↗。

Node.js 版本管理器

使用 Volta ↗ 或 nvm ↗ 等 Node 版本管理器,以避免权限问题并切换 Node.js 版本。本指南后续将介绍的 Wrangler 需要 Node 版本 16.17.0 或更高。

  1. 注册 Resend ↗ 并按照 Resend 文档 ↗ 上的指南生成 API 密钥。

  2. 此外,您还需要访问 Cloudflare Queues。

Queues 包含在 Workers Paid 计划的月度订阅费用中,并根据对 Queues 的操作计费。Workers Free 计划也提供有限版本的 Queues。有关更多详情,请参阅定价。

在使用 Queues 之前,您必须通过 Cloudflare 仪表板 ↗启用它。您需要 Workers Paid 计划才能启用 Queues。

要启用 Queues:

  1. 在 Cloudflare 仪表板中,前往 Queues 页面。

    Go to Queues ↗
  2. 选择 Enable Queues(启用 Queues)。

1. 创建新的 Workers 应用程序

要开始使用,请使用 create-cloudflare CLI ↗ 创建 Worker 应用程序。打开终端窗口并运行以下命令:

npm create cloudflare@latest -- resend-rate-limit-queue

进行设置时,请选择以下选项:

  • 对于 What would you like to start with?,选择 Hello World example。
  • 对于 Which template would you like to use?,选择 Worker only。
  • 对于 Which language do you want to use?,选择 TypeScript。
  • 对于 Do you want to use git for version control?,选择 Yes。
  • 对于 Do you want to deploy your application?,选择 No(部署前我们还会做一些修改)。

然后,进入新创建的目录:

cd resend-rate-limit-queue

2. 设置 Queue

您需要创建 Queue 并将其绑定到 Worker。运行以下命令创建名为 rate-limit-queue 的 Queue:

Create a Queuesh
npx wrangler queues create rate-limit-queue
Creating queue rate-limit-queue.
Created queue rate-limit-queue.

将 Queue 绑定添加到 Wrangler 配置文件

In your Wrangler file, add the following:

{
	"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 为 2 很重要,因为 Resend API 默认速率限制为每秒两次请求。此批大小允许队列以 2 的批次大小处理消息。若批大小小于 2,队列将等待 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-17",
	"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-17"
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 = 3

3. 将绑定添加到环境

在 worker-configuration.d.ts 中将绑定添加到环境接口,以便 TypeScript 正确类型化绑定。队列类型为 Queue<Message>,其中 Message 在下一步中定义。

worker-configuration.d.tsts
interface Env {
	EMAIL_QUEUE: Queue<Message>;
}

4. 向队列发送消息

当 Worker 收到请求时,应用程序将向队列发送消息。为简单起见,您将向队列发送电子邮件地址作为消息。新消息将以 1 秒的延迟发送到队列。

src/index.tsts
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 处理。消费者 Worker 将处理消息并发送邮件。

由于您尚未配置 Resend,您将把消息记录到控制台。配置 Resend 后,您将使用它发送邮件。

按如下所示添加 queue() 处理程序:

src/index.tsts
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 设置为 5 秒,以避免发送邮件过快。

要测试应用程序,请运行以下命令:

Start the development serversh
npm run dev

使用以下 cURL 命令向应用程序发送请求:

Test with a cURL requestsh
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 文件并添加以下内容:

.dev.varstxt
RESEND_API_KEY='your-resend-api-key'

将 your-resend-api-key 替换为您的实际 Resend API 密钥。

接下来,在 worker-configuration.d.ts 中更新 Env 接口以包含 RESEND_API_KEY 变量。

worker-configuration.d.tsts
interface Env {
	EMAIL_QUEUE: Queue<Message>;
	RESEND_API_KEY: string;
}

最后,使用以下命令安装 resend 包 ↗:

npm i resend

您现在可以在代码中使用 RESEND_API_KEY 变量。

7. 使用 Resend 发送邮件

在 src/index.ts 文件中,导入 Resend 包并更新 queue() 处理程序以发送邮件。

src/index.tsts
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 发送邮件。它还会检查发送邮件是否失败并将重试消息。

最终脚本如下:

src/index.tsts
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>;

要测试应用程序,使用以下命令启动开发服务器:

Start the development serversh
npm run dev

使用以下 cURL 命令向应用程序发送请求:

Test with a cURL requestsh
curl -X POST -d "[email protected]" http://localhost:8787/

在 Resend 仪表板上,您应看到邮件已发送到提供的电子邮件地址。

8. 部署 Worker

要部署 Worker,请运行以下命令:

Deploy your Workersh
npx wrangler deploy

最后,使用以下命令添加 Resend API 密钥:

Add the Resend API keysh
npx wrangler secret put RESEND_API_KEY

输入 API 密钥的值。API 密钥将添加到您的项目中。您现在可以在代码中使用 RESEND_API_KEY 变量。

您已成功创建可以使用 Resend API 发送邮件并遵守速率限制的 Worker。

要测试 Worker,您可以使用以下 cURL 请求。将 <YOUR_WORKER_URL> 替换为已部署 Worker 的 URL。

Test with a cURL requestbash
curl -X POST -d "[email protected]" <YOUR_WORKER_URL>

请参阅 GitHub 仓库 ↗ 获取本教程的完整代码。若您使用 Hono ↗,请参阅 Hono 示例 ↗。

相关资源

这篇文档对您有帮助吗?