Hello!
We have a web service (Jersey based) on Jetty 9.1.3.v2014022 which somehow leaves sockets open. After a while we realized that problem occurs only in our production environment where we have a monitoring daemon calling the service with a simple ping request every 1 minute and a balancer doing the same thing every 6 seconds. The interesting part is the balancer ends its requests with RST (not FIN/ACK). No one else uses the service yet.
The service is pretty simple and is going to be called once a day for integration purposes so the configuration is fairly modest: 1 acceptor, 2 selectors and 2 threads for request handlers. Omitting irrelevant code it's roughly going like this:
final QueuedThreadPool threadPool = new QueuedThreadPool(5);final Server server = new Server(threadPool);final Connector[] connectors = new Connector[1];final ServerConnector serverConnector = new ServerConnector(server, 1, 2);serverConnector.setSoLingerTime(0);serverConnector.setPort(35980);connectors[0] = serverConnector;server.setConnectors(connectors);final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);context.setContextPath("/");ServletHolder restApiHolder = ...;context.addServlet(restApiHolder, "/*");server.setHandler(context);server.start();
The problem occurs pretty rarely. Here what we found out so far:
1) The service stops closing sockets immediately after two consequent exceptions:
[2014-04-14 12:29:50,552] DEBUG [qtp782189620-16 - /ping] write exceptionorg.eclipse.jetty.io.EofExceptionat org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:189)at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:335)at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:125)at org.eclipse.jetty.server.HttpConnection$CommitCallback.process(HttpConnection.java:555)at org.eclipse.jetty.util.IteratingCallback.processIterations(IteratingCallback.java:166)at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:126)at org.eclipse.jetty.server.HttpConnection.send(HttpConnection.java:296)at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:715)at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:751)at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:130)at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:124)at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:356)at java.io.ByteArrayOutputStream.writeTo(ByteArrayOutputStream.java:154)at org.glassfish.jersey.message.internal.CommittingOutputStream.flushBuffer(CommittingOutputStream.java:307)at org.glassfish.jersey.message.internal.CommittingOutputStream.commit(CommittingOutputStream.java:261)at org.glassfish.jersey.message.internal.CommittingOutputStream.close(CommittingOutputStream.java:276)at org.glassfish.jersey.message.internal.OutboundMessageContext.close(OutboundMessageContext.java:835)at org.glassfish.jersey.server.ContainerResponse.close(ContainerResponse.java:411)at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:645)at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:381)at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:371)at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:262)at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)at org.glassfish.jersey.internal.Errors.process(Errors.java:315)at org.glassfish.jersey.internal.Errors.process(Errors.java:297)at org.glassfish.jersey.internal.Errors.process(Errors.java:267)at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1010)at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:382)at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:345)at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:220)at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:711)at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1644)at ru.yandex.bayan2.integration.servlet.LoggingFilter.doFilter(LoggingFilter.java:27)at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1615)at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:550)at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1112)at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:479)at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1046)at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)at org.eclipse.jetty.server.Server.handle(Server.java:462)at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:281)at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:232)at org.eclipse.jetty.io.AbstractConnection$1.run(AbstractConnection.java:505)at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607)at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536)at java.lang.Thread.run(Thread.java:744)
Caused by: java.io.IOException: Connection reset by peerat sun.nio.ch.FileDispatcherImpl.writev0(Native Method)at sun.nio.ch.SocketDispatcher.writev(SocketDispatcher.java:51)at sun.nio.ch.IOUtil.write(IOUtil.java:148)at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:524)at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:169)... 50 more
2) When it starts doing so, we get lots of such exceptions:
[2014-04-14 12:41:55,524] DEBUG [Scheduler-340008923] SelectChannelEndPoint@f67ae6c{/10.0.0.1:60468<->35980,Open,in,out,-,-,30000,HttpConnection}{io=0,kio=0,kro=1} idle timeout expired[2014-04-14 12:41:55,524] DEBUG [Scheduler-340008923] ignored: WriteFlusher@7fdc861b{IDLE} java.util.concurrent.TimeoutException: Idle timeout expired: 30001/30000 ms[2014-04-14 12:41:55,529] DEBUG [Scheduler-340008923] SelectChannelEndPoint@69f1af68{/10.0.0.1:48730<->35980,Open,in,out,-,-,30000,HttpConnection}{io=0,kio=0,kro=1} idle timeout check, elapsed: 30000 ms, remaining: 0 ms
but sockets never get closed.
3) org.eclipse.jetty.io.SelectorManager reports a growing number of selected events:
...LOG.debug("Selector loop woken up from select, {}/{} selected", selected, _selector.keys().size());...
4) Sockets left in CLOSE_WAIT state.
As a result we have a growing number of sockets and finally "Too many open files" exception.
So the questions are
1) Where can I dig further?
2) Why AbstractEndPoint#onIdleExpired(TimeoutException) doesn't simply close itself. Instead it checks some conditions before doing that:
@Overrideprotected void onIdleExpired(TimeoutException timeout){boolean output_shutdown=isOutputShutdown();boolean input_shutdown=isInputShutdown();_fillInterest.onFail(timeout);_writeFlusher.onFail(timeout);if (isOpen() && output_shutdown || input_shutdown)close();}
3) Can this help us?
ServerConnector connector = new ServerConnector(...) {@Overrideprotected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectorManager.ManagedSelector selectSet, SelectionKey key) throws IOException {return new SelectChannelEndPoint(channel, selectSet, key, getScheduler(), getIdleTimeout()) {@Overrideprotected void onIdleExpired(TimeoutException timeout) {super.onIdleExpired(timeout);close();}};}};
Thanks.
_______________________________________________ jetty-users mailing list [email protected] https://dev.eclipse.org/mailman/listinfo/jetty-users
