Skip to content

Latest commit

 

History

History
70 lines (42 loc) · 5.23 KB

集群思路.md

File metadata and controls

70 lines (42 loc) · 5.23 KB

很多时候,现实几百用户量的老板,可能阻止不了他千万用户量的心。。。。

当用户量少的时候:我们只需要一台NettyServer节点便可以扛住流量,所有的Client链接到同一个NettyServer上,并在NettyServer的SessionMap中保存每个Client的会话。 Client1与Client2通信时,Client1把消息发给NettyServer,NettyServer从SessionMap中取出Client2的Session和Channel,将消息发给Client2。
随着用户量不断增多:一台NettyServer不够,我们增加了几台NettyServer,这时Client1链接到NettyServer1上并在SessionMap和Redis中保存了会话和Client1的链接信息, Client2链接到NettyServer2上并在SessionMap和Redis中保存了会话和Client2的链接信息。Client1给Client2发消息时,通过NettyServer1的SessionMap找不到Client2的会话, 消息无法发送,于是便从Redis中获取Client2链接在哪台NettyServer上。获取到Client2所链接的NettyServer信息后,我们可以把消息转发给NettyServer2, NettyServer2收到消息后,从NettyServer2的SessionMap中获取Client2的Session和Channel,然后将消息发送给Client2。

那么:NettyServer1的消息如何转发给NettyServer2呢?

答案是通过消息队列

客户端的负载方式

image.png


NettyServer启动,每启动一台Server节点,都会把自身的节点信息,如:ip、port等信息注册到ZK上(临时节点)。

正如上节架构图上启动了两台NettyServer,所以ZK上会保存两个Server的信息。

同时ZK将监听每台Server节点,如果Server宕机ZK就会删除当前机器所注册的信息(把临时节点删除),这样就完成了简单的服务注册的功能。

Client启动时,会先从ZK上随机选择一个可用的NettyServer,拿到NettyServer的信息(IP和port)后与NettyServer建立链接。

链接建立起来后,NettyServer端会生成一个Session(即会话),用来把当前客户端的Channel等信息组装成一个Session对象,保存在一个SessionMap里,同时也会把这个Session保存在Redis中。

服务端的负载方式

image.png
客户端不负责轮询和负载,交给反向代理
由(

)作为反向代理的方式进行
而server服务,通过第三方组件进行广播,从而达到NettyServer1消息转发到NettyServer2服务中

改进一下

不基于第三方进行广播,我们用Jgroups进行(JGroups是一个开源的纯java编写的可靠的群组通讯工具。其是一个可靠的组播通讯工具集)
JGroups 适合使用场合
服务器集群cluster、多服务器通讯、服务器replication(复制)等,分布式cache缓存
EhCache,Memcached等都是通过JGroups进行的同步,集群
jgroups作为广播通信工具
相比

  • Redis 适配器依赖于 Redis Pub/Sub 机制

  • MongoDB 适配器依赖于 MongoDB 的变更流 (因此需要副本集或分片集群)。

  • Postgres 适配器依赖于NOTIFYLISTEN 命令。

以上的方式,原理上是一致的,都是将消息广播到其他服务.

image.png

关于Tia

我们选取服务端的负载方式结合Jgroups进行集群广播,也欢迎大家实现其他方式

补充阅读

以上文档可以适用于大部分长连接项目,但对于socketio,还有一些注意点
socketio官方文档把问题将的比较清晰了:
https://socket.io/zh-CN/docs/v4/using-multiple-nodes/