Использование стороннего http-клиента на Armeria

Я открываю для себя фреймворк Armeria и хочу использовать REST-сервис. Используя Armeria WebClient:

WebClient webClient = WebClient.of("http://localhost:9090");
RequestHeaders getJson = RequestHeaders.of(HttpMethod.GET, "/some-service",
            HttpHeaderNames.CONTENT_TYPE, "application/json", "SomeHeader", "armeriaTest");
return webClient.execute(getJson).aggregate().thenApply(resp->{
        if(HttpStatus.OK.equals(resp.status())) {
            return parseBody(resp.contentUtf8());
        }else if(HttpStatus.BAD_REQUEST.equals(resp.status())){
            throw new IllegalStateException("not exists");
        }
        throw new RuntimeException("Error");
    });

Этот код возвращает CompletionStage, который будет разрешен асинхронно, потому что, если я выполняю join() или get() прямо здесь, вызывает "java.lang.IllegalStateException: цикл событий блокировки, не делайте этого".

Мой вопрос: что, если я хочу использовать стороннюю библиотеку httpclient (например, Apache HttpClient) вместо Интернета? Вызов клиента тоже должен быть заключен в Будущее? Как мне управлять клиентскими запросами, чтобы они соответствовали подходу фреймворка и избегали проблемы "Блокирующий цикл событий"?

Спасибо всем!

1 ответ

Решение

Да. Никогда не следует выполнять какие-либо операции блокировки, когда ваш код выполняется в потоке цикла событий. Вы можете выполнить операцию блокировки, отправив ее в другой пул потоков, предназначенный для обработки операций блокировки.

Если вы используете Armeria на стороне сервера, вы можете получить его через ServiceRequestContext.blockingTaskExecutor():

Server server = Server
    .builder()
    .service("/", (ctx, req) -> {
        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
            // Perform some blocking operations that return a string.
        }, ctx.blockingTaskExecutor());

        CompletableFuture<String> f2 = f1.thenApply(result -> {
            // Transform the result into an HttpResponse.
            return HttpResponse.of("Result: %s", result);
        });

        return HttpResponse.from(f2);
    })
    .build();

Если вы не используете Armeria на стороне сервера, вы можете использовать другие Executor предоставляемые вашей платформой, или вы даже можете создать новый ThreadPoolExecutor предназначен для обработки блокирующих операций.

Другие вопросы по тегам