-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
I have googled and tried with GPT, but no luck, so asking in this place, if not appropriate I will delete it.
I am using webClient in my springboot app like below code shows, after several hours later, there would be errors like "4194304 bytes of direct buffer memory", also pasted below...
The error all happens to one fixed service which usually returns around 20M-30M response, other get cmd works just fine...
I use Spring-webflux-5.3.31 + spring boot 2.17.18, openJdk 17.0.8_1
private void initializeWebClient() {
log.info("Initializing released webClient");
ConnectionProvider connectionProvider = ConnectionProvider.builder("pool")
.maxConnections(100)
.pendingAcquireTimeout(Duration.ofSeconds(60))
.build();
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
.codecs(configuer -> configuer.defaultCodecs().maxInMemorySize(500 * 1024 * 1024))
.build();
HttpClient httpClient = HttpClient.create(connectionProvider)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 100000)
.doOnConnected(connection -> {
connection.addHandlerLast(new ReadTimeoutHandler(100000, TimeUnit.MILLISECONDS));
connection.addHandlerLast(new WriteTimeoutHandler(100000, TimeUnit.MILLISECONDS));
});
this.webClient = org.springframework.web.reactive.function.client.WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.exchangeStrategies(exchangeStrategies)
.build();
}
public String get(String url, Map<String, String> headers) {
String response = this.webClient.get()
.uri(url)
.headers(httpHeaders -> headers.forEach(httpHeaders::add))
.retrieve()
.onStatus(HttpStatus::isError,
clientResponse -> clientResponse.bodyToMono(String.class)
.flatMap(errorMessage -> Mono.error(new RuntimeException("Error: " + errorMessage))))
.bodyToMono(String.class)
.retryWhen(Retry.fixedDelay(MAX_RETRIES, RETRY_DELAY)
.doBeforeRetry(retrySignal -> log.info("Retrying... attempt: {}", retrySignal.totalRetries() + 1)))
.doOnError((throwable) -> {
log.error("Error happened for get: {}, detail error: {}", url, throwable.getMessage());
throw new RuntimeException("Error happened for get " + url, throwable);
})
.block();
return response;
}
Caused by: java.lang.OutOfMemoryError: Cannot reserve 4194304 bytes of direct buffer memory (allocated: 1070302774, limit: 1073741824)
at java.base/java.nio.Bits.reserveMemory(Unknown Source)
at java.base/java.nio.DirectByteBuffer.(Unknown Source)
at java.base/java.nio.ByteBuffer.allocateDirect(Unknown Source)
at io.netty.buffer.PoolArena$DirectArena.allocateDirect(PoolArena.java:701)
at io.netty.buffer.PoolArena$DirectArena.newChunk(PoolArena.java:676)
at io.netty.buffer.PoolArena.allocateNormal(PoolArena.java:215)
at io.netty.buffer.PoolArena.tcacheAllocateNormal(PoolArena.java:197)
at io.netty.buffer.PoolArena.allocate(PoolArena.java:139)
at io.netty.buffer.PoolArena.allocate(PoolArena.java:129)
at io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:396)
at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:188)
at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:179)
at io.netty.buffer.AbstractByteBufAllocator.ioBuffer(AbstractByteBufAllocator.java:140)
at io.netty.channel.DefaultMaxMessagesRecvByteBufAllocator$MaxMessageHandle.allocate(DefaultMaxMessagesRecvByteBufAllocator.java:120)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:150)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)