Apache httpd-Tomcat mod_proxy_ajp 연동
Apache HTTP Server의 mod_proxy_ajp로 Tomcat AJP Connector에 연결하는 방식과 mod_jk와의 차이를 정리한다.
mod_proxy_ajp 요청 경로
Client
-> Apache HTTP Server
-> mod_proxy / mod_proxy_ajp
-> Tomcat AJP Connector
mod_proxy_ajp는 Apache HTTP Server의 mod_proxy 계열 모듈로, HTTP가 아니라 AJP 프로토콜로
Tomcat에 요청을 전달한다.
연동 방식 요약
mod_proxy_ajp는 ProxyPass 문법을 사용하지만 backend URL에 ajp://를 쓴다. 설정 형태는
mod_proxy_http와 비슷하고, 실제 연결은 Tomcat의 AJP Connector로 들어간다.
mod_proxy_http, mod_proxy_ajp, mod_jk 비교
| 방식 | backend | 주요 설정 | 특징 |
|---|---|---|---|
mod_proxy_http | Tomcat HTTP Connector | ProxyPass http://... | 단순하고 curl로 backend 점검이 쉬움 |
mod_proxy_ajp | Tomcat AJP Connector | ProxyPass ajp://... | Apache 내장 proxy 문법으로 AJP 연결 |
mod_jk | Tomcat AJP Connector | JkMount, workers.properties | 별도 worker 설정과 JK 로그를 사용 |
새로 구성한다면 HTTP reverse proxy가 보통 단순하다. 다만 기존 운영 환경에서 AJP를 써야 하고
mod_jk까지는 필요하지 않다면 mod_proxy_ajp를 만날 수 있다.
필요한 모듈
| 모듈 | 역할 |
|---|---|
mod_proxy | 프록시 공통 기능 |
mod_proxy_ajp | AJP backend 연결 |
mod_proxy_balancer | 여러 AJP backend로 분산할 때 필요 |
mod_ssl | HTTPS 종료가 Apache HTTP Server에서 일어날 때 필요 |
apachectl -M | grep proxy
proxy_module과 proxy_ajp_module이 보여야 한다.
기본 설정
<VirtualHost *:80>
ServerName example.com
ProxyRequests Off
ProxyPass "/app" "ajp://127.0.0.1:8009/app" secret=change-this-secret
ErrorLog logs/example-error.log
CustomLog logs/example-access.log combined
</VirtualHost>
mod_proxy_ajp는 ProxyPassReverse가 항상 필요한 것은 아니다. 다만 앞단 경로와 Tomcat Context 경로가
다르면 redirect header 보정이 필요할 수 있다.
Tomcat AJP Connector
<Connector protocol="AJP/1.3"
address="127.0.0.1"
port="8009"
secretRequired="true"
secret="change-this-secret" />
AJP는 외부에 직접 노출하지 않는다. address로 바인딩 범위를 제한하고, Apache HTTP Server와 Tomcat의
secret 값을 맞춘다.
로드밸런싱 예시
<Proxy "balancer://ajp_cluster">
BalancerMember "ajp://10.0.0.11:8009" secret=change-this-secret loadfactor=1
BalancerMember "ajp://10.0.0.12:8009" secret=change-this-secret loadfactor=1
ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
ServerName example.com
ProxyPass "/app" "balancer://ajp_cluster/app"
</VirtualHost>
세션을 Tomcat 메모리에만 저장한다면 sticky session이 필요한지 확인한다. 이 부분은 mod_jk와 마찬가지로
Tomcat의 route 설정과 함께 봐야 한다.
장애별 확인
| 증상 | 확인 지점 |
|---|---|
| 503 | AJP backend down, Tomcat 미기동, worker 연결 실패 |
| 403 / 거부 | AJP secret 불일치, address 제한, 방화벽 |
| 404 | ProxyPass 경로와 Tomcat Context 경로 불일치 |
| redirect 이상 | 앞단 path와 backend path 차이, ProxyPassReverse 필요 여부 |
| 간헐적 오류 | connection reuse, timeout, Tomcat thread |
점검 명령
apachectl configtest
apachectl -M | grep proxy
ss -lntp | grep 8009
tail -f /var/log/httpd/error_log
tail -f $CATALINA_BASE/logs/catalina.out
AJP는 HTTP처럼 브라우저나 curl로 바로 확인하기 어렵다. 그래서 Apache error log와 Tomcat log를
같은 시간대에서 같이 보는 것이 중요하다.
관련 블로그 기록
- 폐쇄망에서 서버 시간 맞추기 — Web Server와 WAS 로그를 같은 시간축에서 비교하기 위한 기반 사례
- Tomcat Catalina.out 파일 용량 증가 문제 해결 — Tomcat 로그 운영 사례
공식 문서
닫기 전 질문
- 지금 AJP 연동은
mod_jk인가,mod_proxy_ajp인가? - Apache HTTP Server와 Tomcat의 AJP secret은 일치하는가?
- AJP 포트는 외부에 노출되지 않고 내부 통신으로만 제한되어 있는가?
- 앞단 URL 경로와 Tomcat Context 경로는 같은가, 다르면 redirect 보정이 필요한가?