spring-cloud / spring-cloud-gateway

An API Gateway built on Spring Framework and Spring Boot providing routing and more.
http://cloud.spring.io
Apache License 2.0
4.55k stars 3.33k forks source link

Unknown reason triggers .doOnCancel(() -> cleanup(exchange)) in NettyWriteResponseFilter occasionally #3301

Open renjie6666 opened 8 months ago

renjie6666 commented 8 months ago

Describe the bug Spring Cloud Gateway version:2.2.5 reactor-netty version :0.9.15

Describe the solution you'd like

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));
}
spencergibb commented 8 months ago

Is this still an issue with the supported version of spring cloud 4.1.1?

renjie6666 commented 8 months ago

Is this still an issue with the supported version of spring cloud 4.1.1?

yes, the issue still exists. Please mainly focus on the impact of my changes to the source code NettyWriteResponseFilter. I added comments to the sample code.

spencergibb commented 8 months ago

Can you tell me how to reproduce it?

renjie6666 commented 8 months ago

Test topology:

  1. Jmeter (Constructing HTTP post requests,100 qps is enough)->
  2. Spring Cloud Gateway( version 4.1.1 can reproduce and make the modifications according to my previous comments in NettyWriteResponseFilter )->
  3. DownStream Services(a netty http server Or a springboot server)

Notes:

renjie6666 commented 8 months ago

The issue I asked is related to this one? https://github.com/reactor/reactor-netty/issues/741

haoran1221 commented 7 months ago

Does the question subject have a solution? I have also been troubled by this issue in my project for a long time..