网络(六)——netty


原则上NIO的出现,已经提升和加快了网络IO的处理方式,但它只能帮忙我们解决了IO层次的读写问题,在软件层次上我们需要更好的编程架构模型,来解决扩展性以及高并发的问题。Netty正是用来解决这些问题的,这一篇我们将详细介绍Netty的知识点;

一、netty是什么

1、是什么

我们采用官方的话来说:

  • Netty是一个高性能、异步事件驱动的网络应用框架。 基于Netty,可以快速的开发和部署高性能、 高可用的网络服务端和客户端应用。

简单来说,它是一个网络应用框架,帮你解决面向网络开发中的三个问题:

  • 面向网络IO的读写,如TCP的socket连接
  • 应用层协议编解码,如HTTP协议
  • 高并发架构

那么他有哪些优点?

  • 性能强悍,高并发,低延迟;
  • 高扩展,API使用简单,开发门槛低;
  • 无阻塞,支持NIO;

在这里插入图片描述

2、有何不同

对于我们用惯了web容器的人来说,第一个疑惑就是netty究竟能干什么,为何要用它。既然Netty是一个网络应用框架,这些明明tomcat也能帮我们解决了,为何还要用Netty?

netty和tomcat的不同,主要在以下几点:

  • tomcat是一个「HTTP Server」,更准确的说是一个「Servlet/JSP」应用的容器,它主要解决的是 HTTP 协议层面的传输和访问。
  • HTTP是一种应用层协议,应用层的协议除了HTTP以外,还有面向邮局协议的POP和IMAP,以及FTP、LDAP、SSH、TLS/SSL等其他协议。
  • Netty 不仅可以支持HTTP,还可以支持FTP、LDAP、SSH、TLS/SSL等应用层多数的协议,另外还支持自定义的应用层协议,只要你有这方面的需求,它足够灵活。
  • Netty 虽然按归类上算属于OSI的第七层【应用层】,但它的存在是帮你支持第三层【传输层】的问题,比如面向TCP,面向UDP,以及SCTP网络协议的开发,它都能很好的支持。所以他可以称为一个通信组件。
  • 原则上,Tomcat的网络通信组件也可以采用Netty,但servlet3.0之前完全是同步阻塞模型,tomcat要遵循servlet规范所以不能最大发挥NIO的特性,而Netty不用遵循servlet规范,可以最大化发挥NIO的特性,性能更高一些。

二、为何要用Netty

Selector BUG:
在NIO中,若Selector的轮询结果为空,也没有wakeup或新消息处理,则发生空轮询,CPU使用率100%,Netty的解决办法:对Selector的select操作周期进行统计,每完成一次空的select操作进行一次计数, 若在某个周期内连续发生N次空轮询,则触发了epoll死循环bug。重建Selector,判断是否是其他线程发起的重建请求,若不是则将原SocketChannel从旧的Selector上去除注册,重新注册到新的Selector上,并将原来的Selector关闭。

Netty的三大特性(fast,easy,no-blocking)可以详细分解为以下特性:

  • 支持NIO,异步编程;
  • 性能强悍,高并发,低延迟,更少的资源占用和内存使用率带来更快的性能支撑,NIO领域最强
  • 成熟、稳定,你想到的一切tcp 问题,都已经解决,特别是NIO bug,以及完美解决了。
  • 不仅仅支持http,支持多种应用协议和网络协议,如TCP/UDP/UDT/SCTP/FTP/SMTP等。
  • 功能强大,预制了多种编解码处理器,支持多种主流应用协议
  • API使用简单,开发门槛低

1、快

Netty正是基于NIO实现了这种Reactor模型,Boss线程用来专门处理连接的建立,SubReactor专门用来处理IO的读写以及任务的处理。这种线程模型在充分利用CPU性能的情况下支撑大量的并发连接。

Reactor参考;

在这里插入图片描述
在这里插入图片描述

2、更少的内存使用

Netty因为要面对大量的网络数据包处理,所以会有大量的网络对象创建和销毁,对JVM来说有很大的压力。

