
Apache Server 역방향 프록시를 통해 https를 통해 Tomcat 서블릿에 파일을 게시하는 동안 간헐적으로 매우 자주 발생하는 오류가 갑자기 발생합니다. 이 오류는 20MB 이상의 파일(동영상)을 게시하는 동안에만 발생하는 것 같습니다. 2~5MB(JPEG)의 작은 파일에서는 문제가 발생하지 않았습니다.
이 오류는 우리가 시도한 5개의 서버 중 2개에서 발생했습니다.
연결의 서버 측(예: Jersey를 사용하여 구축된 Tomcat 서블릿)에서 다음을 얻습니다.
java.net.SocketException: Connection reset
역방향 프록시 역할을 하는 동일한 시스템의 Apache 서버는 다음 오류 메시지를 표시합니다.
[Thu May 15 17:08:58 2014] [error] proxy: pass request body failed to 127.0.0.1:8080 (localhost) from 192.168.16.xx ()
문제를 디버깅하고 재현하기 위해 Apache 서버의 로깅 수준을 설정하면 추가 정보가 생성되지 않습니다. 관련 메시지 없이 동일한 오류 메시지가 계속 표시됩니다.
Tomcat 측에서는 예외가 발생하지 않지만 Content-Length 헤더에 대해 전송된 바이트 수를 확인하면 모든 것이 통과되지는 않았음을 알 수 있습니다. 이 두 번째 시나리오에서 Apache 서버의 오류는 첫 번째 "프록시: 요청 본문 전달 실패..."와 동일합니다.
Apache 서버 버전은 한 서버에서는 2.2.15.29이고 다른 서버에서는 2.2.15.30이며 모든 경우에 CentOS 6.2에서 실행됩니다. 역방향 프록시 규칙은 다음과 같이 설정됩니다.
<IfModule mod_proxy.c>
ProxyRequests Off
# Case Manager Tomcat web service
ProxyPass /casemanager http://localhost:8080/casemanager
ProxyPassReverse /casemanager http://localhost:8080/casemanager
# Matcher images directories
ProxyPass /matcher-images http://x.x.x.108:80/matcher-images
</IfModule>
프록시 통과는 https가 아닌 http를 통해서만 진행됩니다.
SSL 구성을 위해 자체 서명된 인증서를 사용하고 있습니다. OpenSSL 버전은 실패한 서버 중 하나에서는 1.0.1e-fips이고 다른 서버에서는 1.0.0-fips입니다.
Tomcat 측에서는 7.0.26을 실행하고 Jersey 1.8을 사용하고 있습니다.
그것이 중요한지는 의심스럽지만 POST가 시작된 브라우저 연결은 Firefox 27 또는 Chrome 34입니다.
어떤 경우에는 파일 업로드를 처리하는 코드가 최근에 변경되지 않았지만 서블릿이 최근 업데이트되었습니다. 문제가 발생한 다른 서버에서는 몇 달 전의 서블릿 빌드를 실행하고 있습니다. 실제로 두 번째 컴퓨터에서는 지난 몇 달 동안 코드나 구성 변경 사항이 전혀 인식되지 않았습니다. 2월 중순부터 오늘까지 유휴 상태로 있었습니다.
이 문제를 해결하려면 다음으로 무엇을 해야 합니까? 어디를 봐야 할까요?
-- 업데이트 --
추가 테스트에 따르면 Apache 서버를 우회하고 Tomcat에 직접 POST하는 경우에도 연결이 끊어지는 경우가 있습니다. 따라서 프록시 문제는 전혀 아닌 것 같습니다.
-- 추가 업데이트 --
scp를 통해 동일한 대용량 파일을 복사하는 데 간헐적으로 문제가 발생합니다. 근본적인 문제는 사무실/개발 서브넷과 프로덕션/스테이징 네트워크 사이의 방화벽인 것 같습니다. scp 복사가 실패할 때 나타나는 오류 메시지는 "깨진 파이프"입니다.
연결이 끊어졌을 때 서블릿의 스택 추적은 다음과 같습니다.
2014-05-16 13:20:44,566 [http-bio-8080-exec-7] 오류 com.objectvideo.wx.casemanager.service.resources.QueryFileService [null] - 파일을 업로드하지 못했습니다. javax.ws.rs.WebApplicationException: java.net.SocketException: com.objectvideo.wx.casemanager.service.resources.QueryFileService.uploadRawFile(QueryFileService.java:342)(com.objectvideo.wx.casemanager.service)에서 연결이 재설정되었습니다. resources.QueryFileService.uploadFile(QueryFileService.java:607) at sun.reflect.GeneratedMethodAccessor37.invoke(알 수 없는 소스) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke( Method.java:606) com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch (AbstractResourceMethodDispatchProvider.java:205), com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75), com.sun.jersey.server.impl.uri.rules.HttpMethodRule com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)의 .accept(HttpMethodRule.java:288) com.sun.jersey.server.impl.uri.rules.RightHandPathRule의 com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)의 .accept(RightHandPathRule.java:147) com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest의 (WebApplicationImpl.java:1469) com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400) com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java) :1349) com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339) com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699) at javax.servlet. org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)의 http.HttpServlet.service(HttpServlet.java:722) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) org.apache.catalina.authenticator.AuthenticatorBase.invoke (AuthenticatorBase.java:472) org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927) org.apache.catalina.core.StandardEngineValve org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)의 .invoke(StandardEngineValve.java:118), org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987), org. apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307) at java.util.concurrent.ThreadPoolExecutor.runWorker( ThreadPoolExecutor.java:1145) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) java.lang.Thread.run(Thread.java:724) 원인: java.net.SocketException: 연결 org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:532)에서 java.net.SocketInputStream.read(SocketInputStream.java:121)에서 java.net.SocketInputStream.read(SocketInputStream.java:189)에서 재설정합니다. org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:501) org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:563) org.apache.coyote.http11.filters .IdentityInputFilter.doRead(IdentityInputFilter.java:118) at org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:326) at org.apache.coyote.Request.doRead(Request.java:422) at org. apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:290) org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:431) org.apache.catalina.connector.InputBuffer.read( org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:167) org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1719) org.apache.commons에서 InputBuffer.java:315) org.apache.commons.io.IOUtils.copy(IOUtils.java:1671)의 .io.IOUtils.copyLarge(IOUtils.java:1696) org.apache.commons.io.FileUtils.copyInputStreamToFile(FileUtils.java:1444) ) com.objectvideo.wx.casemanager.service.resources.QueryFileService.writeTempFile(QueryFileService.java:535)에서 com.objectvideo.wx.casemanager.service.resources.QueryFileService.uploadRawFile(QueryFileService.java:320)에서 ... 35개 이상org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)의 org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)의 프로세스(AbstractHttp11Processor.java:987) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)에서 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)에서 java.lang.Thread.run(Thread.java:724)에서 ) 원인: java.net.SocketException: org.apache.coyote.http11의 java.net.SocketInputStream.read(SocketInputStream.java:121)에서 java.net.SocketInputStream.read(SocketInputStream.java:189)에서 연결 재설정 .InternalInputBuffer.fill(InternalInputBuffer.java:532) org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:501) org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:563) ) org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:118) org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:326) org.apache.coyote.Request에서. org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:290)의 org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:431)의 doRead(Request.java:422) org org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:315) org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:167) org.apache.commons.io.IOUtils.copyLarge(IOUtils) .java:1719) org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1696) org.apache.commons.io.IOUtils.copy(IOUtils.java:1671) org.apache.commons. com.objectvideo.wx.casemanager.service.resources.QueryFileService.writeTempFile(QueryFileService.java:535)의 io.FileUtils.copyInputStreamToFile(FileUtils.java:1444), com.objectvideo.wx.casemanager.service.resources.QueryFileService. uploadRawFile(QueryFileService.java:320) ... 35개 더 보기org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)의 org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)의 프로세스(AbstractHttp11Processor.java:987) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)에서 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)에서 java.lang.Thread.run(Thread.java:724)에서 ) 원인: java.net.SocketException: org.apache.coyote.http11의 java.net.SocketInputStream.read(SocketInputStream.java:121)에서 java.net.SocketInputStream.read(SocketInputStream.java:189)에서 연결 재설정 .InternalInputBuffer.fill(InternalInputBuffer.java:532) org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:501) org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:563) ) org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:118) org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:326) org.apache.coyote.Request에서. org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:290)의 org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:431)의 doRead(Request.java:422) org org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:315) org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:167) org.apache.commons.io.IOUtils.copyLarge(IOUtils) .java:1719) org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1696) org.apache.commons.io.IOUtils.copy(IOUtils.java:1671) org.apache.commons. com.objectvideo.wx.casemanager.service.resources.QueryFileService.writeTempFile(QueryFileService.java:535)의 io.FileUtils.copyInputStreamToFile(FileUtils.java:1444), com.objectvideo.wx.casemanager.service.resources.QueryFileService. uploadRawFile(QueryFileService.java:320) ... 35개 더 보기org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:563)의 org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:118)에서 fill(InternalInputBuffer.java:501) org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:326) org.apache.coyote.Request.doRead(Request.java:422) org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer) .java:290) org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:431) org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:315) org.apache. org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1719)의 catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:167) org.apache.commons.io.IOUtils.copyLarge(IOUtils.java: 1696) org.apache.commons.io.IOUtils.copy(IOUtils.java:1671) org.apache.commons.io.FileUtils.copyInputStreamToFile(FileUtils.java:1444) com.objectvideo.wx.casemanager.service .resources.QueryFileService.writeTempFile(QueryFileService.java:535) at com.objectvideo.wx.casemanager.service.resources.QueryFileService.uploadRawFile(QueryFileService.java:320) ... 35 더 보기org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:563)의 org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:118)에서 fill(InternalInputBuffer.java:501) org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:326) org.apache.coyote.Request.doRead(Request.java:422) org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer) .java:290) org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:431) org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:315) org.apache. org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1719)의 catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:167) org.apache.commons.io.IOUtils.copyLarge(IOUtils.java: 1696) org.apache.commons.io.IOUtils.copy(IOUtils.java:1671) org.apache.commons.io.FileUtils.copyInputStreamToFile(FileUtils.java:1444) com.objectvideo.wx.casemanager.service .resources.QueryFileService.writeTempFile(QueryFileService.java:535) at com.objectvideo.wx.casemanager.service.resources.QueryFileService.uploadRawFile(QueryFileService.java:320) ... 35 더 보기
답변1
keepalive=on
지시문 에 추가해 보세요 ProxyPass
.
전역 Apache 서버 측에서도 KeepAlive
설정 해야 할 수도 있습니다 .on