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_ajpProxyPass 문법을 사용하지만 backend URL에 ajp://를 쓴다. 설정 형태는 mod_proxy_http와 비슷하고, 실제 연결은 Tomcat의 AJP Connector로 들어간다.

mod_proxy_http, mod_proxy_ajp, mod_jk 비교

방식backend주요 설정특징
mod_proxy_httpTomcat HTTP ConnectorProxyPass http://...단순하고 curl로 backend 점검이 쉬움
mod_proxy_ajpTomcat AJP ConnectorProxyPass ajp://...Apache 내장 proxy 문법으로 AJP 연결
mod_jkTomcat AJP ConnectorJkMount, workers.properties별도 worker 설정과 JK 로그를 사용

새로 구성한다면 HTTP reverse proxy가 보통 단순하다. 다만 기존 운영 환경에서 AJP를 써야 하고 mod_jk까지는 필요하지 않다면 mod_proxy_ajp를 만날 수 있다.

필요한 모듈

모듈역할
mod_proxy프록시 공통 기능
mod_proxy_ajpAJP backend 연결
mod_proxy_balancer여러 AJP backend로 분산할 때 필요
mod_sslHTTPS 종료가 Apache HTTP Server에서 일어날 때 필요
apachectl -M | grep proxy

proxy_moduleproxy_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_ajpProxyPassReverse가 항상 필요한 것은 아니다. 다만 앞단 경로와 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 설정과 함께 봐야 한다.

장애별 확인

증상확인 지점
503AJP backend down, Tomcat 미기동, worker 연결 실패
403 / 거부AJP secret 불일치, address 제한, 방화벽
404ProxyPass 경로와 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를 같은 시간대에서 같이 보는 것이 중요하다.

관련 블로그 기록

공식 문서

닫기 전 질문

  • 지금 AJP 연동은 mod_jk인가, mod_proxy_ajp인가?
  • Apache HTTP Server와 Tomcat의 AJP secret은 일치하는가?
  • AJP 포트는 외부에 노출되지 않고 내부 통신으로만 제한되어 있는가?
  • 앞단 URL 경로와 Tomcat Context 경로는 같은가, 다르면 redirect 보정이 필요한가?