Spring 5反应式网络套接字:客户端未从热流中接收相同的数据

时间:2019-03-06 12:48:36

标签: java spring-webflux project-reactor

我在WebSocketHandler的实现中拥有此功能:

@Override
public Mono<Void> handle(WebSocketSession session) {

    return session.send(
       session.receive()
              .flatMap(webSocketMessage -> {
                  int id = Integer.parseInt(webSocketMessage.getPayloadAsText());

                  Flux<EfficiencyData> flux = service.subscribeToEfficiencyData(id);
                  var publisher = flux
                      .<String>handle((o, sink) -> {
                         try {
                            sink.next(objectMapper.writeValueAsString(o));
                         } catch (JsonProcessingException e) {
                            e.printStackTrace();                               
                         }
                      })
                      .map(session::textMessage);

                  return publisher;
              })
    );
}

Flux<EfficiencyData>当前是用于在服务中进行测试的,如下所示:

public Flux<EfficiencyData> subscribeToEfficiencyData(long weavingLoomId) {
    return Flux.interval(Duration.ofSeconds(1))
               .map(aLong -> {
                   longAdder.increment();
                   return new EfficiencyData(new MachineSpeed(
                           RotationSpeed.ofRpm(longAdder.intValue()),
                           RotationSpeed.ofRpm(0),
                           RotationSpeed.ofRpm(400)));
               }).publish().autoConnect();
}

我正在使用publish().autoConnect()使其成为热门视频流。我创建了一个单元测试,该单元测试启动了两个线程,它们对返回的Flux执行此操作:

flux.log().handle((s, sink) -> {
            LOGGER.info("{}", s.getMachineSpeed().getCurrent());
        }).subscribe();

在这种情况下,我看到两个线程每秒都打印出相同的值。

但是,当我打开2个浏览器选项卡时,在两个网页中都看不到相同的值。连接的Websocket客户端越多,则它们之间的值就越分开(因此,原始Flux中的每个值似乎都发送给了一个不同的客户端,而不是发送给所有客户端)。

1 个答案:

答案 0 :(得分:2)

感谢Brian Clozel on twitter,设法解决了这个问题。

问题在于,对于每个连接的Websocket客户端,我调用service.subscribeToEfficiencyData(id)方法,该方法每次被调用时都会返回 new Flux。因此,当然,这些独立的Flux不会在不同的Websocket客户端之间共享。

为解决此问题,我在服务的构造函数或服务的Flux方法中创建了PostConstruct实例,因此subscribeToEfficiencyData每次都返回相同的Flux实例。

请注意,Flux上的.publish().autoConnect()仍然很重要,因为没有该套接字,客户端将再次看到不同的值!