思考个问题, Java 如何通过 websocket 和 RabbitMq 集群实现复杂聊天系统呢

2020-06-02 17:36:57 +08:00
 inktiger

网上看到的方案貌似都是用 redis 队列 /订阅或者 mq 队列来实现集群的,那么假如有 10 台服务器,使用 webscoket 和 RabbitMq 来实现集群间的消息发送,用户和连接的服务器关系保存在 redis,那么某一个用户发送消息是否就代表着群里有多少人就需要查询多少次 redis 获取到其他在线用户所在服务器依次给其他用户发送消息呢?这样是否太夸张了,消息在于实时性,单单一个用户发一条消息就要这么折腾 redis,如果多了是否就扛不住了

3572 次点击
所在节点    Java
21 条回复
Austaras
2020-06-02 18:01:26 +08:00
别问,问就是用 elixir
wellsc
2020-06-02 18:04:21 +08:00
用 Akka
guyeu
2020-06-02 18:11:34 +08:00
emmmm redis 有键空间通知和键事件通知来避免你说的这种情况。。。
inktiger
2020-06-02 18:15:21 +08:00
@guyeu 额,感觉用这个的好少
inktiger
2020-06-02 18:15:32 +08:00
@wellsc 这么冷门的东西么。。。
opengps
2020-06-02 18:15:54 +08:00
大部分人对于大型系统的理解,中间件成了必不可少,完全错了,中间件只是为了解耦合和提高吞吐!
如果你的 socket 服务端可以做到精确命中目标连接所在服务器然后转发,那么 mq 这一层显然必要性就不高了,毕竟你只有 10 台机器的压力负载
guyeu
2020-06-02 18:22:41 +08:00
@inktiger #4 这个东西有一些限制,具体用起来也不像消息队列那种订阅 /推送的模式舒服,各种客户端的支持也不见得好。但它确实能解决你提出的那个问题。
shenjixiang
2020-06-02 18:36:21 +08:00
@opengps 不用 mq 队列,那怎么保证消息先后到达的顺序呢?
shenjixiang
2020-06-02 18:39:50 +08:00
lz 提出的这个问题完全是数据结构的设计问题。。
opengps
2020-06-02 18:45:13 +08:00
@shenjixiang 你用了 mq 也仅仅是对到达服务器的顺序做了个强制排序而已。
我做过类似聊天业务,回想下业务场景,一对一私聊,0.1 秒的时差就已经足够对消息排序了。即使把并发考虑到钉钉那种 5000 人大群的规模,用微秒本身去排序也没啥大问题的,因为同一微秒的消息即使乱序,也已经不会对群消息造成直接影响了(网络因素本身就已经不能让消息不是微秒级别都准确了)
inktiger
2020-06-02 18:45:26 +08:00
@opengps 其实 mq 也有一个作用就是定位到消息推送到长连接所在用户的那一台服务器
nwljy
2020-06-02 18:55:52 +08:00
RocketMQ 自身可以支持 webscoket ( Kafka )
opengps
2020-06-02 18:56:12 +08:00
@inktiger 是的,达到业务效果怎么着都行。我最早的交换通信就是只用 memcached 全局共享存下所有公网连接信息,然后各个服务器收到消息通过 memcached 找准服务器,然后内网用短链接精准转发消息
opengps
2020-06-02 18:57:36 +08:00
@nwljy 虽然可以,但是这个功能你不会真敢用在公网吧? im 通信一定得用一套自己的通信协议来实现数据加密的
qinxi
2020-06-02 23:49:34 +08:00
每个集群节点订阅自己的 $ip_$port_quenename, 自己 redis 维护一份 用户连接所在服务器所订阅的队列名. ,需要给他发消息,就发到对应服务器的队列
tairan2006
2020-06-03 08:19:01 +08:00
直接用 mqtt 不就完了
inktiger
2020-06-03 10:19:15 +08:00
@qinxi 其实我就是这么做的,但是如果有群发的情况,当用户都分布在不同服务器的时候,你就得去挨个读取用户的所在服务器,我就在想这样会不会量大的时候读不过来
yyConstantine
2020-06-03 10:34:13 +08:00
@inktiger 简单粗暴一点直接广播消费呢?
inktiger
2020-06-03 11:24:34 +08:00
@yyConstantine 广播消费的话太浪费资源了,还是精准推送节约点
ljzxloaf
2020-06-03 15:43:23 +08:00
用户建立连接时,查看当前服务器是否已经订阅了该用户所属的所有群的 queue,没有的话去订阅;连接关闭时,就像引用计数一样,判断下哪些 queue 已经用不到了,取消订阅。

没做过,纯脑洞。感觉这样的话建立连接和关闭连接的开销也不小。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/677937

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX