Skip to content

外部代理

简单代理虽然易于起步,但由于功能受限且不支持集群,无法满足严肃的生产环境需求。作为替代方案,你可以将应用程序升级为使用全功能的消息代理(Message Broker)。

请参阅你选择的消息代理(如 RabbitMQActiveMQ 等)的 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-nettyio.netty:netty-all 依赖以实现 TCP 连接管理。


补充教学

1. 为什么需要外部代理实现集群?

当你有多个后端实例时,客户端会负载均衡到不同的机器。如果用户 A 订阅在 1 号机,用户 B 订阅在 2 号机:

  • 简单代理: 你的消息发到 1 号机,用户 B 永远收不到。
  • 外部代理: 1 号机把消息扔给 RabbitMQ,MQ 会广播给 2 号机,最终用户 B 成功接收。

2. 功能完整性

外部代理支持真正的 STOMP 语义,包括消息确认 (ACK)。这意味着你可以确保消息绝对被投递成功,而不只是“发出去了就不管”。

3. 系统维护性

通过外部代理,你可以监控积压的消息数、连接数以及节点健康状况,这对于生产环境排查性能瓶颈至关重要。

Based on Spring Framework.