七、Java NIO 深入解读--Netty高可靠性设计与Netty协议栈

Netty高可靠性设计

1.网络通信类故障

1.1 客户端连接超时

在传统的同步阻塞编程模式下,客户端Socket发起网络连接,往往需要指定连接超时时间,这样做的目的主要有两个。

  • 在同步阻塞I/O模型中,连接操作是同步阻塞的,如果不设置超时时间,客户端IO线程可能会被长时间阻塞,这会导致系统可用I/O线程数的减少。

  • 业务层需要:大多数系统都会对业务流程执行时间有限制,例如WEB交互类的响应时间要小于3S。客户端设置连接超时时间是为了实现业务层的超时。

Netty解决方案:

设置完连接超时之后,Netty在发起连接的时候,会根据超时时间创建ScheduledFuture挂载在Reactor线程上,用于定时监测是否发生连接超时。创建连接超时定时任务之后,会由NioEventLoop负责执行。如果已经连接超时,但

是服务端仍然没有返回TCP握手应答,则关闭连接。如果在超时期限内处理完成连接操作,则取消连接超时定时任务。

1.2  通信对端强制关闭连接

1.3 链路关闭

1.4  定制IO故障

2. 链路的有效性检测

当网络发生单通、连接被防火墙Hang住、长时间GC或者通信线程发生非预期异常时,会导致链路不可用且不易被及时发现。特别是异常发生在凌晨业务低谷期间,当早晨业务高峰期到来时,由于链路不可用会导致瞬间的大批量业务失败或者超时,这将对系统的可靠性产生重大的威胁。从技术层面看,要解决链路的可靠性问题,必须周期性的对链路进行有效性检测。目前最流行和通用的做法就是心跳检测。

 

不同的协议,心跳检测机制也存在差异,归纳起来主要分为两类:

  1. Ping-Pong型心跳:由通信一方定时发送Ping消息,对方接收到Ping消息之后,立即返回Pong应答消息给对方,属于请求-响应型心跳。

  2. Ping-Ping型心跳:不区分心跳请求和应答,由通信双方按照约定定时向对方发送心跳Ping消息,它属于双向心跳。

心跳检测策略如下:

  • 连续N次心跳检测都没有收到对方的Pong应答消息或者Ping请求消息,则认为链路已经发生逻辑失效,这被称作心跳超时。

  • 读取和发送心跳消息的时候如何直接发生了I0异常,说明链路已经失效,这被称为心跳失败。无论发生心跳超时还是心跳失败,都需要关闭链路,由客户端发起重连操作,保证链路能够恢复正常。

Netty提供的空闲检测机制分为三种:

1.读空闲,链路持续时间t没有读取到任何消息

2.写空闲,链路持续时间t没有发送任何消息

3.读写空闲,链路持续时间t没有接收或者发送任何消息。

3.Reactor线程的保护

4.内存保护

NIO通信的内存保护:

1.链路总数的控制:每条链路都包含接收和发送缓冲区,链路个数太多容易导致内存溢出;

2.单个缓冲区的上限控制:防止非法长度或者消息过大导致内存溢出:

3.缓冲区内存释放:防止因为缓冲区使用不当导致的内存泄露:

4.NIO消息发送队列的长度上限控制。

4.1 缓冲区的内存泄漏保护

为了提升内存的利用率,Netty提供了内存池和对象池。但是,基于缓存池实现以后需要对内存的申请和释放进行严格的管理,否则很容易导致内存泄漏。如果不采用内存池技术实现,每次对象都是以方法的局部变量形式被创建,使用完成之后,只要不再继续引用它,JVM会自动释放。但是,一旦引入内存池机制,对象的生命周期将由内存池负责管理,这通常是个全局引用,如果不显式释放JVM是不会回收这部分内存的。对于Netty的用户而言,使用者的技术水平差异很大,一些对JVM内存模型和内存泄漏机制不了解的用户,可能只记得申请内存,忘记主动释放内存,特别是JAVA程序员。为了防止因为用户遗漏导致内存泄漏,Netty在Pipeline的Tail Handler中自动对内存进行释放。

4.2 缓冲区溢出保护

Netty是如何对缓冲区进行上限保护的:

  • 在内存分配的时候指定缓冲区长度上限,其次,在对缓冲区进行写入操作的时候,如果缓冲区容量不足需要扩展,首先对最大容量进行判断,如果扩展后的容量超过上限,则拒绝扩展;

  • 在消息解码的时候,对消息长度进行判断,如果超过最大容量上限,则抛出解码异常,拒绝分配内存;

Netty协议栈

Netty协议栈用于内部各模块之间的通信,它基于TCP/IP协议栈,是一个类HTTP协议的应用层协议栈,相比于传统的标准协议栈,它更加轻巧、灵活和实用。

Netty协议栈承载了业务内部各模块之间的消息交互和服务调用,它的主要功能如下。

(1)基于Netty的NIO通信框架,提供高性能的异步通信能力:

(2)提供消息的编解码框架,可以实现POJO的序列化和反序列化

(3)提供基于IP地址的白名单接入认证机制:

(4)链路的有效性校验机制

(5)链路的断连重连机制

1.Netty通信模型:

 

(1)Netty协议栈客户端发送握手请求消息,携带节点ID等有效身份认证信息:

(2)Netty协议服务端对握手请求消息进行合法性校验,包括节点ID有效性校验、节点重复登录校验和IP地址合法性校验,校验通过后,返回登录成功的握手应答消息;

(3)链路建立成功之后,客户端发送业务消息

(4)链路成功之后,服务端发送心跳消息:

(5)链路建立成功之后,客户端发送心跳消息:

(6)链路建立成功之后,服务端发送业务消息

(7)服务端退出时,服务端关闭连接,客户端感知对方关闭连接后,被动关闭客户端连接。

2. Netty消息定义:

 Netty协议栈包括消息头和消息体。

 

3 链路的建立:

Netty协议栈支持服务端和客户端,对于使用Netty协议栈的应用程序而言,不需要刻意区分到底是客户端还是服务端,在分布式组网环境中,一个节点可能既是服务端也是客户端,这个依据具体的用户场景而定

Netty协议栈对客户端的说明如下:如果A节点需要调用B节点的服务,但是A和B之间还没有建立物理链路,则由调用方主动发起连接,此时,调用方为客户端,被调用方为服务端。考虑到安全,链路建立需要通过基于IP地址或者号段的黑白名单安全认证机制,作为样例,本协议使用基于IP地址的安全认证,如果有多个IP,通过逗号进行分割。在实

际商用项目中,安全认证机制会更加严格,例如通过密钥对用户名和密码进行安全认证。客户端与服务端链路建立成功之后,由客户端发送握手请求消息。

4.可靠性设计

Netty协议栈可能会运行在非常恶劣的网络环境中,网络超时、闪断、对方进程死或者处理缓慢等情况都有可能发生。为了保证在这些极端异常场景下Netty协议栈仍能够正常工作或者自动恢复,需要对它的可靠性进行统一规划和设计。

  1. 心跳机制

  2. 重连机制

  3. 重复登录保护

  4. 消息缓存重发

5. 可靠性设计

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值