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