Tente anexar keepalive=on
às suas diretivas ProxyPass
.
Isso pode exigir que KeepAlive
seja definido como on
no lado do servidor Apache global.
De repente, estamos vendo um erro intermitente, mas muito freqüente, durante o envio de arquivos para um servlet Tomcat por meio de um proxy reverso do Apache Server. O erro parece ocorrer apenas durante o envio de arquivos de 20 MB ou mais (vídeos). Nós não vimos o problema com arquivos menores de 2 a 5 MB (JPEGs).
O erro ocorre em dois dos cinco servidores em que o testamos.
No lado do servidor da conexão, ou seja, um servlet Tomcat construído usando Jersey, obtemos:
java.net.SocketException: Connection reset
O Apache Server na mesma máquina, atuando como um proxy reverso, fornece esta mensagem de erro:
[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 ()
Definir o nível de registro do Apache Server para depurar e reproduzir o problema não produz informações adicionais - ainda recebemos a mesma mensagem de erro sem nenhuma mensagem associada.
Um pouco menos vezes, não obtemos uma exceção no lado do Tomcat, mas verificar o número de bytes transferidos no cabeçalho Content-Length revela que nem tudo foi bem sucedido. O erro no Apache Server neste segundo cenário é o mesmo que no primeiro "proxy: o corpo da solicitação de aprovação falhou ..."
A versão do Apache Server é 2.2.15.29 em um servidor e 2.2.15.30 no outro, rodando sob o CentOS 6.2 em todos os casos. As regras do proxy reverso são configuradas da seguinte forma:
<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>
Observe que a passagem do proxy está passando por http, não https.
Estamos usando certificados autoassinados para a configuração SSL. A versão do OpenSSL é 1.0.1e-fips em um dos servidores com falha e 1.0.0-fips no outro.
No lado do Tomcat, estamos executando o 7.0.26 e usando o Jersey 1.8.
Eu duvido que isso importe, mas a conexão do navegador a partir da qual o POST se origina é o Firefox 27 ou o Chrome 34.
Em um caso, nosso servlet foi atualizado recentemente, embora o código para o upload de arquivos não tenha sido alterado recentemente. No outro servidor com o problema, estamos executando uma compilação de servlet de meses atrás. Na verdade, nessa segunda máquina, não estamos cientes de qualquer alteração de código ou configuração nos últimos meses - ela ficou inativa de meados de fevereiro até hoje.
O que devo fazer para resolver este problema? Onde devo estar procurando?
- Atualizar -
Outros testes mostram que a conexão às vezes é interrompida mesmo se eu ignorar o Apache Server e o POST diretamente para o Tomcat. Por isso, não parece ser um problema de proxy.
- Atualizações adicionais -
Estamos vendo problemas para copiar os mesmos arquivos grandes via scp. Parece que o problema subjacente é o firewall entre nossa sub-rede de escritório / desenvolvimento e a rede de produção / teste. A mensagem de erro quando uma cópia do scp falha é "Canal quebrado".
Aqui está o rastreamento de pilha do servlet quando a conexão cai:
2014-05-16 13:20:44,566 [http-bio-8080-exec-7] ERROR com.objectvideo.wx.casemanager.service.resources.QueryFileService [null] - Failed to upload file(s). javax.ws.rs.WebApplicationException: java.net.SocketException: Connection reset at com.objectvideo.wx.casemanager.service.resources.QueryFileService.uploadRawFile(QueryFileService.java:342) at com.objectvideo.wx.casemanager.service.resources.QueryFileService.uploadFile(QueryFileService.java:607) at sun.reflect.GeneratedMethodAccessor37.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205) at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288) at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339) at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) at 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.http.HttpServlet.service(HttpServlet.java:722) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987) at 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) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724) Caused by: java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:189) at java.net.SocketInputStream.read(SocketInputStream.java:121) at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:532) at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:501) at org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:563) at 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) at org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:431) at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:315) at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:167) at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1719) at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1696) at org.apache.commons.io.IOUtils.copy(IOUtils.java:1671) at org.apache.commons.io.FileUtils.copyInputStreamToFile(FileUtils.java:1444) at com.objectvideo.wx.casemanager.service.resources.QueryFileService.writeTempFile(QueryFileService.java:535) at com.objectvideo.wx.casemanager.service.resources.QueryFileService.uploadRawFile(QueryFileService.java:320) ... 35 more
Tente anexar keepalive=on
às suas diretivas ProxyPass
.
Isso pode exigir que KeepAlive
seja definido como on
no lado do servidor Apache global.