Guide de limitation de débit

VérifiéSûr

Exécute un guide de conception de limitation de débit couvrant les algorithmes Token Bucket, Leaky Bucket et Sliding Window avec des exemples d'implémentation en Redis et Node.js.

Spar Skills Guide Bot
DeveloppementIntermédiaire
1025/07/2026
Claude Code
#rate-limiting#api-rate-limit#redis#backend

Recommandé pour

Notre avis

Ce guide fournit des instructions pour concevoir et implémenter une limitation de débit (rate limiting) à l'aide de divers algorithmes, avec des exemples en Node.js et Redis.

Points forts

  • Couvre plusieurs algorithmes avec des diagrammes clairs
  • Inclut des implémentations concrètes (script Lua, middleware Node.js)
  • Propose des stratégies par niveau et dynamiques

Limites

  • Suppose Redis comme seul stockage
  • Ne traite pas la coordination distribuée
  • Exemples limités à Node.js
Quand l'utiliser

À utiliser lors de la conception d'une limitation de débit pour une API web, notamment avec Redis et Node.js.

Quand l'éviter

À éviter si la solution doit être indépendante du langage ou sans Redis, ou pour des limitations de débit simples en mémoire.

Analyse de sécurité

Sûr
Score qualité95/100

The skill provides educational content and code examples for rate limiting design. It does not include any destructive commands, data exfiltration, or execution of external scripts. The code snippets are for illustration only and do not pose a risk.

Aucun point d'attention détecté

Exemples

Token Bucket with Redis
Implement a token bucket rate limiter using Redis Lua script for my Express API.
Tiered Rate Limiting
Set up tiered rate limiting for free, basic, and pro users in my Node.js app.
Sliding Window Counter
Implement a sliding window counter rate limiter with Redis and Node.js.

name: "rate-limit" description: "레이트 리밋 설계 가이드를 실행합니다." user-invocable: true

Rate Limiting Skill

레이트 리밋 설계 가이드를 실행합니다.

레이트 리밋 알고리즘

Token Bucket

버킷에 토큰이 일정 속도로 추가
요청 시 토큰 소비
토큰 없으면 거부

┌─────────────┐
│ ○ ○ ○ ○ ○  │ ← 토큰 추가 (초당 10개)
│   Bucket    │
└──────┬──────┘
       ↓ 요청당 1토큰 소비
    [Request]

장점: 버스트 허용, 평균 속도 제한
구현: Redis + Lua Script

Leaky Bucket

요청이 버킷에 쌓임
일정 속도로 처리
버킷 넘치면 거부

     [Request]
         ↓
┌─────────────┐
│ ░ ░ ░ ░ ░  │ ← 큐 (고정 크기)
└──────┬──────┘
       ↓ 일정 속도로 처리
   [Processed]

장점: 일정한 출력 속도
단점: 버스트 불가

Fixed Window

고정 시간 창에서 요청 수 제한

|----60초----|----60초----|
| 100 요청   | 100 요청   |
|____________|____________|

단점: 경계에서 2배 버스트 가능
      (59초에 100개 + 61초에 100개)

Sliding Window Log

각 요청의 타임스탬프 기록
윈도우 내 요청 수 계산

현재 시간: 10:05:30
윈도우: 60초
[10:04:31, 10:04:45, 10:05:10, 10:05:25]
→ 윈도우 내 4개 요청

장점: 정확함
단점: 메모리 사용 많음

Sliding Window Counter

이전 윈도우와 현재 윈도우 가중 평균

이전 윈도우 (70개) × 30% + 현재 윈도우 (50개) × 70%
= 21 + 35 = 56개

장점: 메모리 효율적, 상당히 정확

구현 예시

Redis + Token Bucket

-- rate_limit.lua
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local now = tonumber(ARGV[3])

local bucket = redis.call('HMGET', key, 'tokens', 'last_update')
local tokens = tonumber(bucket[1]) or limit
local last_update = tonumber(bucket[2]) or now

-- 토큰 리필
local elapsed = now - last_update
local refill = elapsed * (limit / window)
tokens = math.min(limit, tokens + refill)

if tokens >= 1 then
    tokens = tokens - 1
    redis.call('HMSET', key, 'tokens', tokens, 'last_update', now)
    redis.call('EXPIRE', key, window)
    return {1, tokens}  -- 허용, 남은 토큰
else
    return {0, 0}  -- 거부
end

Node.js 미들웨어

const Redis = require('ioredis');
const redis = new Redis();

const rateLimitScript = fs.readFileSync('rate_limit.lua', 'utf8');

