Skip to content

Call Mono.timeout in WebFilter may hang up the response body #35283

@chentao106

Description

@chentao106

Call Mono.timeout in WebFilter occasional hang up the response body.
When the Controller response time equals the timeout value.

Use Case

I uses Spring boot Webflux in my Web Server, but there were requests hung up for days when TCP packet loss(Cause by firewall).
I tried to set timeout for each request, to fast fail when request hang up, but another problem come out.

Mono.timeout works in Controller

Code below works fine, but does not solve my problem(request header sended, but body hung up):

@RestController
public class TestController {
   @GetMapping("hello")
    public Mono<String> hello() {
        return Mono.just("hello world").delayElement(Duration.ofMillis(500)).timeout(Duration.ofMillis(500));
    }
}

Mono.timeout occasional hang up Response Body in a WebFilter

Code below occasional hang up Response Body(Response Header sended):

Controller:

@RestController
public class TestController {
   @GetMapping("hello")
    public Mono<String> hello() {
        return Mono.just("hello world").delayElement(Duration.ofMillis(500));
    }

TimeoutWebFilter

@Service
@Order(10)
public class TimeoutWebFilter implements WebFilter {
    @Nonnull
    @Override
    public Mono<Void> filter(@Nonnull ServerWebExchange exchange, WebFilterChain chain) {
        return chain.filter(exchange).timeout(Duration.ofMillis(500));
    }
}

New Problem

When I call the controller with Postman, occasional the Status Code and Headers received, but the Body hang up.
Server log:

        java.lang.UnsupportedOperationException: null
        at org.springframework.http.ReadOnlyHttpHeaders.set(ReadOnlyHttpHeaders.java:110) ~[spring-web-6.1.14.jar:6.1.14]
        Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
        ...

Reason(Maybe)

I think it is a concurrency conflict on sending Response.
WebFilter: Schedulers.parallel() detected timeout, send response header;
Controller: Logic finished, send response header——confict and trigger an error, interrupt the Response.

Proposal

Maybe there should be a Common timeout method for WebFlux Server stack, works like that:

  1. Properties like spring.webflux.server.timeout, to config Webflux Server timeout;
  2. Controller timeout implements by use AOP, for request handle timeout;
  3. WebFilter timeout implements, for request header received but body hang up.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions