웹(아파치 HTTPD/Nginx) ↔ WAS(Tomcat 등) 사이를 mod_jk + AJP로 연동하는 구조
AJP(ajp13): 웹서버와 WAS 간 이진(Binary) 프로토콜. HTTP보다 헤더 전달·세션 스티키 등 게이트웨이 최적화에 유리.
mod_jk: Apache HTTPD 모듈. AJP 커넥터로 WAS에게 요청을 넘기고, 응답을 되돌려줌.
장점: 성능/안정성, 세션 스티키/로드밸런싱, 상태 모니터링(jk-status).
대안: mod_proxy_ajp(간단) 또는 mod_proxy_http(HTTP로 연결). 새 환경에선 proxy 계열을 권장하는 경우도 많습니다.
---
아키텍처
[Client] --HTTP/HTTPS--> [Apache HTTPD + mod_jk] --AJP/8009--> [Tomcat/WAS]
정적 파일은 HTTPD가 직접 서비스
동적 요청(URL 패턴 매칭)은 AJP로 WAS에 포워딩
---
구성 단계 (Apache + Tomcat 예시)
1) Tomcat: AJP 커넥터 활성화
server.xml (Tomcat 9 이상은 기본이 비활성/주석인 경우 많음)
<Connector protocol="AJP/1.3"
address="127.0.0.1"
port="8009"
secretRequired="true"
secret="YOUR_AJP_SECRET"
redirectPort="8443" />
포인트
address는 가능하면 루프백(127.0.0.1) 또는 내부망 IP로 제한
secretRequired=true + secret 설정(보안 필수)
방화벽으로 8009 포트 접근 제어
2) Apache: mod_jk 로드 & 기본 설정
httpd.conf 또는 conf.modules.d/ 등
LoadModule jk_module modules/mod_jk.so
# mod_jk 로그
JkLogFile logs/mod_jk.log
JkLogLevel info # (debug로 높여 진단 가능)
JkShmFile logs/mod_jk.shm # 공유메모리(상태/로드밸런싱)
JkWorkersFile conf/workers.properties
3) workers.properties (WAS 대상 정의 & LB)
conf/workers.properties
# 대상 워커 목록
worker.list=loadbalancer,jkstatus
# 톰캣 개별 워커
worker.app1.type=ajp13
worker.app1.host=127.0.0.1
worker.app1.port=8009
worker.app1.secret=YOUR_AJP_SECRET
worker.app1.socket_timeout=20
worker.app1.connection_pool_size=50
# 로드밸런서(스티키 세션)
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=app1
worker.loadbalancer.sticky_session=1
# 상태 페이지
worker.jkstatus.type=status
4) URL 매핑(어떤 요청을 AJP로 보낼지)
가상호스트 혹은 서버 컨텍스트에:
# /app 아래는 WAS로
JkMount /app/* loadbalancer
# jk-status 모니터링 (관리 IP만 허용)
<Location /jkstatus>
JkMount jkstatus
Require ip 10.0.0.0/8
</Location>
이제 https://www.example.com/app/... 요청은 AJP로 Tomcat에 전달됩니다.
---
세션, 헤더, HTTPS 처리 포인트
스티키 세션: worker.loadbalancer.sticky_session=1
Tomcat jvmRoute(server.xml의 Engine에 jvmRoute="app1" 등)와 세션ID(JSESSIONID)의 route를 일치시켜야 함.
원본 클라이언트 IP: AJP는 AJP_REMOTE_ADDR/x-forwarded-for를 넘깁니다. 앱/로그에서 원 IP가 필요하면
Apache에 RemoteIPHeader X-Forwarded-For(mod_remoteip)
Tomcat에 RemoteIpValve 설정을 고려
HTTPS 종단(Offload): HTTPS를 Apache에서 종단하고 AJP로 백엔드에 전달 시, Tomcat에 proxyPort, proxyName, secure="true", scheme="https" 설정 또는 RemoteIpValve로 스킴/포트 보정.
---
보안 체크리스트 (매우 중요)
AJP 포트 외부 노출 금지(방화벽/보안그룹)
secretRequired=true + 강한 secret 사용
바인딩 주소 제한: address="127.0.0.1" 또는 내부망 IP
업데이트: Tomcat/Apache 최신 보안 패치 (과거 AJP 취약점 Ghostcat/CVE-2020-1938 이슈 상기)
jk-status 접근제어 필수
---
성능·안정화 팁
커넥션 풀: connection_pool_size, connection_pool_timeout 조정
타임아웃: socket_timeout, reply_timeout으로 백엔드 지연 방지
패킷 크기: 대형 헤더/쿠키 많으면 Tomcat maxHttpHeaderSize(HTTP)처럼 AJP 쪽도 환경 고려
헬스체크: worker.app1.ping_mode=A 등 ping 설정(빌드에 따라 지원 옵션 상이)
로그: mod_jk.log(Apache 측), catalina.out/localhost_access_log(Tomcat) 교차 확인
---
트러블슈팅 빠른 가이드
503/Service Unavailable: WAS 다운/방화벽/secret 불일치/포트 오류 → mod_jk.log에 원인 표기
원본 IP가 모두 127.0.0.1: XFF 처리/RemoteIpValve 미설정 → 헤더/밸브 설정 보완
세션 끊김: sticky_session과 jvmRoute 불일치, 다중 노드 라우팅 문제 점검
URL 안 넘어감/404: JkMount 패턴, Tomcat Context 경로(/app) 일치 확인
---
mod_proxy_ajp/HTTP로 대체 시 비교
mod_proxy_ajp: 설정 단순, 아키텍처 비슷. mod_jk의 세밀한 튜닝 기능은 일부 덜함.
mod_proxy_http: HTTP로 백엔드 연결(방화벽·관찰성 용이), 현대 환경에서 L7 표준화 장점.