Как выполнить блокирующий код в неблокирующем обработчике в Undertow? - PullRequest
0 голосов
/ 05 июля 2019

Как описано в отдельном вопросе , при использовании Undertow вся обработка должна выполняться в выделенном пуле рабочих потоков, который выглядит следующим образом:

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

Согласно документам , существует метод HttpServerExchange.startBlocking(), но согласно JavaDoc, если вам действительно не нужно использовать входной поток, этот вызов все еще является блокирующим.

Вызов этого метода переводит обмен в режим блокировки и создает BlockingHttpExchange объект для хранения потоков. Когда обмен в режиме блокировки становятся доступными методы входного потока, кроме что в настоящее время нет большой разницы между блокированием неблокирующие режимы

Как превратить этот блокирующий вызов в неблокирующий?

...