이 종합 가이드에서는 트래픽이 많은 환경에서 사용자 요청을 제어하기 위해 Redis 및 Lua 스크립팅을 사용하여 분산 속도 제한기를 구축합니다.
속도 제한은 남용을 방지하고, 트래픽을 관리하고, 리소스를 보호하기 위해 모든 시스템에서 매우 중요합니다. Redis와 Lua를 활용하면 백엔드 서비스를 안전하게 유지하면서 많은 수의 요청을 처리할 수 있는 효율적이고 확장 가능한 속도 제한 시스템을 구축하게 됩니다.
또한 사용자가 트래픽을 시뮬레이션하고, 적용되는 속도 제한을 관찰하고, 차단된 요청 로그를 볼 수 있는 대화형 데모도 포함됩니다.
배우게 될 내용
-
Redis를 사용하여 속도 제한 시스템을 구축하는 방법
-
Redis에서 Lua 스크립트를 사용하여 원자적 작업을 수행하는 방법
-
효율적인 요청 추적을 위한 Redis 데이터 구조 이해
-
분산 시스템에서 높은 트래픽을 처리하는 기술.
-
Docker를 사용하여 분산 속도 제한기를 시뮬레이션하고 확장합니다.
전제조건
시작하기 전에 다음이 설치되어 있는지 확인하세요:
-
Node.js(v14 이상)
-
레디스
-
Docker(분산 환경 시뮬레이션용)
-
Node.js, Redis 및 Lua 스크립팅에 대한 기본 이해
목차
-
무엇을 배울 것인가
-
전제 조건
-
프로젝트 개요
-
1단계:프로젝트 설정 방법
-
2단계:Redis 설정 방법
-
3단계:Redis 및 Lua를 사용하여 속도 제한기를 구현하는 방법
-
4단계:Node.js API 서버를 만드는 방법
-
5단계:속도 제한기를 테스트하는 방법
-
6단계:속도 제한 측정항목을 시각화하는 방법
-
7단계:Docker를 사용하여 배포하는 방법
-
결론:배운 내용
프로젝트 개요
이 튜토리얼에서는 다음을 수행합니다:
-
요청 할당량을 적용하기 위해 Redis와 Lua를 사용하여 속도 제한기를 구축하세요.
-
Lua 스크립트를 사용하면 경쟁 조건을 피하면서 원자적 작업을 보장할 수 있습니다.
-
속도 제한을 위한 토큰 버킷 알고리즘을 구현합니다.
-
높은 트래픽을 시뮬레이션하고 속도 제한이 실제로 작동하는 모습을 시각화하는 대화형 데모를 만드세요.
시스템 아키텍처
다음 구성 요소를 사용하여 시스템을 구축하게 됩니다:
-
API 서버 :들어오는 사용자 요청을 처리합니다.
-
레디스 :요청 데이터를 저장하고 속도 제한을 적용합니다.
-
Lua 스크립트 :속도 제한을 위해 Redis에 대한 원자적 업데이트를 보장합니다.
-
도커 :여러 인스턴스가 있는 분산 환경을 시뮬레이션합니다.
1단계:프로젝트 설정 방법
Node.js 프로젝트를 설정하는 것부터 시작해 보겠습니다.
mkdir distributed-rate-limiter
cd distributed-rate-limiter
npm init -y
다음으로 필요한 종속성을 설치하십시오:
npm install express redis dotenv
-
표현 :경량 웹 서버 프레임워크입니다.
-
레디스 :Redis와의 상호작용을 위해.
-
도텐브 :환경변수를 관리하기 위한 것입니다.
.env 만들기 다음 내용을 포함하는 파일:
REDIS_HOST=localhost
REDIS_PORT=6379
PORT=3000
RATE_LIMIT=5
TIME_WINDOW=60
이러한 변수는 Redis 호스트, 포트, 속도 제한(허용된 요청 수) 및 기간(초)을 정의합니다.
2단계:Redis 설정 방법
코드를 살펴보기 전에 Redis가 시스템에 설치되어 실행되고 있는지 확인하세요. Redis가 설치되어 있지 않은 경우 Docker를 사용하여 빠르게 설정할 수 있습니다.
docker run -p 6379:6379 --name redis-rate-limiter -d redis
3단계:Redis 및 Lua를 사용하여 속도 제한기를 구현하는 방법
속도 제한을 효율적으로 처리하기 위해 토큰 버킷 알고리즘을 사용합니다. 이 알고리즘에서는:
-
각 사용자는 토큰의 "버킷"을 갖습니다.
-
각 요청은 토큰을 소비합니다.
-
토큰은 정해진 비율로 주기적으로 채워집니다.
원자성을 보장하고 경쟁 조건을 방지하기 위해 Redis와 함께 Lua 스크립팅을 사용하겠습니다. Redis의 Lua 스크립트는 원자적으로 실행됩니다. 즉, 실행 중에 다른 작업으로 인해 중단될 수 없습니다.
속도 제한을 위한 Lua 스크립트를 만드는 방법
rate_limiter.lua라는 파일을 만듭니다. :
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local current = redis.call("get", key)
if current and tonumber(current) >= limit then
return 0
else
if current then
redis.call("incr", key)
else
redis.call("set", key, 1, "EX", window)
end
return 1
end
-
입력 :
-
키[1] :사용자의 요청 횟수를 나타내는 Redis 키입니다.
-
ARGV[1] :속도 제한(허용되는 최대 요청 수)
-
ARGV[2] :속도 제한의 기간(초)입니다.
-
-
논리 :
-
사용자가 속도 제한에 도달한 경우
0를 반환합니다. (요청이 차단되었습니다.) -
사용자가 한도 내에 있는 경우 요청 횟수를 늘리거나 첫 번째 요청인 경우 만료된 새 횟수를 설정하세요.
-
1을 반환합니다(요청 허용).
-
4단계:Node.js API 서버 생성 방법
server.js라는 파일을 만듭니다. :
require('dotenv').config();
const express = require('express');
const redis = require('redis');
const fs = require('fs');
const path = require('path');
const app = express();
const client = redis.createClient({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT
});
const rateLimitScript = fs.readFileSync(path.join(__dirname, 'rate_limiter.lua'), 'utf8');
const RATE_LIMIT = parseInt(process.env.RATE_LIMIT);
const TIME_WINDOW = parseInt(process.env.TIME_WINDOW);
// Middleware for rate limiting
async function rateLimiter(req, res, next) {
const ip = req.ip;
try {
const allowed = await client.eval(rateLimitScript, 1, ip, RATE_LIMIT, TIME_WINDOW);
if (allowed === 1) {
next();
} else {
res.status(429).json({ message: 'Too many requests. Please try again later.' });
}
} catch (err) {
console.error('Error in rate limiter:', err);
res.status(500).json({ message: 'Internal server error' });
}
}
app.use(rateLimiter);
app.get('/', (req, res) => {
res.send('Welcome to the Rate Limited API!');
});
const PORT = process.env.PORT;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
-
비율 제한 미들웨어 :
-
클라이언트의 IP 주소를 검색하고 Lua 스크립트를 사용하여 속도 제한 내에 있는지 확인합니다.
-
사용자가 한도를 초과하면
429응답이 전송되었습니다.
-
-
API 엔드포인트 :
- 루트 엔드포인트는 속도가 제한되어 있으므로 사용자는 지정된 창 내에서 제한된 횟수에만 액세스할 수 있습니다.
5단계:속도 제한기 테스트 방법
-
Redis 시작 :
docker start redis-rate-limiter -
Node.js 서버 실행 :
node server.js -
요청 시뮬레이션 :
-
curl사용 또는 속도 제한기를 테스트하기 위한 Postman:curl http://localhost:3000 -
여러 요청을 신속하게 보내 속도 제한이 어떻게 작동하는지 확인하세요.
-
6단계:속도 제한 측정항목을 시각화하는 방법
캐시 적중 및 차단된 요청과 같은 속도 제한 측정항목을 모니터링하기 위해 server.js의 미들웨어에 로깅을 추가합니다. :
async function rateLimiter(req, res, next) {
const ip = req.ip;
try {
const allowed = await client.eval(rateLimitScript, 1, ip, RATE_LIMIT, TIME_WINDOW);
if (allowed === 1) {
console.log(`Allowed request from ${ip}`);
next();
} else {
console.log(`Blocked request from ${ip}`);
res.status(429).json({ message: 'Too many requests. Please try again later.' });
}
} catch (err) {
console.error('Error in rate limiter:', err);
res.status(500).json({ message: 'Internal server error' });
}
}
7단계:Docker를 사용하여 배포하는 방법
애플리케이션을 컨테이너화하여 분산 환경에서 실행해 보겠습니다.
Dockerfile 만들기 :
FROM node:14
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["node", "server.js"]
Docker 컨테이너 구축 및 실행:
docker build -t rate-limiter .
docker run -p 3000:3000 rate-limiter
이제 여러 인스턴스를 실행하여 속도 제한기를 확장할 수 있습니다.
결론:배운 내용
축하합니다! Redis 및 Lua 스크립트를 사용하여 분산 속도 제한기를 성공적으로 구축했습니다. 이 튜토리얼 전체에서 다음 방법을 배웠습니다.
-
분산 시스템에서 사용자 요청을 제어하기 위해 속도 제한을 구현합니다.
-
Redis에서 Lua 스크립트를 사용하여 원자성 작업을 수행합니다.
-
요청 할당량을 관리하려면 토큰 버킷 알고리즘을 적용하세요.
-
성능을 최적화하려면 속도 제한 지표를 모니터링하세요.
-
Docker를 사용하여 확장 가능한 분산 환경을 시뮬레이션하세요.
다음 단계:
-
사용자 ID별 속도 제한 추가 :사용자당 속도 제한을 지원하도록 시스템을 확장합니다.
-
Nginx와 통합 :Redis 지원 속도 제한을 통해 Nginx를 역방향 프록시로 사용하세요.
-
Kubernetes로 배포 :고가용성을 위해 Kubernetes를 사용하여 속도 제한기를 확장하세요.
즐거운 코딩 되세요!
무료로 코딩을 배우세요. freeCodeCamp의 오픈 소스 커리큘럼은 40,000명 이상의 사람들이 개발자로 취업하는 데 도움을 주었습니다. 시작하세요