Spring Boot Webflux/Netty - Detect closed connection

后端 未结 2 1545
时光取名叫无心
时光取名叫无心 2020-12-31 13:57

I\'ve been working with spring-boot 2.0.0.RC1 using the webflux starter (spring-boot-starter-webflux). I created a simple controller that returns a

2条回答
  •  旧巷少年郎
    2020-12-31 14:50

    Since this is a known issue (see Brian Clozel's answer), I ended up using one Flux to fetch my real data and having another one in order to implement some sort of ping/heartbeat mechanism. As a result, I merge both together with Flux.merge().

    Here you can see a simplified version of my solution:

    @RestController
    public class Demo {
    
        public interface Notification{}
    
        public static class MyData implements Notification{
            …
            public boolean isEmpty(){…}
        }
    
        @GetMapping(value = "/", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
        public Flux> getNotificationStream() {
            return Flux.merge(getEventMessageStream(), getHeartbeatStream());
        }
    
        private Flux> getHeartbeatStream() {
            return Flux.interval(Duration.ofSeconds(2))
                    .map(i -> ServerSentEvent.builder().event("ping").build())
                    .doFinally(signalType ->System.out.println("END"));
        }
    
        private Flux> getEventMessageStream() {
            return Flux.interval(Duration.ofSeconds(30))
                    .map(i -> {
    
                        // TODO e.g. fetch data from somewhere,
                        // if there is no data return an empty object
    
                        return data;
                    })
                    .filter(data -> !data.isEmpty())
                    .map(data -> ServerSentEvent
                            .builder(data)
                            .event("message").build());
        }
    }
    

    I wrap everything up as ServerSentEvent. Notification is just a marker interface. I use the event field from the ServerSentEvent class in order to separate between data and ping events. Since the heartbeat Flux sends events constantly and in short intervals, the time it takes to detect that the client is gone is at most the length of that interval. Remember, I need that because it might take a while before I get some real data that can be sent and, as a result, it might also take a while before it detects that the client is gone. Like this, it will detect that the client is gone as soon as it can’t sent the ping (or possibly the message event).

    One last note on the marker interface, which I called Notification. This is not really necessary, but it gives some type safety. Without that, we could write Flux> instead of Flux> as return type for the getNotificationStream() method. Or also possible, make getHeartbeatStream() return Flux>. However, like this it would allow that any object could be sent, which I don’t want. As a consequence, I added the interface.

提交回复
热议问题