2014-02-28 7 views
10

Ich verwende Undertow, um eine einfache Anwendung zu erstellen.Undertow wie Non-blocking IO?

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(); 
    } 
} 

Ich öffne einen Browser-Tab auf localhost:8080 und ich öffne ein zweites Tab auch auf localhost:8080

Dieses Mal ist die erste Lasche 5 Sekunden warten, und die zweiten 10 Sekunden

warten Warum ist es so?

Antwort

9

Der HttpHandler wird in einem E/A-Thread ausgeführt. Wie bereits erwähnt in the documentation:

IO-Threads ausführen nicht blockierende Aufgaben und sollten ausführen nie Operationen blockiert, weil sie für mehrere Verbindungen verantwortlich sind, so dass während der Operation andere Verbindungen blockiert wird im Wesentlichen hängen. Ein IO-Thread pro CPU-Kern ist ein angemessener Standard.

Die request lifecycle docs diskutieren, wie eine Anfrage an einen Worker-Thread Versandfertig:

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(); 
    } 
} 

ich festgestellt, dass Sie nicht unbedingt pro Anfrage ein Worker-Thread bekommen - wenn ich einen Haltepunkt auf dem Header gesetzt Ich habe ungefähr einen Thread pro Client bekommen. Es gibt Lücken sowohl im Undertow als auch im zugrunde liegenden XNIO docs, also bin ich mir nicht sicher, was die Absicht ist.

+0

ok. Vielen Dank:) – eclipse

+0

@McDowell Ist Node.js anders, wie es Async-Kommunikation macht? – johnny

4

Undertow verwendet NIO, was bedeutet, dass ein einzelner Thread alle Anforderungen behandelt. Wenn Sie in Ihrem Anforderungshandler blockierende Vorgänge durchführen möchten, müssen Sie diesen Vorgang an einen Arbeitsthread senden.

In Ihrem Beispiel legen Sie den Thread in den Ruhezustand, was bedeutet, dass die Verarbeitung von Anfragen in den Ruhezustand versetzt wird, da dieser Thread alle Anfragen behandelt.

Aber selbst wenn Sie die Operation an den Worker-Thread gesendet und diesen in den Ruhezustand versetzt haben, sehen Sie immer noch das von Ihnen erwähnte Blockierungsproblem. Dies liegt daran, dass Sie dieselbe URL in mehreren Registerkarten desselben Browsers öffnen. Die Browser haben eine interne Blockierung ihrer eigenen. Wenn Sie dieselbe URL auf verschiedenen Registerkarten öffnen, startet die zweite URL die Anfrage, nachdem die erste beendet wurde. Probieren Sie eine beliebige URL aus, die Sie selbst sehen möchten. Sie können leicht mit diesem Browserverhalten verwechselt werden.

3

Am einfachsten wäre es, Ihren Handler in einen BlockingHandler zu verpacken.

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(); 
    } 
} 
Verwandte Themen