如何在 Undertow 的非阻塞处理程序中执行阻塞代码?
Posted
技术标签:
【中文标题】如何在 Undertow 的非阻塞处理程序中执行阻塞代码?【英文标题】:How to execute blocking code in a non-blocking Handler in Undertow? 【发布时间】:2019-11-16 03:15:19 【问题描述】:如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 对象来存储流。当交换是 在阻塞模式下,输入流方法变得可用,除了 目前阻止一个 非阻塞模式
如何将这个阻塞调用变成非阻塞调用?
【问题讨论】:
【参考方案1】:正确的方法是在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();
【讨论】:
以上是关于如何在 Undertow 的非阻塞处理程序中执行阻塞代码?的主要内容,如果未能解决你的问题,请参考以下文章