mina —— 分布式集群下长连接session共享的解决方案

来源:互联网 发布:大学生兼职知乎 编辑:程序博客网 时间:2024/06/05 22:35


1. 首先确定的、无法解决的方案:

将IoSession存入redis

原因:

        1)无法将IoSession保存到redis中,原因IoSession是无法被序列化的。

2)即使将IoSession保存到了redis中并且取出了对应的长连接的session,此时依然无法给客户端发送消息。举个例子就容易理解了:现在有客服A、客服B、客户C,假设客服A在与客户C通话(相当于A与C建立了长连接),客服B想反馈信息给C,然而C与客服B并不在一个回话里,所以C是无法与B通信的,因为B与C之间根本就没有建立连接

所以一台服务器拿到了其他服务器的session是无法与目标主机通信的,因为该服务器与目标主机知己根本就没有建议长连接。

从上述例子可以确定以下两点:

1)获取到别人的session是无法与目标通信的

2)能与目标主机通信的服务器只能是与目标主机建立了长连接的服务器(若想与客户C通信就只能通过A给客户C发信息,客服B是没有办法给客户C发信息的!)


2. 找到问题关键,抓主要矛盾。。。

从以上的分析可以得出以下结论:

1)若想知道是谁在和C通信,必须建立C与A的对应关系 → 必须建立服务器与目标主机之间的对应关系,并且每台服务器都可以取到该映射关系

2)若想与C通信,那么必须通过A  → 服务器之间必须存在一个接口用来通知目标服务器发送消息

当然一定确定是:3)session必须保存

【 其实就是给目标主机C发消息的步骤:知道谁在和C通话,告诉那个人(B)给C发消息, B给C发消息 】

所以解决问题的关键就是实现上述三个条件!


3. 寻求可行的解决方案

1)假设我们先不考虑分布式集群,而是采用单服务器来实现长连接,我们很让容易想到将session保存到静态的Map中,用的时候在取出对应的session,这其实已经实现了session的保存,只不过是保存在本地的内存(Map)中的。

2)那么我们再将问题扩展到分布式集群的情况下,我们要做的就是建立目标主机与目标服务器的映射关系(也就是要让其他人知道哪个客服在和哪个客户通话),而且该映射关系必须保存在公共区域才能被共享。这就简单了,建立映射关系,最简单方案就是键值对,key目标主机ID或者用户IDvalue目标服务器IP(内网IP或公网IP依现实情况而定,只要其他服务器可以通过该ip与其通话即可)。共享映射关系:将该键值对保存到数据库或缓存都行,正常会保存到缓存中,这样效率更高

3)编写一个接口用来通知目标服务器发送消息(可以用http请求代替),同时服务器还需要一个接口来处理该通知来调起session发送消息给目标主机


由此可以得出解决方案:通过Msp保存session,将客户端与服务器的映射关系保存到缓存中

那么发消息的步骤为:根据客户端的唯一标识到缓存中查出与其建立长连接的服务器,通知该服务器发送消息给目标客户端发消息,该服务器从Map中获取到与目标客户端的session,通过该session给目标客户端发送消息

1 0
原创粉丝点击