mod_proxy_http.so 를 이용한 Apache httpd 와 Apache Tomcat 연동
1. mod_proxy_http.so 모듈 활성화
1.1. Apache httpd 를 컴파일해서 설치한 경우
conf/httpd.conf 에서 다음을 찾아 주석을 풀어준다.
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so
2개 이상의 Apache Tomcat 과 연동하는 경우 다음의 항목들도 찾아서 주석을 해제한다.
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so LoadModule slotmem_shm_module modules/mod_slotmem_shm.so LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
1.2. Ubuntu 에서 apt 로 Apache httpd 를 설치한 경우
다음과 같은 명령을 실행한다.
sudo a2enmod proxy sudo a2enmod proxy_http
2개 이상의 Apache Tomcat 과 연동하는 경우 다음의 명령들도 실행한다.
sudo a2enmod proxy_balancer sudo a2enmod slotmem_shm sudo a2enmod lbmethod_byrequests
2. 설정
2.1. localhost 에 1개의 Apache Tomcat 을 두는 경우
VirtualHost 내에 다음과 같이 추가한다.
<VirtualHost 0.0.0.0:80> ProxyPass / http://localhost:8080/ ProxyPassReverse / http://localhost:8080/ ProxyRequests Off </VirtualHost>
필수는 아니지만, 다음과 같은 것들도 추가할 수 있다.
RequestHeader set X-Forwarded-Secure-Request "false" RequestHeader set X-Forwarded-Proto "http" RequestHeader set X-Forwarded-Port "80"
https(포트 443) 인 경우는 다음과 같다.
RequestHeader set X-Forwarded-Secure-Request "true" RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-Port "443"
ProxyPreserveHost on 을 추가하면
ServerAlias 로 요청이 들어온 경우
Apache Tomcat 에 ServerAlias 로 요청을 보낸다.
ProxyPreserveHost on 을 설정했다면,
Apache Tomcat 의 server.xml 에서 <Host> 아래에 <Alias> 를 추가해서,
Apache httpd 와 Apache Tomcat 의 가상 호스트 설정을 동일하게 해야 한다.
만약, Apache Tomcat 에 manager 와 같은 context 를 차단하고 싶다면, VirtualHost 에 다음과 같은 설정을 추가할 수 있다.
ProxyPass /docs ! ProxyPass /examples ! ProxyPass /host-manager ! ProxyPass /manager !
2.2. 2개 이상의 Apache Tomcat 을 두는 경우
<VirtualHost 0.0.0.0:443> ProxyPass / balancer://mytomcatcluster/ ProxyPassReverse / balancer://mytomcatcluster/ <Proxy balancer://mytomcatcluster> BalancerMember http://localhost:8080 BalancerMember http://192.168.0.2:8080 </Proxy> </VirtualHost>
필수는 아니지만, 다음과 같은 것들도 추가할 수 있다.
ProxyRequests Off RequestHeader set X-Forwarded-Secure-Request "true" RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-Port "443"
만약, Apache Tomcat 에 manager 와 같은 context 를 차단하고 싶다면, VirtualHost 에 다음과 같은 설정을 추가할 수 있다.
ProxyPass /docs ! ProxyPass /examples ! ProxyPass /host-manager ! ProxyPass /manager !
2.3. Sticky Session 설정
다음과 같이 Apache Tomcat 의 conf/server.xml 의 <Engine> 항목에
jvmRoute 속성을 추가하고, Apache Tomcat 을 재시작한다.
jvmRoute속성은node_001,node_002와 같이 설정한다고 가정한다.
<Engine name="Catalina" defaultHost="localhost" jvmRoute="node_001">
jvmRoute속성값은JSESSIONIDCookie 의 뒤에 자동으로 붙는다.
Apache httpd 의 <VirtualHost> 부분을 다음과 같이 변경하고,
Apache httpd 를 재시작한다.
<VirtualHost 0.0.0.0:443> ProxyPass / balancer://mytomcatcluster/ ProxyPassReverse / balancer://mytomcatcluster/ ProxyRequests Off <Proxy balancer://mytomcatcluster> BalancerMember http://localhost:8080 route=node_001 BalancerMember http://192.168.0.2:8080 route=node_002 ProxySet stickysession=JSESSIONID|jsessionid </Proxy> </VirtualHost>
필수는 아니지만, 다음과 같은 것들도 추가할 수 있다.
RequestHeader set X-Forwarded-Secure-Request "true" RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-Port "443"
만약, Apache Tomcat 에 manager 와 같은 context 를 차단하고 싶다면, VirtualHost 에 다음과 같은 설정을 추가할 수 있다.
ProxyPass /docs ! ProxyPass /examples ! ProxyPass /host-manager ! ProxyPass /manager !
Sticky Session 은 구성이 단순해 진다는 장점이 있다.
Sticky Session 을 설정하면,
cookie 에
ProxySet ProxySet stickysession=JSESSIONID|jsessionid 에서
설정했던 JSESSIONID 가 붙어서 들어오면
종전에 접속했던 Apache Tomcat 서버로 연결한다.
Sticky Session 은 인트라넷이나 업무시스템에 어울리고 HA 구성을 원한다면 Apache Tomcat 간에 Session 을 공유하도록 설정해야 한다.
Apache Tomcat 간에 Session 공유는 Apache Tomcat 이 공동으로 바라보고 있는 RDBMS나 스토리지에 Session 을 저장하거나, 규모가 크다면 NOSQL 의 일종인 Key–value 를 지원하는 in-memory database 를 다중화하여 Session 저장소로 사용하도록 설정한다.
Cluster 는 Apache Tomcat 간에 의존성을 높인다는 단점이 있다.
3. 주의사항
3.1. 소스코드에서
request.getRemoteAddr() 는 Apache httpd 서버 주소,
이 글과 같은 설정이라면, 항상 127.0.0.1 을 반환한다.
따라서,
request.getRemoteAddr() 대신
request.getHeader("X-Forwarded-For") 을 사용해야 한다.
request.getLocalPort() 는 항상 8080 을 반환하고,
request.getScheme() 도 항상 http 이고,
request.isSecure() 도 항상 false 이다.
request.isSecure() 의 경우,
RequestHeader set X-Forwarded-Secure-Request "true" 설정을 했다면,
request.getHeader("X-Forwarded-Secure-Request") 를 사용할 수 있다.
Apache httpd 에서는 다음의 3개의 헤더를 자동으로 추가한다.
- X-Forwarded-For
- X-Forwarded-Host
- X-Forwarded-Server
MDN 의 HTTP headers 에서
X-Forwarded-For,
X-Forwarded-Host,
X-Forwarded-Proto 헤더에 대해 소개하고 있지만,
X-Forwarded 로 시작하는 헤더들은 표준이 아니기 때문에
X-Forwarded-Port 와 같은 것들도 많이 사용되고,
Apache httpd 와 Apache Tomcat 이 서로 약속한 헤더를 사용하는 경우도 많다.
Apache httpd 가 자동으로 추가하지 않는 것들은 다음과 같은 방식으로 설정파일에 추가해야 한다.
RequestHeader set X-Forwarded-Secure-Request "true" RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-Port "443"
클라이언트가 보낸 X-Forwarded-For 와 같은 헤더를 신뢰할 수 없다면,
다음과 같이 Apache httpd 와 Apache Tomcat 이 서로만 알고 있는 헤더를 주고 받아야 한다.
RequestHeader set X-Forwarded-RemoteAddr %{REMOTE_ADDR}s
mod_jk, mod_proxy_ajp 는 이런 제약이 없다.
Apache Tomcat 을 단독으로 사용하고 있었거나, mod_jk 로 연동하고 있었다면, 특별한 이유없이 mod_proxy_http.so 로 방식으로 변경하는 것은 신중을 기해야 한다.
mod_proxy 를 사용하면 mod_cache 설정을 쉽게 할 수 있다는 장점이 있다.
mod_proxy_http.so 는
8009 AJP/1.3 Connector 를 추가하지 않아도 되는 장점이 있겠지만,
Apache Tomcat 에서 서비스하는 프로그램에서
request.getRemoteAddr() 와 같은 코드를 사용하지 않을 때만
적합한 방식이다.
3.2. 보안과 관련해서
8080 포트 보안과
Apache Tomcat 의 manager 등의 Context 와 관련된 것은
mod_jk.so 를 이용한 Apache httpd 와 Apache Tomcat 연동 을
참조한다.