Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring WebClient throws javax.net.ssl.SSLException: SSLEngine closed already when used heavily

That's my code:

WebClient.create().post()
                .uri(URI.create(url))
                .header("Authorization",
                        "Basic " + Base64Utils.encodeToString(("username:password").getBytes(UTF_8)))
                .body(Mono.just(requestBody), Object.class)
                .retrieve()
                .bodyToMono(responseType)

I call this function from multiple threads at the same time. When I only call it around 20~30 times in a single run it works perfectly fine. But when I call it 500~600 times in around 2 minutes (to the same URL) it throws

javax.net.ssl.SSLException: SSLEngine closed already
    at io.netty.handler.ssl.SslHandler.wrap(...)(Unknown Source)

EDIT

I've tried creating only one instance of WebClient but it still throws the same exception

like image 872
AvielNiego Avatar asked Oct 25 '25 02:10

AvielNiego


2 Answers

I found out this is happening due to this issue https://github.com/reactor/reactor-netty/issues/413

To resolve it you need to create WebClient like that:

WebClient webClient = WebClient.builder()
               .clientConnector(new ReactorClientHttpConnector(options -> {
                   options.poolResources(PoolResources.fixed("httpPool")).compression(true);
               })).build();

you can change the pool size by calling PoolResources.fixed with its second parameter

Another solution is to replace this Async http client with another one like this one https://github.com/AsyncHttpClient/async-http-client

like image 95
AvielNiego Avatar answered Oct 27 '25 00:10

AvielNiego


Calling WebClient.create() repeatedly creates and initializes HTTP resources multiple times.

Without more details about this particular issue or a complete stacktrace, it's hard to pinpoint the exact problem here. But I suspect that creating a client HTTP connector for each call is wasteful and might cause issues with setting up SSL on the client side.

You could try instead:

WebClient webClient = WebClient.create();
// then in your for loop
webClient.post() //...

If you're using Spring Boot, you should instead inject a WebClient.Builder instance and use it to create a WebClient instance.

like image 21
Brian Clozel Avatar answered Oct 26 '25 22:10

Brian Clozel