Мы внезапно наблюдаем периодическую, но очень частую ошибку при отправке файлов сервлету Tomcat через https через обратный прокси-сервер Apache Server. Ошибка возникает только при отправке файлов размером 20 МБ или более (видео). Мы не видели проблемы с файлами меньшего размера от 2 до 5 МБ (JPEG).
Ошибка возникает на двух из пяти серверов, на которых мы ее опробовали.
На стороне сервера соединения, то есть сервлета 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 Server для отладки и воспроизведения проблемы не дает дополнительной информации - мы все равно получаем то же сообщение об ошибке без каких-либо связанных сообщений.
Чуть реже мы не получаем исключения на стороне Tomcat, но проверка количества переданных байтов по заголовку Content-Length показывает, что не все прошло. Ошибка в Apache Server в этом втором сценарии такая же, как и в первом «прокси: не удалось передать тело запроса ...»
Версия Apache Server - 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>
Обратите внимание, что прокси-сервер просто проходит через http, а не https.
Мы используем самозаверяющие сертификаты для конфигурации SSL. Версия OpenSSL - 1.0.1e-fips на одном из отказавших серверов и 1.0.0-fips на другом.
На стороне Tomcat мы используем 7.0.26 и Jersey 1.8.
Я сомневаюсь, что это имеет значение, но соединение с браузером, из которого исходит POST, - это Firefox 27 или Chrome 34.
В одном случае наш сервлет был недавно обновлен, хотя код для обработки загрузки файлов в последнее время не менялся. На другом сервере, где возникла проблема, мы запускаем сборку сервлета, сделанную несколько месяцев назад. Фактически, на этой второй машине мы не знаем никаких изменений кода или конфигурации за последние несколько месяцев - она простаивала с середины февраля до сегодняшнего дня.
Что мне делать дальше, чтобы устранить эту проблему? Где мне искать?
-- Обновить --
Дальнейшее тестирование показывает, что соединение иногда разрывается, даже если я обхожу сервер Apache и POST напрямую с Tomcat. Так что это вообще не проблема прокси.
- Дальнейшие обновления -
Мы периодически наблюдаем проблемы с копированием одних и тех же больших файлов через 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) на sun.reflect.GeneratedMethodAccessor37.invoke (Неизвестный источник) на sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.invoke) at java. Method.java:606) по адресу com.sun.jersey.spi.container.JavaMethodInvokerFactory $ 1.invoke (JavaMethodInvokerFactory.java:60) по адресу com.sun.jersey.server.impl.model.model.method.dispatch.AbstractvokerDisourcepatch (AbstractResourceMethodDispatchProvider.java:205) по адресу com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch (ResourceJavaMethodDispatcher.java:75) по адресу com.suuriMethodDispatcher. .accept (HttpMethodRule.java:288) в com.sun.jer sey.server.impl.uri.rules.ResourceClassRule.accept (ResourceClassRule.java:108) на com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept (RightHandPathRule.java:147) на com.sun. jersey.server.impl.uri.rules.RootResourceClassesRule.accept (RootResourceClassesRule.java:84) на com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest (WebApplicationImpl.java:1469.jersey. server.impl.application.WebApplicationImpl._handleRequest (WebApplicationImpl.java:1400) по адресу com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest (WebApplicationImpl.java:1349) по адресу com.sun.impl.server.server. 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) в com.sun.jersey.spi.container.servlet.ServletContainer.service (ServletContainer.java:699) в javax.servlet.http.HttpServlet. сервис (HttpServlet.java:722) в org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:305) в org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilter.Chain) или в ApplicationFilterChain.java или .catalina.core.StandardWrapperValve.invoke (StandardWrapperValve.java:224) в org.apache.catalina.core.StandardContextValve.invoke (StandardContextValve.java:169) в org.apache.catalina.authenticator.AutatorBackup.Authenticator.AuthenticatorB. : 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.invoke (StandardEngineValve.java:118) в org.apache.catalina.connector.CoyoteAdapter.service (Coyoteg407Adapter.service (Coyote:Adapter) .apache.coyote.http11.AbstractHttp11Processor.process (AbstractHttp11Processor.java:987) на org.apache.co yote.AbstractProtocol $ AbstractConnectionHandler.process (AbstractProtocol.java:579) в org.apache.tomcat.util.net.JIoEndpoint $ SocketProcessor.run (JIoEndpoint.java:307) в java.util.concurrent.ThreadPoolExecutor.r (ThreadPoolExecutor.r. java: 1145) в java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:615) в java.lang.Thread.run (Thread.java:724) Причина: java.net.SocketException: сброс соединения в java.net.SocketInputStream.read (SocketInputStream.java:189) в java.net.SocketInputStream.read (SocketInputStream.java:121) в org.apache.coyote.http11.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.Pache.Coy. .doRead (IdentityInputFilter.java:118) в 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.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.io.FileUtils.copyInputStreamToFile (FileUtils.java:1444) в com.objectvideo.wx.casemanager.service.resources.QueryFileService.writeTempFile (QueryFileService.java .:535) в com.objectvideo.java .:535) objectvideo.wx.casemanager.service.resources.QueryFileService.uploadRawFile (QueryFileService.java:320) ... еще 35
Попробуйте добавить keepalive=on
на ваш ProxyPass
директивы.
Это может потребовать KeepAlive
быть установлен на on
на столь глобальной стороне сервера Apache.