我正在尝试使用Springframework SimpMessagingTemplate(默认的Stomp实现)来传输时间序列数据,以将消息广播到SockJS客户端订阅的主题。但是,消息是无序接收的。服务器是单线程,消息按时间戳按升序发送。客户端以某种方式收到了订单中的消息。
我正在使用stompjs和springframework(4.1.6版本)的最新版本。
答案 0 :(得分:10)
找到此问题的根本原因。消息从应用程序实现的角度以“正确”的顺序发送(即,在一个线程或至少是线程安全的方式中调用convertAndSend())。但是,Springframework Web套接字使用reactor-tcp实现,它将处理消息来自线程池的clientOutboundChannel。因此消息可以按它们到达的不同顺序写入tcp套接字。当我配置web套接字限制clientOutboundChannel的1个线程时,保留订单。
这个问题不在SocketJS中,而是当前Spring Web套接字设计的限制。
答案 1 :(得分:8)
这是Spring网络套接字设计问题。要以有效顺序接收消息,您必须将websocket客户端的corePoolSize设置为1。
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketMessageBrokerConfiguration extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
registration.taskExecutor().corePoolSize(1);
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.taskExecutor().corePoolSize(1);
}
}
答案 2 :(得分:2)
我也遇到过这个问题。我不喜欢将我的线程池大小限制为1,这将导致我的应用程序的开销。相反,我使用StripedExecutorService来处理进出我的应用程序的消息。此类执行程序服务可保证对具有相同条带的任务的消息进行有序处理。对我来说,我使用WebSocket会话ID作为条带。通过您的入站,代理和出站通道上的ChannelRegistration.taskExecutor()注册此执行程序,这将保证有序消息。明智地选择你的条纹。
答案 3 :(得分:1)
看起来好像有一个内置的带区执行器,所以只需启用它即可:
@Override
protected void configureMessageBroker(MessageBrokerRegistry registry) {
// ...
registry.setPreservePublishOrder(true);
}