使用redis解决用户跨服务器通信

我们在集群聊天服务器中涉及的通信是:一对一的聊天,群聊。如上图所示,client1登录在chatserver1上,client2登录在chatserver2上,client3登录在chatserver3上。
按我们现有的单台服务器业务来说,我们在每一台服务器上都有_userConMap,当client1给client2发送聊天消息的话,在chatserver1上的_userConMap肯定是找不到client2的connection。
在集群环境中,我们服务器的代码在业务逻辑上应该做修改,客户端完全不用改动,因为客户端不用去了解服务器有几台。我们要继续判断,如果当前client1所要聊的client2并不在这台chatserver1的机器上,就要去数据库找client2用户的一个在线状态,如果是offline,说明client2确实不在线,直接按照原来的逻辑发送离线消息就可以了,如果是在数据库查到client2的状态是online,是在线的,不在这台主机上的_userConMap而已,只是登录在集群的其他的服务器上,如果是这种情况,如何聊天呢?client1根本不知道client2的connection是什么。
有一种解决方式是让这几台服务器之间建立连接,即这几台服务器承担着客户端和服务端这两种角色。这样的设计使得各个服务器之间耦合度太高,不利于系统扩展,并且会占用系统大量的socket资源,各服务器之间的带宽压力很大,不能够节省资源给更多的客户端提供服务,因此绝对不是一个好的设计。
集群部署的服务器之间进行通信,最好的方式就是引入中间件消息队列,解耦各个服务器,使整个系统松耦合,提高服务器的响应能力,节省服务器的带宽资源,如下图所示:

在集群分布式环境中,经常使用的中间件消息队列有ActiveMQ、RabbitMQ、Kafka等,都是应用场景广泛并且性能很好的消息队列,供集群服务器之间,分布式服务之间进行消息通信。限于我们的项目业务类型并不是非常复杂,对并发请求量也没有太高的要求,因此我们的中间件消息队列选型的是-基于发布-订阅模式的redis。
chatserver1有用户client1登录后,要向消息队列订阅一下这个client1,如果有人向client1发送消息,那这个消息队列就给chatserver1上报一下,client1就拿到了该消息。同理,client2在chatserver2登录,那么chatserver2向消息队列订阅了client2,表示chatserver2对发送给client2的消息感兴趣。
这时候如果client1向client2发消息,一看client2没有在这台聊天服务器上,但是client2是在线的状态,说明client2在其他服务器上登录。client2所在的chatserver2肯定向消息队列订阅了client2的消息事件,client1 publish一下消息(聊天的json消息)。由于chatserver2向消息队列订阅了client2,消息队列给chatserver2 notify一下,chatserver2知道有人给client2发送消息了,就找client2通信用的connection,把这个聊天消息转发到client2上。整个过程如下图所示:

也就是说,引入了消息队列,除了消息队列是单独开发的代码模块,我们的服务器只需要向消息队列订阅发布消息。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
