관련 아티클: /index.php/jboss/231-apache-jboss-2gb-response-header-content-length
어디서 Content-Length가 사라지는가? 라는 의문으로 추가 테스트를 진행합니다.
이번에는 response.setHeader("Content-Length", ...)를 사용해 헤더에 명시적으로 Content-Length를 넣었을 때 Apache-JBoss 연동 환경에서 어떤 반응이 나타나는지 확인합니다.
테스트 방법은 간단합니다. 아무 내용이 없는 JSP 파일 안에서 response.setHeader("Content-Length", ...)를 사용했습니다.
참고로 2147483647이 테스트의 중심에 있는 이유는 2GB 경계와 관련이 있기 때문입니다. 정확히 2GiB는 2 * 1024 * 1024 * 1024 = 2147483648이고, 2147483647은 그보다 1 작은 값이자 32비트 signed integer의 최댓값입니다.
명시적으로 Content-Length를 지정했을 때: only JBoss와 Apache-JBoss의 차이
1. JBoss EAP 6.2
Content-Length를 2147483647로 지정했습니다.
Content-Length:2147483647 Content-Type:text/html;charset=ISO-8859-1 Date:Fri, 12 Sep 2014 22:47:45 GMT Server:Apache-Coyote/1.1 X-Powered-By:JSP/2.2
결과: 명시적으로 지정한 Content-Length가 헤더에 잘 들어 있습니다.
2. Apache 2.2.27 - JBoss EAP 6.2
Content-Length를 2147483647로 지정했습니다.
Connection:Keep-Alive Content-Length:31 Content-Type:text/html;charset=ISO-8859-1 Date:Fri, 12 Sep 2014 22:42:11 GMT Keep-Alive:timeout=3, max=100 Server:Apache X-Powered-By:JSP/2.2
결과: 명시적으로 지정한 Content-Length가 아니라 실제 body 크기인 31바이트로 Content-Length가 표시됩니다.
FlushPackets, FlushHeader를 사용했을 때의 차이
여기까지는 Apache-JBoss 연동을 위한 mod_jk 설정에서 다음 옵션을 사용했습니다.
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
제가 기본으로 사용하는 옵션입니다.
여기에 추가 옵션을 사용해보려고 합니다. 관련된 옵션으로 추정되는 두 옵션은 다음과 같습니다.
- FlushPackets: mod_jk가 Tomcat에서 AJP packet chunk를 받을 때마다 Apache의 connection buffer를 flush하도록 합니다. 일반적으로 필요한 시점, 즉 각 응답의 끝보다 더 자주 write가 수행되므로 Apache와 Tomcat에 성능 부담이 클 수 있습니다.
- FlushHeader: mod_jk가 Tomcat에서 response header를 받은 뒤 Apache의 connection buffer를 flush하도록 합니다.
+FlushPackets 추가
JkOptions에 +FlushPackets를 추가하고 테스트합니다.
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories +FlushPackets
결과는 다음과 같습니다.
Connection:Keep-Alive Content-Type:text/html;charset=ISO-8859-1 Date:Fri, 12 Sep 2014 22:56:21 GMT Keep-Alive:timeout=3, max=100 Server:Apache Transfer-Encoding:chunked X-Powered-By:JSP/2.2
Content-Length가 2147483647도 아니고 31도 아니고 아예 없습니다. 대신 이번에는 Transfer-Encoding:chunked로 설정되어 있습니다.
+FlushHeader 추가
이번에는 JkOptions에 +FlushHeader를 추가하고 테스트합니다.
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories +FlushHeader
결과는 다음과 같습니다.
Connection:Keep-Alive Content-Type:text/html;charset=ISO-8859-1 Date:Fri, 12 Sep 2014 23:03:32 GMT Keep-Alive:timeout=3, max=100 Server:Apache Transfer-Encoding:chunked X-Powered-By:JSP/2.2
결과는 +FlushPackets를 추가했던 경우와 동일합니다.
2147483647바이트와 2147483646바이트의 차이
혹시 명시적으로 Content-Length로 지정한 2147483647에 어떤 의미가 있는 것은 아닐까요? 그래서 이제부터 그보다 하나 작은 숫자인 2147483646으로 테스트하려고 합니다.
JBoss에 직접 요청하면 문제없을 것으로 생각되어, Apache-JBoss 환경에서 기본 설정인 JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories로 요청합니다.
Connection:Keep-Alive Content-Length:31 Content-Type:text/html;charset=ISO-8859-1 Date:Fri, 12 Sep 2014 23:09:46 GMT Keep-Alive:timeout=3, max=100 Server:Apache X-Powered-By:JSP/2.2
Content-Length가 31로 표시됩니다. 2147483647로 지정하나 2147483646으로 지정하나 결과에 차이는 없습니다.
이번에는 Apache-JBoss 환경에서 JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories +FlushPackets 설정으로 요청합니다.
Connection:Keep-Alive Content-Length:2147483646 Content-Type:text/html;charset=ISO-8859-1 Date:Fri, 12 Sep 2014 23:14:39 GMT Keep-Alive:timeout=3, max=100 Server:Apache X-Powered-By:JSP/2.2
드디어 변화가 있습니다. 2147483647로 지정했을 때는 Transfer-Encoding:chunked가 되었는데, 이번에는 명시적으로 지정한 Content-Length 값인 2147483646이 보입니다.
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories +FlushHeader로 테스트했을 때도 마찬가지입니다.
Connection:Keep-Alive Content-Length:2147483646 Content-Type:text/html;charset=ISO-8859-1 Date:Fri, 12 Sep 2014 23:14:39 GMT Keep-Alive:timeout=3, max=100 Server:Apache X-Powered-By:JSP/2.2
역시 명시적으로 지정한 Content-Length 값인 2147483646이 보입니다.
2147483646바이트 실제 파일을 요청했을 때의 차이
명시적으로 Content-Length를 지정한 것이 아니라, 실제 그 크기의 파일을 요청했을 때는 어떤 결과가 나올지 추가 테스트합니다. 마지막에 사용했던 JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories +FlushHeader 설정에서 계속합니다. 파일은 크기가 2147483646바이트인 gz 파일입니다.
Accept-Ranges:bytes Connection:Keep-Alive Content-Length:2147483646 Content-Type:application/x-gzip Date:Fri, 12 Sep 2014 23:57:57 GMT ETag:W/"2147483646-1410566188000" Keep-Alive:timeout=3, max=100 Last-Modified:Fri, 12 Sep 2014 23:56:28 GMT Server:Apache
파일 크기대로 2147483646바이트의 Content-Length가 잘 표시됩니다.
이어서 기본 JkOptions로 사용했던 JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories에서 테스트합니다. 역시 파일은 크기가 2147483646바이트인 gz 파일입니다.
Accept-Ranges:bytes Connection:Keep-Alive Content-Length:2147483646 Content-Type:application/x-gzip Date:Sat, 13 Sep 2014 00:03:39 GMT ETag:W/"2147483646-1410566188000" Keep-Alive:timeout=3, max=100 Last-Modified:Fri, 12 Sep 2014 23:56:28 GMT Server:Apache
마찬가지로 2147483646바이트의 파일 크기대로 Content-Length가 잘 표시됩니다.
2147483647바이트 실제 파일을 요청했을 때의 차이
많이 달려왔지요. 그러면 이제는 2147483646이 아닌 2147483647바이트의 파일을 요청했을 때 어떤 결과인지 테스트합니다. 먼저 JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories +FlushHeader 설정입니다.
Connection:Keep-Alive Content-Type:application/x-gzip Date:Sat, 13 Sep 2014 00:07:01 GMT ETag:W/"2147483647-1410566607000" Keep-Alive:timeout=3, max=100 Last-Modified:Sat, 13 Sep 2014 00:03:27 GMT Server:Apache Transfer-Encoding:chunked
역시 예전처럼 Content-Length는 표시되지 않고 Transfer-Encoding:chunked가 표시됩니다.
이번에는 기본 옵션으로 사용했던 JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories에서의 테스트입니다.
Accept-Ranges:bytes Connection:Keep-Alive Content-Type:application/x-gzip Date:Sat, 13 Sep 2014 00:08:49 GMT ETag:W/"2147483647-1410566607000" Keep-Alive:timeout=3, max=100 Last-Modified:Sat, 13 Sep 2014 00:03:27 GMT Server:Apache Transfer-Encoding:chunked
동일합니다. Content-Length는 표시되지 않고 Transfer-Encoding:chunked가 표시됩니다.
정리
이제까지의 테스트를 통해 명확히 알 수 있는 사실은 경계가 2147483646과 2147483647 사이라는 것입니다. 즉, 이 테스트 환경에서는 2147483646바이트까지는 Content-Length가 잘 표시되지만, 2147483647바이트부터는 Transfer-Encoding:chunked로 표시됩니다.
테스트할 때는 브라우저보다 응답 헤더를 그대로 확인할 수 있는 도구를 사용하는 편이 좋습니다. 예를 들어 동일한 URL을 JBoss에 직접 요청했을 때와 Apache를 거쳐 요청했을 때의 응답 헤더를 나란히 비교하면, 어느 구간에서 Content-Length가 바뀌거나 사라지는지 확인하기 쉽습니다.