netty 断开连接_亿级高并发IM架构的开发实践——Netty

如何支撑亿级流量的高并发IM架构的理论基础

7d8c0a47785c06d4a8b2972731f54899.png

亿级流量的系统架构的开发实践

支撑亿级流量的高并发IM通信的几大集群中,最为核心的是Netty集群、ZooKeeper集群、Redis集群, 它们是主要实现亿级流量通信功能不可缺少的集群。其次是SpringCloud WEB服务集群、MySql集群,完成海量用户的登录和存储,以及离线消息的存储。最后是RocketMQ消息队列集群,用于离线消息的保存。

主要的集群介绍如下:

(1) Netty服务集群

主要用来负责维持和客户端的TCP连接,完成消息的发送和转发。

(2) ZooKeeper集群

负贵Netty Server集群的管理,包括注册、路由、负载均衡。集群IP注册和节点ID分配。主要在基于ZooKeeper集群提供底层服务。

(3) Redis集群

负责用户、用户绑定关系、用户群组关系、用户远程会话等等数据的缓存其他的配置数据或者临时数据,加快读取速度。

(4) MySq|集群

保存用户、群组、离线消息等。

(5) RocketMQ消 息队列集群

主要是将优先级不高的操作,从高并发模式转成低并发的模式。例如,可以将离线消息发向消息队列,然后通过低并发的异步任务保存到数据库。

高并发架构的技术选型

明确了架构之后,接下来就是平台的技术选型,大致如下:

(1)核心

(2)短连接服务: spring cloud

基于RESTful短连接的分布式微服务架构,完成用户在线管理、单点登录系统。

(3)长连接服务: Netty

主要用来负责维持和客户端的TCP连接,完成消息的发送和转发。

(4)消息队列: rocketMQ高速消息队列。

(5)数据库: mysql+mongodb

mysq用来存储结构化数据,如用户数据。mongodb很重要,用来存储非结构化的离线消息。.

(6)序列化协议: Protobuf+JSON

Protobuf是最高效的二进制序列化协议,用于长连接。JSON是最紧凑的文本协议,用于短连接。

详解IM消息的序列化协议选型

IM系统的客户端和服务器节点之间,需要按照同一-种数据序列化协议进行数据的交换。简而言之:就是规定网络中的字节流数据,如何与应用程序需要的结构化数据相互转换。

序列化协议主要的工作有两部分,结构化数据到二进制数据的序列化和反序列化。序列化协议的类型:文本协议和二进制协议。

常见的文本协议包括XML和JSON。文本协议序列化之后,可读性好,便于调试,方便扩展。但文本协议的缺点在于解析效率一般,有很多的冗余数据,这一点主要体现在XML格式上。

常见的二进制协议包括Protobuf、Thift, 这些协议都自带了数据压缩,编解码效率高,同时兼具扩展性。二进制协议的优势很明显,但是劣势也非常的突出。二进制协议和文本协议相反,序列化之后的二进制协议报文数据,基本.上没有什么可读性,很显然,这点不利于大家开发和调试。

因此,在协议的选择上,给大家的建议是:对于并发度不高的IM系统,建议使用文本协议,例如JSON;对于并发度非常之高,QPS在千万级、亿级的通信系统,尽量选择二进制的协议。

详解长连接和短连接

什么是长连接呢?客户端向服务器发起连接,服务器接受客户端的连接,双方建立连接。客户端与服务器完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。

大家知道,TCP协议的连接过程是比较繁琐的,建立连接是需要三次握手的,.而释放则需要4次握手,所以说每个连接的建立都需要消耗资源和时间。在高并发的IM系统中,客户端和服务器之间,需要大量的发送通信的消息,如果每次发送消息,都去建立连接,客户端的和服务器的连接建立和断开的开销是非常巨大的。所以,IM消息的发送,肯定是需要长连接。

什么是短连接呢?客户端向服务器发起连接,服务器接受客户端连接,在三次握手之后,双方建立连接。客户端与服务器完成一次读写, 发送数据包并得到返回的结果之后,通过客户端和服务器的四次握手断开连接。

短连接适用于数据请求频度较低的应用场景。例如网站的浏览和普通的Web请求。短连接的优点是,管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段。

在高并发的IM系统中,客户端和服务器之间,除了消息的通信外,还需要用户的登录与认证、好友的更新与获取等等一些低频的请求,这些都使用短连接来实现。

