Trong bài viết này, chúng tôi sẽ chỉ cách giới hạn tỷ lệ (rate limit) cho các API routes Next.js bằng Upstash Rate limit SDK.
Thiết lập cơ sở dữ liệu
Tạo cơ sở dữ liệu Redis bằng Upstash Console hoặc Upstash CLI. Sao chép UPSTASH_REDIS_REST_URL và UPSTASH_REDIS_REST_TOKEN cho các bước tiếp theo.
Thiết lập dự án
Chúng ta sẽ tạo một ứng dụng Next.js và triển khai lên Vercel.
npx create-next-app@latestCài đặt @upstash/ratelimit:
npm install @upstash/ratelimit @upstash/redisMã nguồn
Cập nhật pages/api/hello.js như dưới đây và thay thế UPSTASH_REDIS_REST_URL và UPSTASH_REDIS_REST_TOKEN.
// pages/api/hello.js
import {Ratelimit} from "@upstash/ratelimit";
import {Redis} from "@upstash/redis";
const redis = new Redis({
url: 'UPSTASH_REDIS_REST_URL',
token: 'UPSTASH_REDIS_REST_TOKEN',
})
// Tạo rate limiter mới, cho phép 5 request mỗi 5 giây
const ratelimit = new Ratelimit({
redis: redis,
limiter: Ratelimit.fixedWindow(5, "5 s"),
});
export default async function handler(req, res) {
// Dùng chuỗi hằng để giới hạn tất cả request với một rate limit
// Hoặc dùng userID, apiKey hoặc địa chỉ IP cho giới hạn riêng biệt.
const identifier = "api";
const result = await ratelimit.limit(identifier);
res.setHeader('X-RateLimit-Limit', result.limit)
res.setHeader('X-RateLimit-Remaining', result.remaining)
if (!result.success) {
res.status(200).json({message: 'The request has been rate limited.', rateLimitState: result})
return
}
res.status(200).json({name: 'John Doe', rateLimitState: result})
}Ở đây, chúng ta cho phép 5 request mỗi 5 giây.
Chạy thử
Chạy ứng dụng với npm run dev. Làm mới trình duyệt hơn 5 lần và bạn sẽ thấy rate limiting hoạt động.
{"message":"The request has been rate limited.","rateLimitState":{"success":false,"limit":5,"remaining":-1,"reset":1654546770000,"pending":{}}}Các cải tiến có thể
- Sử dụng ID người dùng hoặc địa chỉ IP làm identifier để giới hạn sử dụng theo từng người.
const identifier = getClientIp(req);
const result = await ratelimit.limit(identifier);- Sử dụng Thuật toán Sliding Window để trải nghiệm rate limiting mượt mà hơn (nhưng tốn kém hơn).
const ratelimit = new Ratelimit({
redis: redis,
limiter: Ratelimit.slidingWindow(10, "10 s"),
});- Sử dụng Thuật toán Token Bucket để chịu đựng được một lượng spike nhất định.
const ratelimit = new Ratelimit({
redis: redis,
limiter: Ratelimit.tokenBucket(5, "10 s", 10),
});Sử dụng nhiều Redis ở các khu vực khác nhau nếu ứng dụng Next.js của bạn được triển khai ở nhiều khu vực. Điều này giúp giảm thiểu độ trễ cho các vị trí khác nhau.
Lưu trữ và đọc thông tin xác thực Upstash Redis từ biến môi trường hoặc secret store.