429 rate limiting

Tony·2023년 4월 13일
0

Rate Limiting이란?

  • 동시 다발적으로 여러 요청을 보내는 것을 막는 것

왜 Rate Limiting을 사용해야 해야하는가?

  • DDoS(Denial of service attack) 공격을 막기 위해
  • 시스템의 안정성 보장
  • 사용자들간의 공평성을 유지
    • 한 사용자가 너무 많은 API를 사용해서 다른 사람들이 사용할 수 없게 하는 것을 막기 위해
  • 사용자들 마다 다른 서비스를 제공하게 할 수 있음

상태코드 429 : Too Many Requests

  • headers에 Retry-After를 넣어서 얼마나 기다려야 하는지 알려줄 수 있음(권고 사항)

Global API Rate Limiting

  • 글로벌하게 적용

Per User API Rate Limiting

  • 사용자별로 적용

Combined API Rate Limiting

  • Global + Per User
  • 글로벌하게 적용하되, 사용자별로도 적용

Rate limiting in production

  • 사용자가 많은 규모 있는 서비스는 여러 서버 클러스터를 이용해서 서비스를 구동
    • 로드 밸런서를 이용해서 요청을 분산
    • + Redis Store

프론트엔드 대처 방법

  • 429 응답을 받으면 얼마나 기다려야 하는지 알려주는 Retry-After 헤더를 받을 수 있음
  • 이 헤더를 받으면 그 시간만큼 기다렸다가 다시 요청을 보내면 됨
  • 재시도 시 유의점
    • Jitter(변동 폭)를 이용
      • 재시도 시간을 랜덤하게 조금씩 바꿔서 보내는 것
      • 서버에 부하를 줄이기 위해

재시도 구현하기

import axios from "axios";
import axiosRetry from "axios-retry";

const config = {
  retries: 5,
  initialDelayMs: 100,
};

const axiosInstance = axios.create({
  baseURL: "http://localhost:4000",
  headers: {
    "Content-Type": "application/json",
  },
  withCredentials: true,
});

axiosRetry(axiosInstance, {
  retries: config.retries, // 보통은 3번
  retryDelay: (retryCount) => {
    const delay = Math.pow(2, retryCount) * config.initialDelayMs; // 100ms, 200ms, 400ms, 800ms, 1600ms
    const jitter = delay * 0.1 * Math.random(); // delay의 10% 범위 내에서 랜덤으로 더해줌
    return delay + jitter;
  },
  retryCondition: (error) => {
    return (
      axiosRetry.isNetworkOrIdempotentRequestError(error) ||
      error.response.status === 429
    );
  },
});
  • Idempotent : 여러 번 요청해도 결과가 같은 것
    • GET, HEAD, OPTIONS, TRACE
profile
움직이는 만큼 행복해진다

0개의 댓글