Web Application Server

Apache - JBoss 구조에서 2GB 이상 파일 요청 시 Response Header 에 Content-Length 표시되지 않는 이슈

강철지그·2014년 9월 12일·조회 7,543

1. 개요

Apache - JBoss 구조에서 2GB 이상 파일을 요청할 때 응답 헤더에 Content-Length가 표시되지 않는 이슈가 있다. 정확히 어느 구간의 문제인지 확인하기 위해 여러 지점에 직접 요청을 보내 보았다.


2. 테스트

테스트는 각 구간에 같은 파일을 요청한 뒤 응답 헤더에 Content-Length가 포함되는지 확인하는 방식으로 진행했다. 아래 결과에서 핵심은 Content-Length 또는 Transfer-Encoding: chunked 헤더의 유무다.

2-1. Apache (2.2.27)

Accept-Ranges:bytes
Connection:Keep-Alive
Content-Length:2482044928
Content-Type:application/x-gzip
Date:Fri, 12 Sep 2014 01:07:48 GMT
ETag:"140032-93f10000-500e216017f6d"
Keep-Alive:timeout=3, max=100
Last-Modified:Mon, 18 Aug 2014 07:11:55 GMT
Server:Apache

2-2. JBoss EAP (6.2)

Accept-Ranges:bytes
Content-Length:2482044928
Content-Type:application/x-gzip
Date:Fri, 12 Sep 2014 01:04:24 GMT
ETag:W/"2482044928-1410483441000"
Last-Modified:Fri, 12 Sep 2014 00:57:21 GMT
Server:Apache-Coyote/1.1

2-3. Tomcat (7.0.55)

Accept-Ranges:bytes
Content-Length:2482044928
Content-Type:application/x-gzip
Date:Fri, 12 Sep 2014 01:15:06 GMT
ETag:W/"2482044928-1410483441000"
Last-Modified:Fri, 12 Sep 2014 00:57:21 GMT
Server:Apache-Coyote/1.1

2-4. Apache (2.2.27) - JBoss EAP (6.2)

Accept-Ranges:bytes
Connection:Keep-Alive
Content-Type:application/x-gzip
Date:Fri, 12 Sep 2014 01:00:25 GMT
ETag:W/"2482044928-1410483441000"
Keep-Alive:timeout=3, max=100
Last-Modified:Fri, 12 Sep 2014 00:57:21 GMT
Server:Apache
Transfer-Encoding:chunked

Content-Length 정보가 포함되지 않았다. 다만 요청 시 파일 처리, 즉 다운로드 자체는 정상적으로 동작한다.

2-5. Apache (2.2.27) - Tomcat (7.0.55)

Accept-Ranges:bytes
Connection:Keep-Alive
Content-Length:2482044928
Content-Type:application/x-gzip
Date:Fri, 12 Sep 2014 01:13:21 GMT
ETag:W/"2482044928-1410483441000"
Keep-Alive:timeout=3, max=100
Last-Modified:Fri, 12 Sep 2014 00:57:21 GMT
Server:Apache

3. 결과

위 테스트 결과를 보면, 2GB 이상 파일을 Apache - JBoss 연동 구조로 처리할 때만 Content-Length가 포함되어 있지 않다. 즉, 해당 파일을 JBoss에서 처리하는 경우에만 발생한다.

물론 다운로드는 잘 되지만, Content-Length가 없어서 브라우저에서 다운로드할 때 총 파일 용량이 표시되지 않고 현재 다운로드한 크기만 표시된다. 예를 들어 15MB/2.3GB처럼 나오지 않고 15MB만 표시된다.

추가로 Apache - JBoss 연동에서 2GB 이하 파일도 테스트해 보았다.

Accept-Ranges:bytes
Connection:Keep-Alive
Content-Length:938882272
Content-Type:application/x-gzip
Date:Fri, 12 Sep 2014 01:32:36 GMT
ETag:W/"938882272-1410485435000"
Keep-Alive:timeout=3, max=100
Last-Modified:Fri, 12 Sep 2014 01:30:35 GMT
Server:Apache

이 경우에는 정상적으로 Content-Length가 표시되었다. 결론적으로 Apache - JBoss 연동 시에만, 그리고 2GB 이상일 때 Content-Length가 빠진다.

Apache - Tomcat일 때는 정상적으로 표시되므로, 이 결과만 놓고 보면 단순히 mod_jk 문제라고 보기는 어렵다.


4. Content-Length와 chunked 방식의 차이

4-1. Content-Length 방식

  • Content-Length에 본문의 길이를 기록하므로 수신자가 본문의 전체 길이를 알 수 있게 하는 방식이다.
  • 정적 콘텐츠처럼 헤더 생성 시점에 본문의 길이를 알 수 있을 때 사용한다.
  • 클라이언트는 이 값을 기준으로 다운로드 진행률이나 전체 파일 크기를 표시할 수 있다.

4-2. chunked 방식

  • HTTP 헤더 중 Transfer-Encoding의 값이 chunked인 방식이다.
  • 헤더 생성 시점에 본문의 전체 길이를 알 수 없을 때 사용한다.
  • 동적 콘텐츠의 경우 애플리케이션 수행이 시작되면서 HTTP 응답도 함께 시작될 수 있다.
  • 이때 송신 버퍼가 8K를 넘으면 응답을 먼저 보내기 시작하는데, 아직 애플리케이션 처리가 끝나지 않았다면 이후 응답 본문이 추가로 생성된다.

이번 테스트에서 Apache - JBoss 조합의 2GB 이상 파일 응답은 Content-Length 대신 Transfer-Encoding: chunked로 내려왔다. 따라서 파일 다운로드 자체는 가능하지만, 클라이언트 입장에서는 응답 시작 시점에 전체 크기를 알 수 없어 진행률 표시가 제한될 수 있다.

댓글 2

로그인 후 댓글을 남길 수 있습니다.

  • stdio.hstdio.h· 2014년 9월 14일
    JEUS 같은 경우는 WEBMain.xml 의 webtob-listener 중간에 아래와 같은 옵션을 추가하면 chunked encoding 을 하지 않고 무조건 Content-Length 를 실어 보냅니다만, Jboss 의 경우는 잘 모르겠네요.. 0 (객체를 모두 heap 에 올리게 되어 메모리에 부담은 줍니다) 그런데 꼭 Content-Length 가 실려야 하는 요구사항이 있는건지요?
  • appsrootappsroot· 2014년 9월 14일
    언급하신 버전인 JBoss 6.2 EAP 기준으로 chunked encoding 을 disable 시키는 방법입니다. 1) cxf [code]import org.apache.cxf.endpoint.Client; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.transport.http.HTTPConduit; import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; //Get the JAX-WS proxy object ExampleWSPortType port = new ExampleWS().getExampleWSPortTypePort(); Client client = ClientProxy.getClient(port); HTTPConduit http = (HTTPConduit) client.getConduit(); HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy(); httpClientPolicy.setAllowChunking(false); http.setClient(httpClientPolicy);[/code] 2) MANIFEST.MF 혹은 jboss-deployment-strcuture.xml 에 dependency 추가 [code] [/code]