async function rateLimit(options) {
  const { key, limit, window } = options;

  return async (req, res, next) => {
    const identifier = req.ip; // 또는 req.user.id
    const redisKey = `ratelimit:${key}:${identifier}`;

    const [allowed, remaining] = await redis.eval(
      rateLimitScript,
      1,
      redisKey,
      limit,
      window,
      Date.now() / 1000
    );

    res.set('X-RateLimit-Limit', limit);
    res.set('X-RateLimit-Remaining', remaining);

    if (!allowed) {
      res.set('Retry-After', window);
      return res.status(429).json({
        error: 'Too Many Requests',
        retryAfter: window,
      });
    }

    next();
  };
}

// 사용
app.use('/api/', rateLimit({ key: 'api', limit: 100, window: 60 }));
app.use('/api/search', rateLimit({ key: 'search', limit: 10, window: 60 }));

Express Rate Limit

const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');

const limiter = rateLimit({
  store: new RedisStore({
    client: redis,
    prefix: 'rl:',
  }),
  windowMs: 60 * 1000, // 1분
  max: 100, // 100 요청
  message: { error: 'Too many requests' },
  standardHeaders: true,
  legacyHeaders: false,
});

app.use('/api/', limiter);

레이트 리밋 전략

계층별 제한

const limits = {
  global: { limit: 10000, window: 60 },      // 전체 API
  authenticated: { limit: 1000, window: 60 }, // 인증된 사용자
  anonymous: { limit: 100, window: 60 },      // 익명 사용자
  endpoint: {                                  // 엔드포인트별
    '/api/search': { limit: 10, window: 60 },
    '/api/upload': { limit: 5, window: 60 },
  },
};

사용자 티어별

const tierLimits = {
  free: { limit: 100, window: 3600 },      // 시간당 100
  basic: { limit: 1000, window: 3600 },    // 시간당 1000
  pro: { limit: 10000, window: 3600 },     // 시간당 10000
  enterprise: { limit: 100000, window: 3600 },
};

function getRateLimit(user) {
  return tierLimits[user.tier] || tierLimits.free;
}

동적 제한

// 부하에 따른 동적 조정
async function getDynamicLimit() {
  const load = await getSystemLoad();

  if (load > 0.9) return { limit: 50, window: 60 };   // 높은 부하
  if (load > 0.7) return { limit: 75, window: 60 };   // 중간 부하
  return { limit: 100, window: 60 };                   // 정상
}

응답 헤더

표준 헤더

X-RateLimit-Limit: 100        # 최대 요청 수
X-RateLimit-Remaining: 45     # 남은 요청 수
X-RateLimit-Reset: 1640000000 # 리셋 시간 (Unix timestamp)
Retry-After: 30               # 재시도까지 초 (429 응답 시)

응답 예시

// 429 Too Many Requests
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again in 30 seconds.",
    "retryAfter": 30,
    "limit": 100,
    "remaining": 0,
    "reset": 1640000000
  }
}

분산 환경

Redis Cluster

// 모든 인스턴스가 같은 Redis 참조
const redis = new Redis.Cluster([
  { host: 'redis-1', port: 6379 },
  { host: 'redis-2', port: 6379 },
  { host: 'redis-3', port: 6379 },
]);

일관성 고려

Strong Consistency: 모든 노드가 동일한 카운트 (느림)
Eventual Consistency: 일시적 불일치 허용 (빠름)

대부분의 레이트 리밋은 Eventual Consistency로 충분
약간의 초과 허용이 성능보다 덜 중요

체크리스트

설계

  • [ ] 알고리즘 선택
  • [ ] 제한 수치 결정
  • [ ] 키 식별자 정의 (IP, 사용자, API 키)
  • [ ] 티어별 제한 설계

구현

  • [ ] 분산 저장소 (Redis)
  • [ ] 응답 헤더 설정
  • [ ] 에러 응답 형식
  • [ ] 바이패스 규칙 (내부, 헬스체크)

운영

  • [ ] 모니터링/알림
  • [ ] 제한 초과 로깅
  • [ ] 동적 조정 메커니즘

출력 형식

## Rate Limit Design

### Strategy
- 알고리즘: Token Bucket
- 저장소: Redis

### Limits
| 대상 | 제한 | 윈도우 | 키 |
|------|------|--------|-----|
| Global | 10000 | 분 | IP |
| Auth User | 1000 | 분 | user_id |
| Search API | 10 | 분 | user_id |

### Implementation
```javascript
// 핵심 구현 코드

Response Format

// 429 응답 예시

---

요청에 맞는 레이트 리밋 전략을 설계하세요.
Skills similaires