消息顺序
来自代理的消息被发布到 clientOutboundChannel,并从那里写入 WebSocket 会话。由于该频道由 ThreadPoolExecutor 提供支持,消息是在不同的线程中处理的,因此客户端接收到的序列可能与发布的准确顺序不符。
开启顺序发布
要启用顺序发布,请按如下方式设置 setPreservePublishOrder 标志:
java
@Configuration
@EnableWebSocketMessageBroker
public class PublishOrderWebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// ...
registry.setPreservePublishOrder(true);
}
}kotlin
@Configuration
@EnableWebSocketMessageBroker
class PublishOrderWebSocketConfiguration : WebSocketMessageBrokerConfigurer {
override fun configureMessageBroker(registry: MessageBrokerRegistry) {
// ...
registry.setPreservePublishOrder(true)
}
}xml
<websocket:message-broker preserve-publish-order="true">
<!-- ... -->
</websocket:message-broker>设置此标志后,同一客户端会话中的消息将逐个发布到 clientOutboundChannel,从而保证发布顺序。注意,这会产生少量的性能开销,因此只有在确实需要时才应启用。
开启顺序接收
同样,来自客户端的消息会被发送到 clientInboundChannel。由于该频道也由线程池支持,因此处理顺序可能与接收顺序不一致。
要启用顺序接收,请按如下方式配置:
java
@Configuration
@EnableWebSocketMessageBroker
public class ReceiveOrderWebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.setPreserveReceiveOrder(true);
}
}kotlin
@Configuration
@EnableWebSocketMessageBroker
class ReceiveOrderWebSocketConfiguration : WebSocketMessageBrokerConfigurer {
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
registry.setPreserveReceiveOrder(true)
}
}补充教学
1. 为什么默认不保证顺序?
为了追求极致的吞吐量。在高并发环境下,使用线程池并行处理消息可以显著提高服务器响应速度。如果消息 A 和消息 B 之间没有逻辑依赖(例如来自两个不同群聊的消息),并行处理是最高效的。
2. 性能开销在哪里?
当开启顺序保证时,Spring 会确保同一 Session 的下一条消息必须等待前一条消息处理完成。这本质上将该 Session 的处理退化为了串行,会增加排队延迟。
3. 适用场景
- 指令类消息: 例如游戏动作指令,A 必须在 B 之前执行。
- 严格的状态流转: 例如订单状态从“待支付”变更为“已支付”,顺序至关重要。