Undertow how to do Non-blocking IO?

后端 未结 3 1960
清歌不尽
清歌不尽 2021-02-20 10:16

I am using Undertow to create a simple application.

public class App {
    public static void main(String[] args) {
        Undertow server = Undertow.builder().         


        
相关标签:
3条回答
  • 2021-02-20 10:42

    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();
        }
    }
    
    0 讨论(0)
  • 2021-02-20 10:53

    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.

    0 讨论(0)
  • 2021-02-20 11:07

    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.

    0 讨论(0)
提交回复
热议问题