首页 新闻 会员 周边

Moomoo

0
[已关闭问题] 关闭于 2026-01-09 08:17

网关如何根据用户的权限,自动替用户向后端的消息服务器(Broker)发起订阅,并建立路由通道。这是后台管理系统做的事情。当管理员给“用户A”分配了“订阅TopicA”的权限后,数据通常会落库,并同步到网关。

网关拿到“绑定关系”后,需要做两件事:
1. 替用户订阅:网关作为客户端,连接到消息服务器(如 EMQX/RocketMQ),替用户A订阅 TopicA。
2. 建立管道:当消息服务器把 TopicA 的消息推给网关时,网关要把这条消息路由回给“用户A”的长连接。

角色代码中的体现作用

用户 (User)userId终端设备或前端页面,持有连接。

Topic (权限)topic  字符串消息的地址。在代码中通常作为路由键。

绑定 (Binding)gatewayLocalCache topicUserRouter内存数据结构。存储 Topic  到 User列表  的映射。

注册 (Registry)assignTopicToUser()  方法管理员通过 API 修改权限,数据进入网关内存。

订阅 (Subscribe)subscribeToBroker()  方法网关代替用户向后端消息中间件发起 SUBSCRIBE  指令。

网关 (Gateway)MqttMessageRouter流量转发。收到消息 -> 查路由表 -> 推给对应的 User 连接。

一句话概括代码逻辑:
网关首先根据本地缓存中的“用户-Topic绑定关系”,主动向后端Broker发起订阅;然后在收到消息后,根据路由表将消息转发给对应的用户长连接。 

问题补充:

1. 用户连接:用户A连接网关,网关创建一个 sessionA 对象,并存入内存(或缓存)。
2. 绑定 Topic:后台配置用户A可以订阅 /order ,网关更新 sessionA.subscribedTopics ,并替用户A向 Broker 订阅。
3. 消息到达:Broker 把 /order 的消息推给网关。
4. 查找 Session:网关遍历所有在线的 Session,看谁的 subscribedTopics 里包含 /order 。
5. 推送消息:找到 sessionA ,通过 sessionA.getChannel().writeAndFlush(message) 把消息写回给用户A。

这两个“绑定”不是同一个东西

1. 第一个绑定:用户-Topic 绑定关系
● 这是什么? 这是权限表或配置表。
● 代码里的样子: Map> 或数据库里的一张 user_topic_relation 表。
● 作用: 告诉网关:“用户A 被允许订阅 哪些 Topic”。
● 谁用它? 订阅模块用它。
● 怎么用? 网关启动或后台权限变更时,读取这个表。如果发现用户A绑定了TopicA,而网关目前还没订阅TopicA,网关就会去 Broker 那里执行 SUBSCRIBE TopicA 。
● 特点: 它是静态的(相对不变,除非管理员改权限)。

2. 第二个绑定:路由表
● 这是什么? 这是运行时状态表或反向索引表。
● 代码里的样子: Map> 或 Map> 。
● 作用: 告诉网关:“当消息到达时,应该推送给 哪些在线的连接(Session)”。
● 谁用它? 消息转发模块用它。
● 怎么用? 当网关收到 Broker 推来的消息(TopicA)时,查这个表,找到所有订阅了TopicA的在线 Session,然后遍历发送。
● 特点: 它是动态的(用户上线就加,用户下线就删,非常频繁)。

网关通常是以“网关自己”这个身份,去订阅“它所需要转发的所有 Topic”。

● 当用户A上线,请求订阅 TopicA 。
● 网关查“用户-Topic 绑定表”,确认用户A有权限。
● 网关查自己的 Set :发现没有订阅过 TopicA 。
● 动作:网关向 Broker 发送 SUBSCRIBE TopicA 。
● 网关把 TopicA 加入 Set 。
● 网关建立路由: TopicA -> SessionA 。

复用通道:
● 当用户B上线,也请求订阅 TopicA 。
● 网关查 Set :发现已经订阅过了。
● 动作:不需要再向 Broker 发送 SUBSCRIBE TopicA (发了也是重复的,浪费资源)。
● 网关只需要建立路由: TopicA -> SessionB 。

*Tesla*的主页 *Tesla* | 小虾三级 | 园豆:1374
提问于:2026-01-09 08:13
< >
分享
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册