spring-cloud / spring-cloud/spring-cloud-gateway
Unknown reason triggers .doOnCancel(() -> cleanup(exchange)) in NettyWriteResponseFilter occasionally
Open
Nobody has claimed this yet.
feedback-provided
- Dominant language
- Java
- Stars
- 4.9k
- Forks
- 3.5k
- Avg merge
- 20h 57m
- Merged PRs (30d)
- 8
Description
Describe the bug
Spring Cloud Gateway version:2.2.5
reactor-netty version :0.9.15
- Use method
ServerHttpResponse.writeWith(Mono<DataBuffer>instead ofServerHttpResponse.writeWith(Flux<DataBuffer>)inNettyWriteResponseFilter.javain high-concurrency scenarios triggersdoOnCancel(() -> cleanup(connection))occasionally - Method
doOnCancel(() -> cleanup(connection))will close the long connection between the gateway and downstream services, and this closure will not be monitored by the connection pool status, resulting in subsequent requests generating exceptionreactor.netty.channel.AbortedException: Connection has been closed BEFORE response while sending request body
Describe the solution you'd like
- Understanding the root cause of mono triggering doOnCancel
- Connection pool can monitor connection status when the connection is closed
Sample
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange)
.doOnError(throwable -> cleanup(exchange))
.then(Mono.defer(() -> {
Connection connection = exchange.getAttribute(CLIENT_RESPONSE_CONN_ATTR);
if (connection == null) {
return Mono.empty();
}
ServerHttpResponse response = exchange.getResponse();
final Flux<DataBuffer> body = connection
.inbound()
.receive()
.retain()
.map(byteBuf -> wrap(byteBuf, response));
// My changes are here
Mono<DataBuffer> newBody = body.single();
MediaType contentType = null;
try {
contentType = response.getHeaders().getContentType();
}
catch (Exception e) {}
return (isStreamingMediaType(contentType)
? response.writeAndFlushWith(body.map(Flux::just))
: response.writeWith(newBody));
})).doOnCancel(() -> cleanup(exchange));
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in NettyWriteResponseFilter.java and compare the reported writeWith(Mono) path with the Flux path. Reproduce the high-concurrency scenario and trace when doOnCancel(() -> cleanup(exchange)) runs. Done means the cancellation cause is understood and connection closure is correctly reflected in connection-pool status.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring, spring-boot
- Domain
- api, backend, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100