Netty主要采用两种方案来缓解JVM的压力:

  • ByteBufAllocator 对象池。池化ByteBuf实例以提高性能并最小化内存碎片,后者每次调用时都返回一个新的实例。
  • 零拷贝。支持DirectBuffer的使用,通过JVM的本地调用分配内存,这可避免每次调用本地I / O操作之前(或之后)将缓冲区的内容复制到(或从)中间缓冲区。

3、快速开发

我们知道牵扯到网络上的编程会比较复杂,除了有一堆需要设置的TCP参数以外,还有一堆IO读写的问题要处理,同时为了提高并发能力,还采用多线程,这就又带来了线程安全的问题,往往给开发者带来了很大的挑战和复杂度。

而Netty 正是针对这些难点统一做了简易化的封装,除了让API更加简单易用以外,比如:TCP服务器的配置启动,数据包buffByte的读写等。另外基于事件模式,对网络事件进行串行处理,在保证了高效的同时,又降低了编程的复杂度。

为何串行化执行会提升netty的性能:

  • 串行无锁化设计,在IO线程内部进行串行操作,避免多线程竞争导致的性能下降;
  • 通过调整NIO线程池的线程参数,可以同时启动多个串行化的线程并行运行,这种局部无锁化的串行线程设计相比一个队列-多个工作线程模型性能更优;
  • 减少上下文切换,以及状态数据的同步;

以下 是ChannelPipeline用来处理网络事件的职责链,负责管理和执行ChannelHandler。网络事件以事件流的形式在ChannelPipeline中流转。支持插拔模式,扩展性也很强。
在这里插入图片描述

4、可靠稳定

在网络方面,应用常常要面对复杂的网络环境,比如网络环境差,常会出现一些网络闪断,单通以及网络阻塞等等一系列问题。另外作为基础的通信组件,还需要考虑健壮性的问题,因为一旦出现bug,则会导致依赖的大量业务中断。

Netty 在版本迭代中不断的加入一些可靠性特性来满足用户日益高涨的可靠性与健壮性需求。比如NIO的select空转bug,比如TCP的断线重连,keep-alive检测等问题,Netty已经帮你解决了。

特别是Netty在推出4.0之后,已经被各家大厂采纳为通信组件,这是对其可靠性验证,也是社区对其稳定性的认可。

5、0拷贝

在这里插入图片描述

三、如何用

上面介绍了这么多Netty如何厉害,到编码阶段不会出现一堆代码来要处理吧。

代码参考:
基于Netty实现的客户端和服务端
基于Netty实现的简单聊天室系统

通过代码,我们大概需要通过7个步骤,就能创建一个TCP的Server服务器了,看似7步较多,其实看代码量来说,已经很少了。
在这里插入图片描述
通过以上的执行流程图,我们可以看到:

  • ServerBootstrap是服务启动(引导)辅助类,采用无参构造器(Builder模式)提供一系统方法用于设置启动相关的参数;
  • EventLoopGroup:Netty的Reactor线程池,负责维护一组EventLoop的调度工作,通常是bossEventLoop用来维护连接,subEventLoop来维护所有已注册的Channel的I/O操作处理用户自定义的Task和定时任务的Task;
  • Channel:对Java原生的NIO类库进行了封装对一般用户而言,不需要关心底层实现细节和工作原理,只需要指定具体使用哪种Channel,用以连接IO设备(socket)的纽带,提供与IO设备异步I/O操作的支持(如读、写、连接和绑定);
  • ChildChannelHandler,用来配置ChannelPipeline的执行策略。用来扩展的关键接口,用户可以完成大多数的功能定制,如消息编解码、心跳、安全认证、TSL/SSL认证、流量控制等;

四、源码

主要看这两篇文章:
Netty 源码解析 ——— 服务端启动流程 (上)
Netty 源码解析 ——— 服务端启动流程 (下)

其他拓展:
Netty 源码解析 ——— ChannelConfig 和 Attribute
Netty 源码解析 ——— AdaptiveRecvByteBufAllocator
Netty 源码解析 ——— 基于 NIO 网络传输模式的 OP_ACCEPT、OP_CONNECT、OP_READ、OP_WRITE 事件处理流程
Netty 源码解析 ——— NioEventLoop 详解
Netty 源码解析 ——— Netty 优雅关闭流程
Netty 源码解析 ——— writeAndFlush流程分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值