Почему Vertx выдает предупреждение даже с атрибутом блокировки?

#asynchronous #vert.x #quarkus #blocking

Вопрос:

У меня есть приложение Quarkus, в котором я использую шину событий.

код, о котором идет речь, выглядит следующим образом:

     @ConsumeEvent(value = "execution-request", blocking = true)
    @Transactional
    @TransactionConfiguration(timeout = 3600)
    public void consume(final Message<ExecutionRequest> msg) {
        try {
            execute(...);
        } catch (final Exception e) {
            // some logging
        }
    }

    private void execute(...)
            throws InterruptedException {
        // it actually runs a long running task, but for 
        // this example this has the same effect
        Thread.sleep(65000);
    }

 

Почему я все еще получаю

 WARN  [io.ver.cor.imp.BlockedThreadChecker] (vertx-blocked-thread-checker) Thread Thread[vert.x-worker-thread-0,5,main] has been blocked for 63066 ms, time limit is 60000 ms: io.vertx.core.VertxException: Thread blocked
 

Я что, я делаю что-то не так? Является ли параметр блокировки в аннотации ConsumeEvent недостаточным, чтобы разрешить эту обработку в отдельном работнике?

Ответ №1:

Ваша аннотация работает так, как задумано; метод выполняется в рабочем потоке. Вы можете определить это как по имени потока «vert.x-рабочий поток-0», так и по времени ожидания 60 секунд до регистрации предупреждений. Я полагаю, что поток eventloop имеет только 3-секундный тайм-аут.

Пул рабочих потоков Vert.x по умолчанию не предназначен для «очень» продолжительного кода блокировки, как указано в их документах:

Предупреждение:

Код блокировки должен блокироваться в течение разумного промежутка времени (т. е. не более нескольких секунд). Длительные операции блокировки или операции опроса (т. е. поток, который вращается в цикле, блокируя события опроса) исключаются. Когда операция блокировки продлится более 10 секунд, средство проверки заблокированных потоков выведет сообщение на консоль. При длительных операциях блокировки должен использоваться выделенный поток, управляемый приложением, который может взаимодействовать с вершинами с помощью шины событий или runOnContext

В этом сообщении упоминается, что блокировка более чем на 10 секунд вызывает предупреждение, но я думаю, что это опечатка; по умолчанию на самом деле 60.

Чтобы избежать предупреждения, вам нужно будет создать выделенный WorkerExecutor (via vertx.createSharedWorkerExecutor ), настроенный с очень высоким maxExcecuteTime . Однако, похоже, вы не можете указать @ConsumeEvent аннотации использовать ее вместо рабочего пула по умолчанию, поэтому вам также потребуется вручную создать потребителя шины событий или использовать обычную @ConsumeEvent аннотацию, но вызывать workerExectur.executeBlocking внутри нее.