连接到代理
STOMP 代理中继(Broker Relay)需要与外部消息代理建立 TCP 连接。本节介绍相关的连接配置。
系统连接 vs 客户端连接
代理中继共维护两类连接:
- 系统级连接: 只有一条。用于服务器端应用发送广播消息。
systemLogin和systemPasscode: 默认为guest/guest。
- 客户端连接: 代理中继会为每个已连接的 WebSocket 客户端创建一个对应的 TCP 连接。
clientLogin和clientPasscode: 默认为guest/guest。
TIP
代理中转员会代为设置 CONNECT 帧的标头,因此WebSocket 客户端不需要在前端设置用户名和密码,它们会被忽略。建议在 HTTP 握手阶段通过 Spring Security 进行身份验证。
心跳与重连
代理中继在“系统级连接”上发送和接收心跳(默认为 10 秒)。如果连接丢失,它会每隔 5 秒尝试重新连接,直到成功为止。
配置多地址 (多机高可用)
你可以配置一个地址供应器,而不是固定的单机地址:
java
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableStompBrokerRelay("/queue/", "/topic/")
.setTcpClient(createTcpClient());
}
private ReactorNettyTcpClient<byte[]> createTcpClient() {
return new ReactorNettyTcpClient<>(
client -> client.remoteAddress(() -> new InetSocketAddress(0)), // 此处可配置负载均衡逻辑
new StompReactorNettyCodec());
}kotlin
override fun configureMessageBroker(registry: MessageBrokerRegistry) {
registry.enableStompBrokerRelay("/queue/", "/topic/")
.setTcpClient(createTcpClient())
}
private fun createTcpClient(): ReactorNettyTcpClient<ByteArray> {
return ReactorNettyTcpClient({ it.addressSupplier { InetSocketAddress(0) } }, StompReactorNettyCodec())
}补充教学
1. 为什么有两套账号?
- 客户端账号: 权限通常受到限制,只能订阅和发送特定目的地。
- 系统账号: 往往拥有管理员权限,可以给任何目的地发通知。 在 RabbitMQ 中,你通常会为应用专门创建一个名为
stomp_user的账号并分配 VHost 权限。
2. 用户身份识别
由于代理中继会为每个 WebSocket 客户端“开后门”去连接 MQ,如果你需要 MQ 的插件也能看到具体用户信息,可以考虑实现 StompHeaderAccessor 的动态登录逻辑,但在绝大多数场景下,使用默认的 guest 账号并通过应用层做拦截已经足够。
3. 可用性监听
你可以实现 ApplicationListener<BrokerAvailabilityEvent>。当 MQ 挂掉时,你的系统连接会断开,此时你可以通过这个事件关掉一些不必要的推送逻辑,避免连接池积压。