Node.js 서버의 동시 접속 한도
Node.js 서버의 동시 접속 한도는 기본 설정으로 특정 숫자가 정해져 있지 않지만, 여러 요소에 의해 제한됩니다:
-
HTTP 서버 기본 설정:
- Node.js의 HTTP/HTTPS 서버는 기본적으로 연결 수에 엄격한 제한을 두지 않음
- Express 같은 프레임워크는 기본 설정으로 대기열에 5,000개의 요청을 가질 수 있음
-
운영체제 제한:
- 가장 일반적인 제한 요소는 운영체제의 최대 동시 열린 파일(소켓) 수
- Linux에서는 보통
ulimit -n
으로 확인 가능하며, 기본값은 1,024 - 이는 서버가 1,024개의 동시 연결을 처리할 수 있음을 의미
-
Node.js 이벤트 루프:
- Node.js는 단일 스레드 이벤트 루프 모델을 사용하므로, 처리 능력은 CPU 작업 부하와 I/O 작업의 효율성에 따라 달라짐
-
하드웨어 리소스:
- 메모리, CPU, 네트워크 대역폭 등 서버의 하드웨어 자원도 제한 요소
프로덕션 환경에서 더 많은 동시 연결 처리 방법
// 서버 생성 시 최대 연결 수 증가 const server = http.createServer(app); server.maxConnections = 10000; // OS 파일 디스크립터 한도 증가 (Linux/Unix) // $ ulimit -n 10000 (터미널에서 실행) // Keep-Alive 타임아웃 설정 server.keepAliveTimeout = 5000; // 5초
실제로는 클러스터 모듈이나 PM2 같은 프로세스 매니저를 사용하여 여러 개의 Node.js 인스턴스를 실행하고, Nginx나 HAProxy 같은 로드 밸런서를 앞단에 두는 것이 일반적입니다.
멀티파트 업로드 시스템의 경우, 특히 SSE(Server-Sent Events)를 사용한 진행률 모니터링 때문에 일반적인 HTTP 요청보다 더 많은 리소스를 사용할 수 있으므로, 프로덕션 환경에서는 서버 설정을 적절히 조정하는 것이 중요합니다.
현재 구조라면 로드밸런서(LB)만 추가해도 기본적으로 정상 동작할 수 있지만 대용량 트래픽과 멀티파트 업로드를 효율적으로 처리하기 위해서는 몇 가지 추가 설정이 필요합니다.
로드밸런서 추가 시 고려사항
-
Connection 수 조정:
- Nginx의 경우
worker_connections
값을 조정 (기본값은 보통 512나 1024) - HAProxy의 경우
maxconn
값을 조정
- Nginx의 경우
-
세션 관리:
- 멀티파트 업로드의 경우 각 청크가 같은 서버로 가야 함
- 특히
uploadId
를 기준으로 동일 사용자의 요청이 동일 서버로 라우팅되어야 함
-
타임아웃 설정:
- 대용량 파일 업로드는 일반 요청보다 오래 걸리므로 타임아웃 설정 확인 필요
- Nginx의 경우
client_body_timeout
,proxy_read_timeout
등을 조정
Nginx 설정 예시
http { # 워커 프로세스당 최대 연결 수 증가 worker_connections 10000; # 요청 본문 크기 제한 증가 (대용량 청크 허용) client_max_body_size 10M; # 타임아웃 설정 증가 client_body_timeout 120s; proxy_connect_timeout 120s; proxy_send_timeout 120s; proxy_read_timeout 120s; # 업로드 ID 기반 세션 일관성 설정 upstream app_servers { ip_hash; # 또는 더 나은 방법으로 sticky sessions 사용 server app1.example.com:3000; server app2.example.com:3000; # 추가 서버... } # SSE 관련 설정 (진행률 모니터링용) server { # ... location /api/progress { proxy_pass http://app_servers; proxy_http_version 1.1; proxy_set_header Connection ''; proxy_buffering off; proxy_cache off; proxy_read_timeout 24h; # SSE 연결 유지를 위한 긴 타임아웃 } # 일반 API 엔드포인트 location /api { proxy_pass http://app_servers; proxy_http_version 1.1; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; } } }
HAProxy 설정 예시
global maxconn 10000 defaults timeout connect 10s timeout client 30m # 클라이언트 타임아웃 증가 timeout server 30m # 서버 타임아웃 증가 frontend http-in bind *:80 default_backend app_servers backend app_servers balance source # IP 기반 세션 고정 option http-server-close server app1 app1.example.com:3000 check server app2 app2.example.com:3000 check # 추가 서버...
Node.js 서버에서도 고려할 점
로드밸런서를 추가하더라도 Node.js 서버 자체에서도 다음 설정을 확인해야 합니다:
// app.js 또는 서버 설정 파일 const server = http.createServer(app); // 연결 시간 제한 증가 server.keepAliveTimeout = 60000; // 60초 server.headersTimeout = 65000; // 65초 // Express나 다른 미들웨어 설정 app.use(express.json()); app.use(express.urlencoded({ extended: true }));
현재 코드에서는 SSE를 사용한 업로드 진행 모니터링이 있으므로, 특히 이 부분이 로드밸런서를 통해 제대로 작동하는지 확인하는 것이 중요합니다. 로드밸런서는 SSE 연결을 장시간 유지할 수 있도록 설정해야 합니다.
로드밸런서만 추가해도 기본적인 동작은 가능하지만, 효율적인 운영을 위해서는 로드밸런서와 Node.js 서버 모두에서 연결 수, 타임아웃, 세션 지속성 등의 설정을 적절히 조정해야 합니다.
타임아웃 설정시 일관성이 필요합니다. SSE 연결이 제대로 유지되려면 Node.js 서버의 타임아웃도 로드밸런서의 타임아웃과 일치하거나 그보다 길어야 합니다.
// Node.js 서버 설정 const server = http.createServer(app); // SSE 연결을 위한 긴 타임아웃 설정 server.keepAliveTimeout = 86400000; // 24시간 (밀리초 단위) server.headersTimeout = 86460000; // 약간 더 길게 설정 (24시간 + 1분)
현재 구조에서는 다음과 같은 타임아웃 설정이 일관성 있게 적용되어야 합니다:
- 로드밸런서(Nginx/HAProxy): 24시간 타임아웃
- Node.js 서버: 24시간 타임아웃
- 업로드 상태 관리: 코드에서
expiresIn: 6 * 60 * 60
(6시간)으로 설정되어 있음
특히 uploadStateService
에서는 비활성 상태에 대한 타임아웃이 6시간으로 설정되어 있는데, 이 시간도 일관성 있게 조정하는 것이 좋습니다.
리소스 관리 측면에서는 실제 사용 패턴에 따라 이 타임아웃 값을 조정해야 합니다. 대부분의 업로드가 몇 시간 내에 완료된다면, 24시간보다 짧게 설정하는 것이 리소스 낭비를 줄일 수 있습니다.