Undertow how to do Non-blocking IO?

eclipse picture eclipse · Feb 28, 2014 · Viewed 9.5k times · Source

I am using Undertow to create a simple application.

public class App {
    public static void main(String[] args) {
        Undertow server = Undertow.builder().addListener(8080, "localhost")
                .setHandler(new HttpHandler() {

                    public void handleRequest(HttpServerExchange exchange) throws Exception {
                        Thread.sleep(5000);
                        exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
                        exchange.getResponseSender().send("Hello World");
                    }

                }).build();
        server.start();
    }
}

I open a browser tab on localhost:8080 and I open a second tab also on localhost:8080

This time the first tab will wait 5 seconds, and the second will wait 10 seconds

Why is it so?

Answer

McDowell picture McDowell · Feb 28, 2014

The HttpHandler is executing in an I/O thread. As noted in the documentation:

IO threads perform non blocking tasks, and should never perform blocking operations because they are responsible for multiple connections, so while the operation is blocking other connections will essentially hang. One IO thread per CPU core is a reasonable default.

The request lifecycle docs discuss how to dispatch a request to a worker thread:

import io.undertow.Undertow;
import io.undertow.server.*;
import io.undertow.util.Headers;

public class Under {
  public static void main(String[] args) {
    Undertow server = Undertow.builder()
        .addListener(8080, "localhost")
        .setHandler(new HttpHandler() {
          public void handleRequest(HttpServerExchange exchange)
              throws Exception {
            if (exchange.isInIoThread()) {
              exchange.dispatch(this);
              return;
            }
            exchange.getResponseHeaders()
                    .put(Headers.CONTENT_TYPE, "text/plain");
            exchange.getResponseSender()
                    .send("Hello World");
          }
        })
        .build();
    server.start();
  }
}

I noted that you won't necessarily get one worker thread per request - when I set a breakpoint on the header put I got about one thread per client. There are gaps in both the Undertow and the underlying XNIO docs so I'm not sure what the intention is.