서론
L4의 scale-out이 어렵다는 점을 해결하기 위해, HAProxy를 사용하게 된 후, 과연 web server가 필요할까라는 의문이 들었다. apache http + tomcat
라는 기술 스택은 마치 표준인양 Java 서버 진영에서는 많이 사용되고 있는데, HAProxy로 L4를 대체해버린 경우에도 정말 apache http가 필요한 걸까? 한 번 따져볼 일이다.
L4 + Apache Http + Tomcat VS HAProxy + Tomcat
HAProxy로 L4/L7 switch를 대체하는 것에 대한 내용은 Naver의 기술 블로그(L4/L7 스위치의 대안, 오픈 소스 로드 밸런서 HAProxy)를 참고하자
다음은 각 구성을 다이어그램으로 표현한 것이다.
전통적인 L4 - Server 구성
GSLB - HAProxy - Server 구성
Apache Http + Tomcat 스택을 쓰는 이유
우선 왜 apache http + tomcat
을 사용할까?
개인적으로 생각하는 apache http + tomcat
을 쓰는 이유에 대해서 꼽아봤다.
- 정적 컨텐츠 제공
- apache http는 빠른 성능의 정적 컨텐츠 제공이 강점이다.
- apache http로 정적 컨텐츠를 제공하고, tomcat으로 동적 service logic을 실행한다.
- 보안
- 여러 조건을 가지고 ACL을 걸 수 있다.
- SSL Offloading으로 tomcat에서는 http로만 잘 동작하도록 해도 문제없다.
- Apache 모듈 지원
- 많은 기능을 모듈화하여 필요에 따라 사용할 수 있다.
- 레퍼런스
apache http + tomcat
은 사용자가 많다.- 많은 실패사례, 성공사례, 예제와 설명을 접할 수 있다.
적어놓고 보니 안 쓸 이유가 없어보인다.
사실 이 외에도 많은 장점이 있다.(가상호스트, 요청 편집, 프록시 등)
HAProxy를 사용한다는 가정하에 몇 가지 태클을 걸어보자.
만약 위의 기능이 필요하다면
apache http + tomcat
을 쓰자
정적 컨텐츠 제공
과연 정적인 컨텐츠가 서버마다 있어야 할까?/static/a.png
파일이 A서버에 요청할 때와, B서버에 요청할 때 다른 결과가 나와야할 컨텐츠가 있을까?
그렇지 않다면 차라리 가용성을 높게 구성한 CDN에서 관리하는게 좋다고 생각한다.
보안
SSL Offloading, URI, Header 등, L4/L7을 대체하는 HAProxy에서 ACL체크를 할 수 있다.
Apache 모듈 지원
HAProxy의 주된 기능은 당연히 Proxy이다. 만약 Caching이 필요하다거나, Apache의 모듈에서만 제공하는 기능이 반드시 필요하다면 Apache를 써야한다. 하지만 인프라 구성이 HAProxy로도 충분히 해낼 수 있다면 Apache를 사용해야할 이유가 희미해진다.
성능
단일 서버를 사용한다면 native web server를 tomcat 앞에 두는 것은 대부분의 경우, HTTP connector로 standalone으로 동작하는 것보다
현저하게 낮은 성능(significantly worse)
을 보인다. 이는 web application의 대부분이 정적 파일로 구성된 경우에도 마찬가지다.
물론 apache http + tomcat
으로 구성할 때에는, 둘 사이의 통신을 ajp 프로토콜을 사용하여 빠른 성능을 내려고 노력하지만 필연적으로 tomcat standalone보다는 느릴 수 밖에 없다
결론
Apache http에 의존적인 서비스를 해야하는 가에 대해 확인할 필요가 있다.
꼭 Apache http를 써야할 이유가 없고, 성능이나 비용 절감의 요구가 더 크다면 과감히 WebServer-less로 전환해보는 건 어떨까?
기존에 사용하던 Apache의 기능을 HAProxy로 Porting 할 수 있을까?
error 처리
apache
1 | ErrorDocument 400 /error/invalidRequest.html |
HAProxy
1 | errorfile 404 /etc/haproxy/errorfiles/404.html |
특정 요청 오류 응답
apache
1 | Redirect 404 /favicon.ico |
HAProxy
1 | acl favicon_request path /favicon.ico |
특정 경로 ACL(403)
apache
1 | <DirectoryMatch "(^|/)META-INF($|/)"> |
HAProxy
1 | acl meta_inf_request path_reg (^|/)META-INF($|/) |
응답 압축
apache
1 | AddOutputFilterByType DEFLATE text/plain text/html text/xml |
HAProxy
1 | tune.zlib.memlevel 9 |
Request 재작성(mod_rewrite)
www를 강제로 붙이기
1 | http-request redirect code 301 \ |
VirtualHost
로드밸런서(GSLB)에 등록된 ip 기반으로 나누는 방식(권장)
1 | frontend a_domain |
하나의 IP로 받고 Domain name을 기준으로 front에서 나누는 방식
1 | frontend http_proxy |
X-Forwarded-For
1 | frontend www |
마무리
관례는 좋다고 생각한다. 레퍼런스가 많고, 배우기 쉬우며, 많은 사람들이 그 기술을 사용할 때에는 다 이유가 있기 때문에 쓴다. 하지만 레퍼런스 케이스가 모든 경우에 대입할 수 있는 것은 아니다. 새로운 요구 사항들이 생기고, 새로운 기술들을 익히는 과정에서 한 번 쯤은 내가 쓰고 있던 기술들을 돌이켜 보고 더 나은 구조는 없을까 고민해보는 것도 좋은 경험인 것 같다.
한 가지 분명히 밝혀둬야할 것은 HAProxy는 Apache의 대체 기술이 아니다. Apache는 server이고, HAProxy는 proxy이다. 각자 자신만이 할 수 있는 영역이 있고, 두 기술 모두 처리할 수 있는 영역이 있다. 여기서는 교집합이 되는 영역에 대해서 이야기하고 싶었다.
본문에서는 전체 주제를 유지하기 위해 Apache의 기능에만 많은 초점을 맞추었지만, HAProxy 또한 각 node끼리 P2P로 통신하여 전체 트래픽을 제어하거나, sticky session을 구성하거나, 임계치를 걸 수 있는 등, Apache에서는 하지 못할 일들을 할 수 있다. 그러니 한 번 쯤은 HAProxy 레퍼런스를 훑어보는 것도 좋다.
HAProxy는 L4/L7에서 요청을 다룰 수 있는 기능을 제공한다. HAProxy를 사용해서 L4/L7을 대체하는 구성을 사용하게 된다면, 그동안 당연히 사용해왔던 apache http에 대해서 다시 한 번 돌아볼 필요가 있다고 생각한다.