5

I am having a client doing requests to a server which could take some time to respond.

When the server wanted to reply it was throwing the following exception:

The connection was broken. It was probably closed by the client.

org.eclipse.jetty.io.EofException at org.eclipse.jetty.io.nio.SelectChannelEndPoint.blockWritable(SelectChannelEndPoint.java:435) at org.eclipse.jetty.http.AbstractGenerator.blockForOutput(AbstractGenerator.java:512) at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:159) at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:101) at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221) at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:282) at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125) at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:135) at java.io.OutputStreamWriter.write(OutputStreamWriter.java:220) at java.io.Writer.write(Writer.java:157) at org.restlet.representation.StringRepresentation.write(StringRepresentation.java:237) at org.restlet.representation.CharacterRepresentation.write(CharacterRepresentation.java:76) at org.restlet.engine.adapter.ServerCall.writeResponseBody(ServerCall.java:509) at org.restlet.engine.adapter.ServerCall.sendResponse(ServerCall.java:453) at org.restlet.ext.jetty.internal.JettyCall.sendResponse(JettyCall.java:312) at org.restlet.engine.adapter.ServerAdapter.commit(ServerAdapter.java:196) at org.restlet.engine.adapter.HttpServerHelper.handle(HttpServerHelper.java:153) at org.restlet.ext.jetty.JettyServerHelper$WrappedServer.handle(JettyServerHelper.java:170) at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:452) at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:894) at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:948) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:943) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235) at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:622) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538) at java.lang.Thread.run(Thread.java:722)

When that happens, the client hangs indefinitely.

Here is a code example which reproduces the problem:

Server side:

    public static void main(String[] args) throws Exception  {
        Context context = new Context();
        Server server = new Server(context, Protocol.HTTP, 8182, DummyServerResource.class);
        server.start();
    }

public class DummyServerResource extends ServerResource {

    @Get
    public String retrieve() throws InterruptedException {
        Thread.sleep(1000 * 20);
        return "Dummy";
    }
}

Client side:

public static void main(String[] args) throws IOException, InterruptedException {
    Context context = new Context();
    context.getParameters().add("maxIoIdleTimeMs", "0");
    Client client = new Client(context, Protocol.HTTP);
    ClientResource cr = new ClientResource("http://localhost:8182");
    cr.setNext(client);
    Representation get = cr.get();
    System.out.println(get.getText());
    Thread.sleep(1000 * 50);
    ClientResource cr2 = new ClientResource("http://localhost:8182");
    cr2.setNext(client);
    Representation get2 = cr2.get();
    System.out.println(get2.getText());

}

What is going on here and how do I eliminate the error?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
avandecreme
  • 971
  • 1
  • 8
  • 18

2 Answers2

2

I opened an issue about that in GitHub weeks ago. Thanks for sharing. https://github.com/restlet/restlet-framework-java/issues/675.

devmao
  • 670
  • 8
  • 18
0

What happens is that the server closes the idling socket after 30 seconds by default and doesn't try to reopen a new one.

The workaround I found is to set the ioMaxIdleTimeMs paramter to 0 which means no timeout.

Here is the working server code:

public static void main(String[] args) throws Exception  {
    Context context = new Context();
    context.getParameters().add("maxIoIdleTimeMs", "0");
    context.getParameters().add("ioMaxIdleTimeMs", "0");
    Server server = new Server(context, Protocol.HTTP, 8182, DummyServerResource.class);
    server.start();
}

Note that I set both maxIoIdleTimeMs and ioMaxIdleTimeMs. In my case it's ioMaxIdleTimeMs which is used. It is the parameter use by Jetty.

But if you are not using Jetty, I suspect it might use the parameter maxIoIdleTimeMs defined in org.restlet.engine.connector.BaseHelper.java

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335