跳转到内容
搜索文档

速率限制

最后更新 查看 MarkdownAgent 设置

Rate Limiting API 允许您定义速率限制,并在 Worker 中围绕它们编写代码。

您可以使用它来强制执行:

  • 在 Worker 启动后应用的速率限制,仅在代码的特定部分被到达时才生效
  • 针对不同类型客户或用户(例如:免费 vs. 付费)的不同速率限制
  • 针对特定资源或路径的限制(例如:每个 API 路由的限制)
  • 以上任意组合

Rate Limiting API 由为 rate limiting rules 提供服务的相同基础设施支持。

快速入门

首先,向 Worker 添加一个绑定(binding),使其能够访问 Rate Limiting API:

{
	"main": "src/index.js",
	"ratelimits": [
		{
			"name": "MY_RATE_LIMITER",
			// An identifier you define, that is unique to your Cloudflare account.
			// Must be an integer.
			"namespace_id": "1001",
			// Limit: the number of tokens allowed within a given period in a single
			// Cloudflare location
			// Period: the duration of the period, in seconds. Must be either 10 or 60
			"simple": {
				"limit": 100,
				"period": 60
			}
		}
	]
}
main = "src/index.js"

[[ratelimits]]
name = "MY_RATE_LIMITER"
namespace_id = "1001"

  [ratelimits.simple]
  limit = 100
  period = 60

此绑定使 MY_RATE_LIMITER 绑定可用,它提供 limit() 方法:

export default {
  async fetch(request, env) {
    const { pathname } = new URL(request.url)

    const { success } = await env.MY_RATE_LIMITER.limit({ key: pathname }) // key can be any string of your choosing
    if (!success) {
      return new Response(`429 Failure – rate limit exceeded for ${pathname}`, { status: 429 })
    }

    return new Response(`Success!`)
  }
}
interface Env {
  MY_RATE_LIMITER: RateLimit;
}

export default {
  async fetch(request, env): Promise<Response> {
    const { pathname } = new URL(request.url)

    const { success } = await env.MY_RATE_LIMITER.limit({ key: pathname }) // key can be any string of your choosing
    if (!success) {
      return new Response(`429 Failure – rate limit exceeded for ${pathname}`, { status: 429 })
    }

    return new Response(`Success!`)
  }
} satisfies ExportedHandler<Env>;

limit() API 接受单个参数——一个包含 key 字段的配置对象。

  • 您提供的 key 可以是任何 string 值。
  • 一种常见模式是通过组合唯一标识发起请求的执行者(例如:用户 ID 或客户 ID)的字符串和标识特定资源的字符串(例如:特定 API 路由)来定义 key。

您可以为每个 Worker 定义和配置多个速率限制配置,这允许您根据需要针对传入请求和/或用户参数定义不同的限制,以保护您的应用程序或上游 API。

例如,以下是如何为免费和付费层级用户定义两个速率限制配置:

{
	"main": "src/index.js",
	"ratelimits": [
		// Free user rate limiting
		{
			"name": "FREE_USER_RATE_LIMITER",
			"namespace_id": "1001",
			"simple": {
				"limit": 100,
				"period": 60
			}
		},
		// Paid user rate limiting
		{
			"name": "PAID_USER_RATE_LIMITER",
			"namespace_id": "1002",
			"simple": {
				"limit": 1000,
				"period": 60
			}
		}
	]
}
main = "src/index.js"

[[ratelimits]]
name = "FREE_USER_RATE_LIMITER"
namespace_id = "1001"

  [ratelimits.simple]
  limit = 100
  period = 60

[[ratelimits]]
name = "PAID_USER_RATE_LIMITER"
namespace_id = "1002"

  [ratelimits.simple]
  limit = 1_000
  period = 60

配置

速率限制绑定具有以下设置:

