如separate question中所述,在使用Undertow时,所有处理都应在专用的Worker线程池中完成,如下所示:
public class Start {
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();
}
}
我知道BlockingHandler
可用于明确告诉Undertow将请求安排在专用线程池上以阻止请求。我们可以通过将HttpHandler
包装在BlockingHandler
的实例中来适应上面的示例,如下所示:
.setHandler(new BlockingHandler(new HttpHandler() {
这将适用于我们一直阻塞的呼叫。
但是,如果某些代码在大多数时间是非阻塞的,但有时需要阻塞调用,那么如何将那个阻塞调用变成非阻塞代码呢?例如,如果请求的值存在于缓存中,则以下代码将不会阻塞(它只是从某些Map<>
中获取),但是如果没有,则必须从数据库中获取它。
public class Start {
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;
}
if (valueIsPresentInCache(exchange)) {
return valueFromCache; // non-blocking
} else {
return fetchValueFromDatabase(); // blocking!!!
}
}
})
.build();
server.start();
}
}
根据docs,有一种方法HttpServerExchange.startBlocking()
,但是根据JavaDoc的说法,除非您确实需要使用输入流,否则此调用仍然是阻塞的。
调用此方法会将交换置于阻止模式,并创建一个 BlockingHttpExchange对象存储流。当交换是 在阻塞模式下,输入流方法变得可用,除了 目前,阻止 非阻塞模式
一个人如何将这种阻塞性呼叫变成非阻塞性呼叫?
答案 0 :(得分:0)
正确的方法是实际上在IO线程中执行逻辑(如果它是非阻塞的)。否则,将请求委托给专用线程,例如:
public class Example {
public static void main(String[] args) {
Undertow server = Undertow.builder()
.addListener(8080, "localhost")
.setHandler(new HttpHandler() {
public void handleRequest(HttpServerExchange exchange)
throws Exception {
if (valueIsPresentInCache(exchange)) {
getValueFromCache(); // non-blocking, can be done from IO thread
} else {
if (exchange.isInIoThread()) {
exchange.dispatch(this);
// we return immediately, otherwise this request will be
// handled both in IO thread and a Worker thread, throwing
// an exception
return;
}
fetchValueFromDatabase(); // blocking!!!
}
}
})
.build();
server.start();
}
}