Spring Reactive: java.io.IOException: An establish

2019-08-07 12:15发布

问题:

Working with spring reactive application, I created a rest service which produces an event every second. The code for my rest controller is:

@GetMapping(value = "/events", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Event> getEvents() {
    Flux<Event> eventFlux = Flux.fromStream(Stream.generate(() -> new Event(new Random().nextLong(), "Hello Event")));
    Flux<Long> emmitFlux = Flux.interval(Duration.ofSeconds(1));
    return Flux.zip(eventFlux, emmitFlux).map(Tuple2::getT1);
}

The application runs fine at the url: localhost:8080/events in the browser. I get a new event every second. But when I close the browser I get the following error:

java.io.IOException: An established connection was aborted by the software in your host machine

Have anyone faced and resolved any similar issue with spring-reactive?

回答1:

You see this message because Spring WebFlux has no proper way to differentiate a regular SSE stream cancellation from a unexpected connection closing due to network connectivity issue for example.

We even filter some typical messages like "broken pipe", but I guess you are on windows and exception messages are localized so we can't do that in a reliable way.

That said as part of SPR-16688 which will be available as of Spring Framework 5.0.6 / Spring Boot 2.0.2, we have improved the logging for such use case in order to make it more relevant:

  • Reactor Netty does not log errors in addition to throwing the exception, see reactor-netty#339
  • WebFlux server now uses warning error log level instead of error
  • Only the message is printed in the log, not the stacktrace which is mostly useless in reactive world