Использование стороннего 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
предназначен для обработки блокирующих операций.