Nodes/common/scaling-patterns

common

노드 스케일링 패턴

5분 읽기 · scaling-patterns

list목차(9)

노드 스케일링 패턴

체인에 무관하게 RPC 서비스·퍼블릭 인프라를 확장할 때 쓰이는 공통 패턴입니다. 체인별 클라이언트 세부는 각 chains/<id>/ 가이드를 참고하세요.

1. 단일 노드 vs. 수평 확장

요구 구성
개발·테스트 단일 노드 (Docker 또는 호스트)
프로덕션 RPC 1~100 RPS 단일 노드 + reverse proxy(nginx/Caddy)
100 RPS+ 2~N개의 RPC 노드 + 로드 밸런서 + 헬스체크
대량 historical 조회 Full/Pruned 노드 + Archive 노드 분리
flowchart TB
  Client((Client))
  CDN[Cloudflare / AWS GA]
  LB[nginx / HAProxy]
  subgraph Read["Read 풀 (round-robin)"]
    R1[Full #1]
    R2[Full #2]
    R3[Full #3]
  end
  Archive[Archive Node]
  Client --> CDN --> LB
  LB -->|eth_blockNumber, 최근 블록| Read
  LB -->|getBlockByNumber old| Archive
  LB -->|sendTransaction sticky| R1
  Prometheus[Prometheus 헬스체크] -. scrape .- Read
  LB -. 제외 .- Prometheus

2. Reverse Proxy (nginx 예시)

# /etc/nginx/conf.d/rpc.conf
upstream rpc_pool {
    least_conn;
    server 10.0.0.11:8545 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:8545 max_fails=3 fail_timeout=30s;
    server 10.0.0.13:8545 max_fails=3 fail_timeout=30s;
}

server {
    listen 443 ssl http2;
    server_name rpc.example.com;

    ssl_certificate     /etc/letsencrypt/live/rpc.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/rpc.example.com/privkey.pem;

    # 간단한 IP 기반 rate limit
    limit_req_zone $binary_remote_addr zone=rpc:10m rate=10r/s;
    limit_req zone=rpc burst=30 nodelay;

    location / {
        proxy_pass http://rpc_pool;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header Connection "";
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
        proxy_next_upstream error timeout http_502 http_504;
    }

    # 메서드 allowlist (Lua 없이 Nginx map)
    # 실제 운영 시 OpenResty + Lua로 JSON-RPC 본문 검사 권장
}

헬스체크

각 upstream 노드에 별도 /health 엔드포인트를 두거나, nginx_upstream_check_module을 사용해 동기화 상태 기준으로 제외시킵니다. 동기화 지연을 판단하는 쿼리 예:

  • EVM: eth_syncing == false && eth_blockNumber >= threshold
  • Solana: getSlot 차이 < 200
  • Cosmos: GET /statussync_info.catching_up == false

3. 읽기/쓰기 분리

트랜잭션 전파(write) 경로와 조회(read) 경로의 요구가 다릅니다.

  • Write(sendTransaction): sticky session·같은 노드 유지 → mempool 반영 지연 최소화
  • Read(getBlockByNumber 등): round-robin 로드밸런싱·aggressive 캐싱

nginx map을 사용한 간단한 분기:

map $request_method $is_write {
    default 0;
    POST 1;
}

# POST + JSON-RPC 본문 기준 분기는 OpenResty + Lua로

4. WebSocket 노드

WebSocket RPC(wss://)는 세션이 장시간 유지되므로 로드밸런서에서 sticky 구성과 connection limit이 필수입니다.

  • nginx: ip_hash 또는 hash $remote_addr consistent;
  • Cloudflare Spectrum: TCP/WebSocket 지원, 글로벌 Anycast

5. 캐시 레이어

체인 상태는 빠르게 변하지만 과거 블록/트랜잭션은 immutable 합니다.

데이터 캐시 TTL 캐시 키
과거 블록 해시·본문 영구 getBlockByHash/getBlock + height
영구 트랜잭션 receipt 영구 getTransactionReceipt:<txhash>
현재 블록 번호 500 ms~1 s eth_blockNumber
계정 잔고 1~5 s eth_getBalance:<addr>:<block>

Redis 또는 LFU 인메모리 캐시를 nginx proxy_cache 앞단에 두는 방식이 일반적입니다.

6. 글로벌 배포

  • Anycast / Multi-region RPC: 사용자에게 가까운 리전으로 자동 라우팅 (Cloudflare, AWS Global Accelerator)
  • 읽기 복제본: 리전별 Full 노드 여러 대 + 중앙 Archive 노드 1~2대
  • 쓰기 경로 일원화: 트랜잭션 브로드캐스트는 체인의 P2P 네트워크가 처리하므로 로드밸런서 걱정 없음

7. 비용 대비 성능 팁

  • 체인 스냅샷 활용: 수 TB 재동기화보다 스냅샷 복원이 압도적으로 빠름
  • Pruning 설정: 스토리지 비용을 2~3배 줄임
  • 메트릭 기반 오토스케일: 1시간 RPS/피크 기준으로 노드 수 자동 조정 (HPA)
  • 노드 운영 비용 vs. 외부 RPC: 1M RPS 이상 수요에는 자체 운영이 저렴, 100 RPS 이하면 Alchemy/Infura 등이 저렴

참고

common 다른 챕터