Apache mod_proxy_balancer 로드밸런싱
Apache HTTPD는 mod_proxy_balancer 모듈을 통해 강력한 로드밸런싱 기능을 제공합니다. balancer:// 스킴으로 업스트림 그룹을 정의하고, 다양한 분산 알고리즘(lbmethod)으로 요청을 분배할 수 있습니다.
필요 모듈 활성화
Apache에서 로드밸런싱을 사용하려면 다음 모듈이 활성화되어야 합니다.
# Ubuntu/Debian
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests # Round Robin
sudo a2enmod lbmethod_bytraffic # 트래픽 기반
sudo a2enmod lbmethod_bybusyness # 최소 연결
sudo a2enmod slotmem_shm # 공유 메모리 (balancer 필수)
sudo systemctl restart apache2
# CentOS/RHEL (httpd.conf에서 주석 해제)
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
모듈 활성화 확인:
apache2ctl -M | grep -E "proxy|balancer|lbmethod"
기본 로드밸런서 구성
가장 단순한 설정 (byrequests)
# /etc/apache2/sites-available/load-balancer.conf
<VirtualHost *:80>
ServerName example.com
ProxyRequests Off
ProxyPreserveHost On
# 업스트림 그룹 정의
<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080"
BalancerMember "http://10.0.0.2:8080"
BalancerMember "http://10.0.0.3:8080"
ProxySet lbmethod=byrequests # Round Robin
</Proxy>
# 모든 요청을 로드밸런서로 전달
ProxyPass "/" "balancer://mycluster/"
ProxyPassReverse "/" "balancer://mycluster/"
</VirtualHost>
lbmethod 알고리즘 상세
byrequests (요청 수 기반, Round Robin)
각 서버가 처리한 요청 수를 기준으로 가중치에 따라 분배합니다. 기본적으로 Round Robin과 동일하게 동작합니다.
<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080" loadfactor=3
BalancerMember "http://10.0.0.2:8080" loadfactor=1
ProxySet lbmethod=byrequests
</Proxy>
loadfactor는 Nginx의 weight와 동일한 역할입니다. 위 설정에서 App1은 전체의 75%, App2는 25%를 처리합니다.
bytraffic (트래픽 바이트 기반)
처리한 트래픽(바이트)을 기준으로 분배합니다. 파일 다운로드처럼 응답 크기가 크게 다를 때 유용합니다.
<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080"
BalancerMember "http://10.0.0.2:8080"
ProxySet lbmethod=bytraffic
</Proxy>
100MB 파일을 받는 요청과 1KB API 응답을 받는 요청이 혼재할 때, byrequests는 단순히 요청 수를 세지만 bytraffic은 실제 처리한 데이터량을 기준으로 합니다. 이미지·동영상 서빙 서버에 적합합니다.
bybusyness (최소 활성 요청)
현재 처리 중인 요청 수가 가장 적은 서버로 보냅니다. Nginx의 least_conn과 유사합니다.
<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080"
BalancerMember "http://10.0.0.2:8080"
BalancerMember "http://10.0.0.3:8080"
ProxySet lbmethod=bybusyness
</Proxy>
응답 시간이 긴 API 서버나 DB 쿼리가 많은 백엔드에 적합합니다.
heartbeat (헬스비트 기반, 실험적)
백엔드 서버에서 보내는 헬스비트 정보를 바탕으로 부하를 판단합니다. mod_heartbeat, mod_heartmonitor 모듈과 함께 사용합니다. 특수한 환경에서만 사용하므로 일반적으로는 위 세 가지 중 선택합니다.
BalancerMember 파라미터 완전 정리
<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080"
loadfactor=3 # 가중치 (기본값: 1, 높을수록 요청 많이 받음)
retry=60 # 장애 후 재시도 간격(초), 0이면 무한 배제
timeout=30 # 연결 타임아웃(초)
acquire=3000 # 연결 대기 최대 시간(ms)
max=100 # 최대 동시 연결 수
ttl=60 # 유휴 연결 유지 시간(초)
route=jvm1 # mod_jk와 연동 시 JVM 라우트 ID
status=+H # 상태 강제 설정 (H=Hot Standby, D=Disabled, S=Stop, I=Ignore errors)
BalancerMember "http://10.0.0.2:8080" loadfactor=1 status=+H
# +H: Hot Standby — 다른 모든 서버 다운 시에만 사용
ProxySet lbmethod=bybusyness
ProxySet stickysession=JSESSIONID # 세션 고정
</Proxy>
status 플래그 설명
| 플래그 | 의미 | 사용 시기 |
|---|---|---|
+D | Disabled | 수동 점검 시 트래픽 차단 |
+H | Hot Standby | 예비 서버 (평시에는 사용 안 함) |
+S | Stopped | 새 연결 차단, 기존 연결 유지 |
+I | Ignore errors | 오류 무시 (헬스체크 제외) |
-D | 플래그 제거 | 다시 활성화 |
Sticky Session (세션 고정)
세션 기반 애플리케이션에서 같은 사용자가 항상 같은 서버로 연결되도록 설정합니다.
쿠키 기반 Sticky Session (권장)
<Proxy "balancer://mycluster">
BalancerMember "http://10.0.0.1:8080" route=server1
BalancerMember "http://10.0.0.2:8080" route=server2
BalancerMember "http://10.0.0.3:8080" route=server3
ProxySet lbmethod=byrequests
ProxySet stickysession=JSESSIONID # Tomcat 기본 세션 쿠키명
</Proxy>
Tomcat의 server.xml에서 jvmRoute를 설정해야 합니다:
<!-- server.xml -->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="server1">
이렇게 하면 Tomcat이 세션 ID에 .server1을 붙여 반환합니다:
Set-Cookie: JSESSIONID=ABC123.server1; Path=/
Apache는 이 쿠키를 읽어 route=server1인 서버로 라우팅합니다.
URL 기반 Sticky Session
쿠키를 사용할 수 없는 환경에서 URL에 라우팅 정보를 포함합니다:
ProxySet stickysession=jsessionid|JSESSIONID # URL 파라미터명|쿠키명
URL 예시: http://example.com/app;jsessionid=ABC123.server1
Balancer Manager (웹 관리 인터페이스)
Apache는 브라우저에서 로드밸런서 상태를 모니터링하고 실시간으로 설정을 변경할 수 있는 관리 페이지를 제공합니다.
# /etc/apache2/conf-available/balancer-manager.conf
<Location "/balancer-manager">
SetHandler balancer-manager
Require ip 127.0.0.1 10.0.0.0/8 # 내부 네트워크만 접근 허용
</Location>
# Ubuntu
sudo a2enconf balancer-manager
sudo systemctl reload apache2
# 접속
curl http://localhost/balancer-manager
관리 페이지에서 할 수 있는 작업:
- 각 서버의 상태, 요청 수, 오류 수 확인
- 서버 비활성화/활성화 (점검 중 사용)
- 가중치(loadfactor) 실시간 변경
- 세션 데이터 초기화
실전 구성: 완전한 로드밸런서 설정
# /etc/apache2/sites-available/production-lb.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ProxyRequests Off
ProxyPreserveHost On
# 헤더 설정
Header add X-Forwarded-Proto "http"
RequestHeader set X-Forwarded-Proto "http"
# 메인 앱 클러스터
<Proxy "balancer://appcluster">
BalancerMember "http://10.0.0.1:8080" loadfactor=3 retry=5 route=jvm1
BalancerMember "http://10.0.0.2:8080" loadfactor=3 retry=5 route=jvm2
BalancerMember "http://10.0.0.3:8080" loadfactor=1 retry=5 route=jvm3 status=+H
ProxySet lbmethod=bybusyness
ProxySet stickysession=JSESSIONID
ProxySet nofailover=Off
</Proxy>
# 정적 파일 클러스터
<Proxy "balancer://staticcluster">
BalancerMember "http://10.0.1.1:80" loadfactor=1
BalancerMember "http://10.0.1.2:80" loadfactor=1
ProxySet lbmethod=byrequests
</Proxy>
# 정적 파일: 별도 클러스터
ProxyPass "/static/" "balancer://staticcluster/static/"
ProxyPassReverse "/static/" "balancer://staticcluster/static/"
# 관리자 페이지: 단일 서버 (로드밸런싱 제외)
ProxyPass "/admin/" "http://10.0.0.1:8080/admin/"
ProxyPassReverse "/admin/" "http://10.0.0.1:8080/admin/"
# 나머지 모든 요청: 앱 클러스터
ProxyPass "/" "balancer://appcluster/"
ProxyPassReverse "/" "balancer://appcluster/"
# 타임아웃 설정
ProxyTimeout 60
# 에러 페이지
ErrorDocument 503 /error/503.html
ProxyPass "/error/" "!" # /error/는 로컬 처리
# Balancer Manager (내부 접근만 허용)
<Location "/balancer-manager">
SetHandler balancer-manager
Require ip 127.0.0.1 10.0.0.0/8
</Location>
# 로그
CustomLog /var/log/apache2/lb-access.log combined
ErrorLog /var/log/apache2/lb-error.log
</VirtualHost>
설정 검증 및 테스트
# 설정 문법 확인
sudo apache2ctl configtest
# 적용
sudo systemctl reload apache2
# 로드밸런싱 동작 확인
for i in {1..9}; do
curl -s -o /dev/null -w "%{http_code} - upstream\n" http://example.com/
done
# 로그에서 백엔드 서버 확인 (mod_proxy는 X-Forwarded-For 헤더에 기록)
tail -f /var/log/apache2/lb-access.log
# 현재 balancer 상태 확인
curl -s http://localhost/balancer-manager | grep -E "worker|status|loadfactor"
알고리즘 선택 가이드
| 상황 | 권장 lbmethod |
|---|---|
| 단순 균등 분배, 동일 스펙 서버 | byrequests |
| 파일 다운로드, 미디어 스트리밍 | bytraffic |
| API 서버, 처리 시간 불균일 | bybusyness |
| 세션 공유 없는 기존 앱 | byrequests + stickysession |
다음 페이지에서는 mod_jk를 이용한 AJP 기반 로드밸런싱을 알아봅니다.