Netty TCP方式的集群方案

1、现状

IM服务端在web服务的一个线程下启动,客户端通过tcp连接到服务端后,需要发送认证信息(否则一段时间后,连接关闭),连接认证通过之后,将用户id和连接的context存储到服务端的一个ConcurrentHashMap中。当服务端需要中转消息时,从这个缓存中取,如果消息路由的目标用户在线,路由消息(必须由服务端保证送达的消息在发送失败存离线)。

2、需求

高可用,负载均衡,扩展性:IM项目需要适应业务增长能够快速扩充,客户端登录之后能够选取负载较小的服务进行连接。

很多的用户连接的服务端不是同一个服务,那么他们之间的通信可能需要跨服务进行。

3、技术方案

高可用:zookeeper(集群),服务启动时在zookeeper的一个持久节点下创建临时顺序节点,服务尽量保持一般偏低负载(防止某一台tcp服务器挂掉之后,客户端连接其他的服务导致其他的服务挂掉,引起雪崩)。

负载均衡:web服务提供接口,返回当前负载最小的ip,端口。客户端连接时,拿到这个ip:port之后再做连接。

具体:1、从redis中取所有服务的连接数  2、从zookeeper中取得存活的服务,遍历,获取负载最小的服务。 

用户认证后,在Redis存储用户所在的服务名(zookeeper中创建的节点名),数据类型:Hash,Key: rout_table, HashKey:userId, Value: 服务地址ip:port。存储服务的负载,数据类型,Hash, Key:client_connect_count,HashKey:服务名, Value: 连接数,认证通过时自增,连接断开时自减, 当zookeeper节点变化时根据当前存货节点,删除失效的HashKey。

发消息流程,客户端A通过http接口给B发送IM消息,服务端验证消息正确之后,将消息存入RabbitMQ,返回发送成功。

web服务迟早要和tcp服务分开。

服务端的MQ消费线程,获取的消息,根据路由的目标userId,先查看是否在本服务。如果是,发送消息,发送失败根据情况存离线;否则从redis中取B所在的服务地址,如果B没有,根据情况存离线,否则发送(Http,改为RPC更高效)到目标服务,由目标服务处理(localHandler)(B在线发送,否则根据情况存离线)。

 

 

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值