④ IT 스타트 (IT Competence)/WEB_WAS

웹(아파치 HTTPD/Nginx) ↔ WAS(Tomcat 등) 사이를 mod_jk + AJP로 연동하는 구조

->^_^<- 2025. 9. 19. 14:19
반응형


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 표준화 장점.


반응형