简体   繁体   中英

Undertow how to do Non-blocking IO?

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?

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.

Undertow uses NIO, which means that a single thread handles all the requests. If you want to do blocking operations in your request handler, you have to dispatch this operation to a worker thread.

In your example, you put the thread to sleep, which means tha any request handling is put to sleep, since this thread handles all requests.

However even if you dispatched the operation to worker thread and put that to sleep, you still would see the blocking issue you mention. This is because you open the same url in several tabs on the same browser. The browsers have an internal blocking of their own. If you open the same url in different tabs, the second url will start the request after the first has finished. Try any url you want to see for yourself. You can easily be confused with this browser behaviour.

The easiest thing to do would be to wrap your handler in a BlockingHandler.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM