Apache + Tomcat Integration
mod_jk, mod_proxy, AJP 기반 Apache-Tomcat 연동
📚 시리즈 네비게이션
| 이전 | 현재 | 다음 |
|---|---|---|
| Apache vs Nginx | Apache + Tomcat | Nginx + Tomcat |
→ 시리즈 목차
🎯 왜 연동하는가?
Tomcat 단독으로도 서비스 가능하지만, Apache를 앞에 두는 이유:
| 이유 | 설명 |
|---|---|
| 정적 파일 처리 | Apache가 정적 파일 처리에 효율적 |
| SSL 종료 | Apache에서 SSL 처리, Tomcat은 HTTP만 |
| 로드밸런싱 | 다중 Tomcat 분산 |
| 보안 | Tomcat 직접 노출 방지 |
| URL Rewrite | mod_rewrite 활용 |
| 가상 호스트 | 여러 도메인 처리 |
🔌 연동 방식 비교
| 방식 | 프로토콜 | 특징 | 권장 |
|---|---|---|---|
| mod_jk | AJP | 전통적, 설정 복잡 | △ |
| mod_proxy_ajp | AJP | mod_proxy + AJP | ○ |
| mod_proxy_http | HTTP | 간단, 범용적 | ◎ |
AJP vs HTTP
| 항목 | AJP | HTTP |
|---|---|---|
| 프로토콜 | 바이너리 | 텍스트 |
| 성능 | 약간 빠름 | 약간 느림 |
| 설정 | 복잡 | 간단 |
| 디버깅 | 어려움 | 쉬움 (tcpdump 가능) |
| 방화벽 | 8009 포트 | 8080 포트 |
| 보안 | 취약점 이슈 있었음 | 상대적 안전 |
권장: 최근에는 mod_proxy_http를 더 많이 사용. AJP는 레거시 환경에서 주로 사용함.
⚙️ 방법 1: mod_jk (레거시)
개요
mod_jk는 Apache Tomcat Connector 프로젝트의 일부로, AJP 프로토콜로 통신함.
설치
# CentOS/RHEL
yum install mod_jk
# Ubuntu/Debian
apt install libapache2-mod-jk
# 또는 소스 컴파일
# https://tomcat.apache.org/connectors-doc/
Tomcat 설정 (server.xml)
AJP Connector 활성화:
<!-- $CATALINA_HOME/conf/server.xml -->
<Connector port="8009"
protocol="AJP/1.3"
redirectPort="8443"
secretRequired="false"
address="127.0.0.1" />
⚠️ 보안:
address="127.0.0.1"로 로컬만 허용하거나,secret설정 필요.
Apache 설정
workers.properties:
# /etc/httpd/conf/workers.properties
# Worker 목록
worker.list=tomcat1
# Worker 설정
worker.tomcat1.type=ajp13
worker.tomcat1.host=127.0.0.1
worker.tomcat1.port=8009
worker.tomcat1.lbfactor=1
httpd.conf 또는 가상호스트:
# mod_jk 로드
LoadModule jk_module modules/mod_jk.so
# workers.properties 위치
JkWorkersFile /etc/httpd/conf/workers.properties
# 로그 설정
JkLogFile /var/log/httpd/mod_jk.log
JkLogLevel info
# URL 매핑
JkMount /*.jsp tomcat1
JkMount /api/* tomcat1
JkMount /app/* tomcat1
# 정적 파일은 Apache가 처리 (매핑하지 않음)
# /images, /css, /js 등
uriworkermap.properties (선택):
# /etc/httpd/conf/uriworkermap.properties
# Tomcat으로 보낼 요청
/*.jsp=tomcat1
/api/*=tomcat1
/app/*=tomcat1
# Apache가 처리 (제외)
!/images/*=tomcat1
!/css/*=tomcat1
!/js/*=tomcat1
!/*.html=tomcat1
# httpd.conf에 추가
JkMountFile /etc/httpd/conf/uriworkermap.properties
로드밸런싱 (mod_jk)
# workers.properties
# Worker 목록 (로드밸런서 + 실제 워커들)
worker.list=loadbalancer
# Tomcat 인스턴스들
worker.tomcat1.type=ajp13
worker.tomcat1.host=192.168.1.10
worker.tomcat1.port=8009
worker.tomcat1.lbfactor=1
worker.tomcat2.type=ajp13
worker.tomcat2.host=192.168.1.11
worker.tomcat2.port=8009
worker.tomcat2.lbfactor=1
# 로드밸런서
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=tomcat1,tomcat2
worker.loadbalancer.sticky_session=true
# httpd.conf
JkMount /* loadbalancer
⚙️ 방법 2: mod_proxy_ajp
개요
Apache 기본 mod_proxy를 사용하여 AJP 연동. mod_jk보다 설정이 간단함.
Apache 설정
# 모듈 로드
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
<VirtualHost *:80>
ServerName example.com
# 정적 파일은 Apache가 처리
DocumentRoot /var/www/html
# 동적 요청은 Tomcat으로
ProxyPass /api ajp://127.0.0.1:8009/api
ProxyPassReverse /api ajp://127.0.0.1:8009/api
ProxyPass /app ajp://127.0.0.1:8009/app
ProxyPassReverse /app ajp://127.0.0.1:8009/app
</VirtualHost>
로드밸런싱 (mod_proxy_ajp)
<Proxy balancer://tomcat-cluster>
BalancerMember ajp://192.168.1.10:8009 route=tomcat1
BalancerMember ajp://192.168.1.11:8009 route=tomcat2
ProxySet lbmethod=byrequests
ProxySet stickysession=JSESSIONID
</Proxy>
<VirtualHost *:80>
ServerName example.com
ProxyPass / balancer://tomcat-cluster/
ProxyPassReverse / balancer://tomcat-cluster/
</VirtualHost>
⚙️ 방법 3: mod_proxy_http (권장)
개요
HTTP 프로토콜로 연동. 가장 간단하고 범용적임.
Tomcat 설정
HTTP Connector만 있으면 됨 (기본 활성화):
<!-- $CATALINA_HOME/conf/server.xml -->
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
Apache 설정
# 모듈 로드
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
# Proxy 설정
ProxyPreserveHost On
ProxyRequests Off
# 동적 요청 → Tomcat
ProxyPass /api http://127.0.0.1:8080/api
ProxyPassReverse /api http://127.0.0.1:8080/api
ProxyPass /app http://127.0.0.1:8080/app
ProxyPassReverse /app http://127.0.0.1:8080/app
# 정적 파일은 Apache에서 직접 처리
<Directory /var/www/html>
Require all granted
</Directory>
</VirtualHost>
전체 요청 프록시
<VirtualHost *:80>
ServerName example.com
ProxyPreserveHost On
ProxyRequests Off
# 정적 파일 제외
ProxyPassMatch ^/images !
ProxyPassMatch ^/css !
ProxyPassMatch ^/js !
# 나머지는 Tomcat으로
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
# 정적 파일 위치
Alias /images /var/www/static/images
Alias /css /var/www/static/css
Alias /js /var/www/static/js
</VirtualHost>
로드밸런싱 (mod_proxy_http)
<Proxy balancer://tomcat-cluster>
BalancerMember http://192.168.1.10:8080 route=tomcat1
BalancerMember http://192.168.1.11:8080 route=tomcat2
ProxySet lbmethod=byrequests
ProxySet stickysession=JSESSIONID
</Proxy>
<VirtualHost *:80>
ServerName example.com
ProxyPreserveHost On
ProxyPass / balancer://tomcat-cluster/
ProxyPassReverse / balancer://tomcat-cluster/
</VirtualHost>
로드밸런싱 알고리즘:
| lbmethod | 설명 |
|---|---|
| byrequests | 요청 수 기반 (기본) |
| bytraffic | 트래픽 양 기반 |
| bybusyness | 활성 요청 수 기반 |
| heartbeat | 하트비트 기반 |
🔒 SSL 설정
Apache에서 SSL 종료
<VirtualHost *:443>
ServerName example.com
# SSL 설정
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/server.crt
SSLCertificateKeyFile /etc/pki/tls/private/server.key
SSLCertificateChainFile /etc/pki/tls/certs/chain.crt
# Tomcat으로 프록시 (HTTP)
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
# 헤더 추가 (Tomcat이 HTTPS임을 인식)
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
</VirtualHost>
# HTTP → HTTPS 리다이렉트
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://example.com/
</VirtualHost>
Tomcat 설정 (프록시 인식)
<!-- server.xml의 Connector -->
<Connector port="8080"
protocol="HTTP/1.1"
proxyName="example.com"
proxyPort="443"
scheme="https"
secure="true" />
또는 RemoteIpValve 사용:
<!-- server.xml의 Engine 또는 Host 내부 -->
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto" />
🩺 트러블슈팅
연결 안 됨
# Tomcat 포트 확인
netstat -tlnp | grep 8080
netstat -tlnp | grep 8009
# Tomcat 로그 확인
tail -f $CATALINA_HOME/logs/catalina.out
# Apache 에러 로그
tail -f /var/log/httpd/error_log
503 Service Unavailable
- Tomcat이 실행 중인지 확인
- 방화벽 확인:
firewall-cmd --list-all - SELinux 확인:
setsebool -P httpd_can_network_connect 1
AJP 연결 문제
# AJP 포트 확인
telnet 127.0.0.1 8009
# Tomcat 9+ AJP 보안 설정 확인
# secretRequired="false" 또는 secret 설정 필요
타임아웃
# Apache에서 타임아웃 늘리기
ProxyTimeout 300
Timeout 300
# 또는 ProxyPass에서
ProxyPass / http://127.0.0.1:8080/ timeout=300
세션 유지 안 됨 (로드밸런싱)
Tomcat의 jvmRoute 설정:
<!-- server.xml -->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
# Apache에서 route 매칭
BalancerMember http://192.168.1.10:8080 route=tomcat1
📋 설정 체크리스트
| 항목 | 확인 |
|---|---|
| Tomcat Connector 활성화 (8080 또는 8009) | ☐ |
| Apache 모듈 로드 (mod_proxy, mod_proxy_http) | ☐ |
| 방화벽 포트 허용 | ☐ |
| SELinux 설정 (httpd_can_network_connect) | ☐ |
| ProxyPreserveHost 설정 | ☐ |
| SSL 사용 시 X-Forwarded-Proto 헤더 | ☐ |
| 로드밸런싱 시 sticky session | ☐ |
🔗 시리즈 네비게이션
| 이전 | 다음 |
|---|---|
| Apache vs Nginx | Nginx + Tomcat Integration |