跳转到内容
搜索文档

速率限制

最后更新 查看 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 速率限制窗口的持续时间,以秒为单位。必须是 1060

例如,要应用每分钟 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 位置内的后备存储通信在后台异步更新。

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

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

示例

这篇文档对您有帮助吗?