外部代理
简单代理虽然易于起步,但由于功能受限且不支持集群,无法满足严肃的生产环境需求。作为替代方案,你可以将应用程序升级为使用全功能的消息代理(Message Broker)。
请参阅你选择的消息代理(如 RabbitMQ、ActiveMQ 等)的 STOMP 文档并安装运行。
启用代理中继 (Broker Relay)
在 Spring 配置中使用 enableStompBrokerRelay 替代简单代理:
java
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/portfolio").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 目的地以 /topic 或 /queue 开头的将被转发给外部代理
registry.enableStompBrokerRelay("/topic", "/queue");
registry.setApplicationDestinationPrefixes("/app");
}
}kotlin
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfiguration : WebSocketMessageBrokerConfigurer {
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
registry.addEndpoint("/portfolio").withSockJS()
}
override fun configureMessageBroker(registry: MessageBrokerRegistry) {
registry.enableStompBrokerRelay("/topic", "/queue")
registry.setApplicationDestinationPrefixes("/app")
}
}xml
<websocket:message-broker application-destination-prefix="/app">
<websocket:stomp-endpoint path="/portfolio">
<websocket:sockjs />
</websocket:stomp-endpoint>
<websocket:stomp-broker-relay prefix="/topic,/queue" />
</websocket:message-broker>工作原理
STOMP 代理中继(Broker Relay)是一个特殊的 MessageHandler,它通过 TCP 连接到外部代理,充当“中转员”的角色:
- 它将客户端发来的消息转发给代理。
- 它将从代理接收到的消息转发给客户端。
TIP
你需要在项目中添加 io.projectreactor.netty:reactor-netty 和 io.netty:netty-all 依赖以实现 TCP 连接管理。
补充教学
1. 为什么需要外部代理实现集群?
当你有多个后端实例时,客户端会负载均衡到不同的机器。如果用户 A 订阅在 1 号机,用户 B 订阅在 2 号机:
- 简单代理: 你的消息发到 1 号机,用户 B 永远收不到。
- 外部代理: 1 号机把消息扔给 RabbitMQ,MQ 会广播给 2 号机,最终用户 B 成功接收。
2. 功能完整性
外部代理支持真正的 STOMP 语义,包括消息确认 (ACK)。这意味着你可以确保消息绝对被投递成功,而不只是“发出去了就不管”。
3. 系统维护性
通过外部代理,你可以监控积压的消息数、连接数以及节点健康状况,这对于生产环境排查性能瓶颈至关重要。