在本教程中,我们将展示如何使用CloudFlare工人和Upstash Redis限制您的应用程序。我们将使用将数据保存在upstash redis中的rate limiting SDK。
REDIS设置
使用Upstash Console或Upstash CLI创建一个或多个Redis数据库。请勿选择全局,而是在您期望进入网站流量的不同区域中创建多个数据库。 (为什么?我们稍后会解释)您将需要在接下来的步骤中进行剩下的URL和令牌。
项目设置
我们将使用Wrangler 2进行部署,因此请安装(或升级)Wrangler 2。
为您的项目创建一个文件夹并运行wrangler init
。选择ts
:
⛅️ wrangler 2.0.7 (update available 2.0.26)
------------------------------------------------------
Using npm as package manager.
✨ Created wrangler.toml
No package.json found. Would you like to create one? (y/n)
✨ Created package.json
Would you like to use TypeScript? (y/n)
✨ Created tsconfig.json
Would you like to create a Worker at src/index.ts? (y/n)
✨ Created src/index.ts
编码
更新工人的功能如下:
import { Redis } from "@upstash/redis/cloudflare";
import { MultiRegionRatelimit } from "@upstash/ratelimit";
export interface Env {
}
const cache = new Map();
export default {
async fetch(
request: Request,
env: Env,
_ctx: ExecutionContext,
): Promise<Response> {
if (new URL(request.url).pathname == "/favicon.ico") {
return new Response(null, { status: 400 });
}
const ratelimit = new MultiRegionRatelimit({
redis: [
new Redis({
url: "https://us1-cool-macaque-32148.upstash.io",
token: "AASQgODM5ZjExZGEtMZDRjOWI4ZmVjNmE3ZDk3NDIxMmEwNmNkYjVmOGVmZTk5Mz",
}),
new Redis({
url: "https://eu2-merry-caribou-31549.upstash.io",
token: "AXe5ASQgNmM5YmFiYWEtMmV3N2E1ODFiMWExMDc5NNGFiYWEwMzk2ZjE4ZWQ3N2Y",
})
],
limiter: MultiRegionRatelimit.fixedWindow(5, "5 s"),
ephermeralCache: cache,
});
const userIP: string = request.headers.get('CF-Connecting-IP') || "none";
const data = await ratelimit.limit(userIP);
if (data.success) {
// if you use CF Workers to intercept another site, uncomment below
// return await fetch(request);
return new Response(JSON.stringify({ message: "Success, you are not rate limited.", ip: userIP, data }, null, 2), { status: 200 });
} else {
// show an error page for rate limited users
return new Response(JSON.stringify({ message: "You are rate limited, try again later.", ip: userIP, data }, null, 2), { status: 200 });
}
},
};
替换上述redis实例的REST_URL和令牌。您可以根据流量在不同区域(或设置单个区域)中添加更多REDIS数据库。
测试和部署
您可以使用wrangler dev
进行本地测试。
用wrangler publish
将打印函数的端点。例如https://cloudflare-workers-rate-limiting.upsdev.workers.dev/当您连续5次刷新页面时,您应该看到您的费率有限。
好吧,教程结束了(很容易,对吗?),现在让我们介绍一些细节。
为每个请求远程通话不是昂贵的吗?
可能是我们不使用短暂的缓存。 The ephemeral cache是在处理程序外定义的地图对象。限制SDK的速率使用它在无服务器函数处于活动状态时缓存标识符(热)。在处理程序外定义它很重要,因此它将是一个全局变量。 CloudFlare工人不能保证不同的调用将使用相同的变量,但在高峰流量期间仍然有很大的帮助。
为什么不全局数据库?
UpStash全局数据库将重新数据复制到多个区域。它非常适合许多边缘用例。但是对于限制速率,我们不需要将一个区域的数据复制到所有其他区域。费率限制会议具有本地范围。我们仍然可以使用全球数据库,但是这将是不必要的昂贵的,因为每个更新都会复制给全世界。这就是为什么我们选择创建多个区域数据库为the rate-limiting SDK recommends。
IP作为标识符
我们已将用户的IP用作限制函数的标识符。这意味着我们限制了单个用户的速率。如果您的请求中有更好的标识符(用户名,电子邮件等),请使用它。如果要限制总共流量,则可以设置一个常数字符串。或者,您可以使用区域或国家(request.cf.country)作为标识符来限制每个地理的流量。
我可以使用自托管的redis吗?
CloudFlare工人在V8隔离株上运行,并且不允许TCP连接。因此,除非您使用REST代理,否则您无法访问自托管的redis,redislabs或Elasticache。 Upstash Redis具有内置的REST API。
集成到您现有网站
您可以在不触摸其代码的情况下限制现有的Web应用程序/站点。您只需要在CloudFlare中创建一个站点,并相应地为您的域名设置名称服务器。因此,CloudFlare将能够拦截您网站的请求并运行工人功能。也要输入XX行,因此您的工人功能将使请求转发到您的网站,如果请求不得限制。
。