Setting Type Description
namespace_id string 包含正整数的字符串,在您的 Cloudflare 账户内唯一标识此速率限制命名空间(例如 "1001")。虽然值必须是有效整数,但指定为字符串。这是有意为之。
simple object 速率限制配置。simple 是唯一支持的类型。
simple.limit number 在给定 period 内允许的请求数(或对 limit() 的调用次数)。
simple.period number 速率限制窗口的持续时间,以秒为单位。必须是 10 或 60。

例如,要应用每分钟 1500 个请求的速率限制,您可以按如下方式定义速率限制配置:

{
	"ratelimits": [
		{
			"name": "MY_RATE_LIMITER",
			"namespace_id": "1001",
			// 1500 requests - calls to limit() increment this
			"simple": {
				"limit": 1500,
				"period": 60
			}
		}
	]
}
[[ratelimits]]
name = "MY_RATE_LIMITER"
namespace_id = "1001"

  [ratelimits.simple]
  limit = 1_500
  period = 60

最佳实践

传递给 limit 函数、用于确定速率限制依据的 key,应代表您希望进行速率限制的用户或用户类别的唯一特征。

  • 好的选择包括 Authorization HTTP 标头中的 API 密钥、URL 路径或路由、应用程序使用的特定查询参数,和/或用户 ID 和租户 ID。这些都是稳定的标识符,在请求之间不太可能改变。
  • 不建议使用 IP 地址或位置(区域或国家),因为在许多有效情况下,这些可能被许多用户共享。您可能会发现自己在这些 key 上进行速率限制时,无意中限制了比预期更广泛的用户群体。
// Recommended: use a key that represents a specific user or class of user
const url = new URL(req.url)
const userId = url.searchParams.get("userId") || ""
const { success } = await env.MY_RATE_LIMITER.limit({ key: userId })

// Not recommended:  many users may share a single IP, especially on mobile networks
// or when using privacy-enabling proxies
const ipAddress = req.headers.get("cf-connecting-ip") || ""
const { success } = await env.MY_RATE_LIMITER.limit({ key: ipAddress })

Locality

您在 Worker 中定义和强制执行的速率限制是本地于 Worker 运行的 Cloudflare 位置 ↗的。

例如,如果请求从澳大利亚悉尼到达上述 Worker,在 60 秒窗口内 100 个请求之后,对特定路径的任何进一步请求将被拒绝,并返回 429 HTTP 状态码。但这仅适用于在悉尼提供服务的请求。对于您传递给速率限制绑定的每个唯一 key,每个 Cloudflare 位置都有独立的限制。

Performance

Workers 中的 Rate Limiting API 设计为快速。

底层计数器缓存在 Worker 运行的同一台机器上,并通过与同一 Cloudflare 位置内的后备存储通信在后台异步更新。

这意味着在代码中 await 对 limit() 方法的调用时:

const { success } = await env.MY_RATE_LIMITER.limit({ key: customerId })

您不是在等待网络请求。您可以使用 Rate Limiting API,而不会给 Worker 引入任何有意义的延迟。

Accuracy

上述情况也意味着 Rate Limiting API 是宽松的、最终一致的,并且有意设计为不用于精确的会计系统。

例如,如果许多请求到达 Worker 的单个 Cloudflare 位置,全部在同一 key 上进行速率限制,为每个请求提供服务的 isolate 将检查其本地缓存的速率限制值。很快(但不是立即),这些请求将计入该 Cloudflare 位置内的速率限制。

Monitoring

速率限制绑定目前在 Cloudflare 仪表板中不可见。要从 Worker 监控被速率限制的请求:

  • Workers Observability — 使用 Workers Logs 和 Traces 观察 Worker 在超出速率限制时返回的 HTTP 429 响应。
  • Workers Analytics Engine — 向 Worker 添加 Analytics Engine 绑定,并在 limit() 返回 { success: false } 时发出自定义数据点(例如 rate_limited 事件)。这允许您构建仪表板并随时间查询速率限制指标。

示例

这篇文档对您有帮助吗?