综上所述,在这个高并发IM系统中,存在两类的服务器。一类短连接服务器和一个长连接服务器。

短连接服务器也叫Web服务器,主要功能是实现用户的登录鉴权和拉取好友、群组、数据档案等相对低频的请求操作。

长连接服务器也叫IM即时通信服务器,主要作用就是用来和客户端建立并维持长连接,实现消息的传递和即时的转发。并且,分布式网络非常复杂,长连接管理是重中之重,需要考虑到连接保护、连接检测、自动重连等方方面面的工作。短连接Web服务器和长连接IM服务器之间,是相互配合的。在分布式集群的环

境下,用户首先通过短连接登录Web服务器。Web服务器在完成用户的账号/密码验证,返回uid和token时,还需要通过一定 策略,获取目标IM服务器的IP地址和端口号列表,并返回给客户端。客户端开始连接IM服务器,连接成功后,发送鉴权请求,鉴权成功则授权的长连接正式建立。

如果用户规模庞大,无论是短连接Web服务器,还是长连接IM服务器,都需要进行横向的扩展,都需要扩展到上十台、百台、甚至上千台服务器。只有这样,才能有良好性能的用户体验。因此,需要引入一个新的角色,短连接Web网关( WebGate)。

WebGate短连接网关的职责,首先是代理大量的Web服务器,从而无感知的实现短连接的高并发。在客户端登录时和进行其他短连接时,不直接连接Web服务器,而是连接Web网关。围绕Web网关和Web高并发的相关技术,目前非常成熟,可以使用SpringCloud或者Dubbo等分布式Web技术,也很容易扩展。

除此之外,大量的IM服务器,又如何协同和管理呢?基于ZooKeeper或者其他的分布式协调中间件,可以非常方便、轻松地实现- -个IM服务器集群的管理,包括而且不限于命名服务、服务注册、服务发现、负载均衡等管理。

当用户登录成功的时候,WebGate短 连接网关可以通过负载均衡技术,从ZooKeeper集群中,找出一个可用的IM服务器的地址,返回给用户,让用户来建立长连接。

分布式IM的命名服务的实践案例

前面提到,一个高并发系统是由很多的节点所组成,而且节点的数量是不断动态变化的。在一个即时消息(IM)通信系统中,从0到1到N,用户量可能会越来越多,或者说由于某些活动影响,会不断地出现流量洪峰。这时需要动态加入大量的节点。另外,由于服务器或者网络的原因,- -些节点主动离开了集群。如何为大量的动态节点命名呢?最好的办法是使用分布式命名服务,按照-定的规则,为动态上线和下线的工作节点命名。

IM节点的POJO类

首先定义一个POJO类,保存IM Worker节点的基础信息如Netty服务IP、Netty服务端口,以及Netty的服务连接数。具体如下:

dc5e09183d27f56d873c924a50b1e9a3.png

这个POJO类的IP、端口、balance负载和每一个节点的Netty服务器相关。而id属性,则利用ZooKeeper中 的ZNode子节点可以顺序编号的性质,由ZooKeeper生成。

IM节点的ImWorker类

节点的命名服务的思路是,所有的工作节点都在ZooKeeper的同一个父节点下,创建顺序节点。然后从返回的临时路径上,取得属于自己的那个后缀的编号。主要的代码如下:

283e0c1acdac849148c3d4045993c7ef.png
0de9435c65954790beeb8d9e77e9a3b4.png

注意,这里有三个ZNode相关的路径:

(1) MANAGE PATH

(2) pathPrefix

(3) pathRegistered

第一个MANAGE_ PATH是- -一个常量,值为"/im/nodes",为所有Worker临时工作节点的父亲节点的路径,在创建Worker节点之前,首先要检查一下,父亲ZNode节点是否存在,否则的话,先创建父亲节点。"/im/nodes"父亲 节点的创建方式是,持久化节点,而不是临时节点。

第二路径pathPrefix是所有临时节点的前缀,值为"/im/nodes/",是在工作路径后,加上一个“”分割符。也可是在工作路径的后面,加,上“/”分割符和其他的前缀字符,如"/im/nodes/id-" 、“/im/nodes/seq-"等等。

b21ecd8fcb4632394154e4a0358a0b56.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值