Skip to content

消息流 ​

一旦暴露了 STOMP 端点,Spring 应用程序就会成为已连接客户端的 STOMP 代理。本节描述服务器端的消息流。

spring-messaging 模块包含了对消息传递应用程序的基础支持。以下是几个核心抽象:

  • Message: 消息的简单表示,包括标头 (Headers) 和负载 (Payload)。
  • MessageHandler: 处理消息的契约。
  • MessageChannel: 发送消息的契约,实现生产者和消费者之间的解耦。
  • SubscribableChannel: 带有 MessageHandler 订阅者的 MessageChannel。
  • ExecutorSubscribableChannel: 使用 Executor 交付消息的 SubscribableChannel。

频道 (Channels) 与流程 ​

无论通过 Java 配置还是 XML 配置,Spring 都会组装一个消息工作流。以下是启用简单内置消息代理(Simple Broker)时的组件示意:

消息流简单代理

图中包含三个核心消息频道:

  1. clientInboundChannel: 接收从 WebSocket 客户端发来的消息。
  2. clientOutboundChannel: 向 WebSocket 客户端发送服务器消息。
  3. brokerChannel: 用于从服务器端应用程序代码内部向消息代理发送消息。

当使用外部代理(如 RabbitMQ)时,流程如下:

消息流外部代理

主要的区别在于使用了“代理中继”(Broker Relay),它通过 TCP 将消息传递给外部 STOMP 代理,并将来自代理的消息传递给已订阅的客户端。

典型流程轨迹 ​

  1. 接收消息: 从 WebSocket 连接接收到的消息被解码为 STOMP 帧,转为 Spring Message 表示,发送到 clientInboundChannel。
  2. 路由方法: 目的地以 /app 开头的 STOMP 消息被路由到 @MessageMapping 控制器方法。
  3. 路由代理: 目的地以 /topic 或 /queue 开头的消息直接路由到消息代理。
  4. 返回结果: 控制器方法返回的值变为 Message 发送到 brokerChannel,代理再通过 clientOutboundChannel 广播给匹配的订阅者。

补充教学 ​

1. 这种架构的意义:解耦 ​

Spring 将 WebSocket 原始连接与业务处理完全解耦。你的 Controller 处理的是标准的 Message 对象,并不需要知道它是从哪个物理连接、哪个 TCP 端口过来的。这种抽象使得同样的逻辑也可以应用于非 WebSocket 环境。

2. 拦截器 (Interceptors) ​

由于一切都流经 MessageChannel,你可以在这些频道上注册 ChannelInterceptor。例如,在 clientInboundChannel 上加一个拦截器,就可以在消息到达 Controller 之前进行统一的权限控制或日志记录。

3. 多线程处理 ​

ExecutorSubscribableChannel 意味着消息的处理是异步的。Spring 默认配置了线程池来处理这些频道,这意味着高并发下的消息发送不会阻塞 Servlet 容器的主线程。

Based on Spring Framework.