Webflux-在并行执行2个WebClient请求时如何防止IllegalReferenceCountException

问题描述

我正在使用spring WebClient并行进行两个调用。 调用结果之一将作为ResponseEntity传递回去,而另一个结果将被检查然后被忽略。尽管事务都成功,但是我看到在实际执行任何WebClient调用之前发生了IllegalReferenceCountException。 我在日志记录中看到的是容器记录了异常,然后成功执行了我的两个HTTP请求,并将其中一个响应返回给客户端。
如果shouldBackfill()函数返回false,那么我将执行一个HTTP请求并返回该响应(并且不会发生IllegalReferenceCountException)。

最初,我以为我应该在我忽略的第二个响应中发布参考。 如果我尝试直接在WebClient响应上调用releaseBody()。 (请参阅https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/client/ClientResponse.html),这无济于事。我现在假设容器正在检测到我忽略的WebClient请求处于非法状态,因此是错误检测。但是我不明白的是,实际请求是在记录IllegalReferenceCountException之后发生的。

这里有关如何解决此问题的任何想法?我想知道异常是否实际上不是任何泄漏。

代码如下:


fun execute(routeHttpRequest: RouteHttpRequest): Mono<ResponseEntity<String>> =
        propertyRepository.getProperty(routeHttpRequest.propertyId.orDefault())
            .flatMap {
                val status = it.getOrElse { unknownStatus(routeHttpRequest.propertyId.orDefault()) }
                val response1 = execute(routeHttpRequest,routingRepository.webClientFor(routeHttpRequest))
                if (shouldBackfill(routeHttpRequest,status.type())) {
                    val response2 =
                        execute(routeHttpRequest,routingRepository.shadowOrBackfillWebClientFor(routeHttpRequest))
                    zip(response1,response2).map { response ->
                        compare(routeHttpRequest,response.t1,response.t2,status.type())
                        response.t1 // response.t2 is NOT returned here..
                    }
                } else response1
            }

    // This function returns a wrapper on a spring Webclient that makes an HTTP post.
    // 
    private fun execute(routeHttpRequest: RouteHttpRequest,client: Mono<MyWebClient>) =
        client
            .flatMap { dataService.execute(routeHttpRequest,it) }
            .subscribeOn(Schedulers.elastic()) // TODO: consider a dedicated executor here?

    private fun shouldBackfill(routeHttpRequest: RouteHttpRequest,migrationStatus: MigrationStatusType): Boolean {
       ... this logic returns true when we should execute 2 requests in parallel
    }


这是异常和部分跟踪:

io.netty.util.IllegalReferenceCountException: refCnt: 0,decrement: 1
    at io.netty.util.internal.ReferenceCountUpdater.toLiveRealRefCnt(ReferenceCountUpdater.java:74)
    at io.netty.util.internal.ReferenceCountUpdater.release(ReferenceCountUpdater.java:138)
    at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:100)
    at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:88)

解决方法

对不起,您没有发布确切的代码。修复-我将传入的http请求org.springframework.core.io.buffer.DataBuffer直接传递给WebClient请求主体。这是有意的,因为我的应用程序充当代理服务。当我尝试并行进行两个出站WebClient调用时,出现了问题-容器尝试释放基础缓冲区两次,并且发生IllegalReferenceCountException。我的解决方法是在将请求发送到目的地之前,仅将DataBuffer字节数组复制到新缓冲区中。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...