Netty学习记录-初步认识Netty及I/O模型

Netty学习记录

  • Netty简介
  • Netty特征
  • Netty架构结构图
  • Netty如今使用的场景
  • IO了解
    • BIO:
      • BIO演变的NIO的过程
    • NIO:
      • NIO三大核心(重点)
      • NIO非阻塞网络编程原理分析(重点)
    • AIO:
    • 我们用一个生活中的例子来理解BIO,NIO,AIO(重点理解)

Netty简介

Netty是由JBOSS提供的一个java开源框架,现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序

也就是说,Netty 是一个基于NIO的客户、服务器端的编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发

“快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,并经过相当精心设计的项目。最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性

Netty特征

设计

各种传输类型的统一 API - 阻塞和非阻塞套接字
基于灵活且可扩展的事件模型,允许清晰的关注点分离
高度可定制的线程模型——单线程、一个或多个线程池,如 SEDA
真正的无连接数据报套接字支持(自 3.1 起)

使用方便

有据可查的 Javadoc、用户指南和示例
没有额外的依赖,JDK 5 (Netty 3.x) 或 6 (Netty 4.x) 就足够了
    注意:某些组件(例如 HTTP/2)可能有更多要求。 请参阅 要求页面 想要查询更多的信息。

表现

更高的吞吐量,更低的延迟
更少的资源消耗
最小化不必要的内存复制

安全

完整的 SSL/TLS 和 StartTLS 支持

社区

早发布,经常发布
作者自 2003 年以来一直在编写类似的框架,他仍然认为您的反馈很宝贵!

Netty架构结构图

Netty学习记录-初步认识Netty及I/O模型_第1张图片

上面是对于netty的官方介绍,网络上面经常看到有人说过这句话,不学netty就相当于刚入java的入门,会一些curd操作,还没有真正的了解java。那么作为小白的我肯定要学习一下了!


    首先我们需要了解为什么学习Netty(通过官方介绍相信对Netty有了一定的初步了解),然后再思考Netty可以用在那些地方,如何使用?带着这一系列问题,我们开始研究一下。


Netty如今使用的场景

  • 互联网行业:随着网站规模的不断扩大,系统并发访问量也越来越高,传统基于 Tomcat 等 Web 容器的垂直架构已经无法满足需求,需要拆分应用进行服务化,以提高开发和维护效率。从垂直的架构拆分之后,系统采用分布式部署,各个节点之间需要远程服务调用,高性能的 RPC 框架必不可少,Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些 RPC 框架使用。

    典型的应用有:阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用 Netty 作为基础通信组件,用于实现各进程节点之间的内部通信。它的架构图如下:

Netty学习记录-初步认识Netty及I/O模型_第2张图片
    其中,服务提供者和服务消费者之间,服务提供者、服务消费者和性能统计节点之间使用 Netty 进行异步/同步通信。  
     除了 Dubbo 之外,淘宝的消息中间件 RocketMQ 的消息生产者和消息消费者之间,也采用 Netty 进行高性能、异步通信。  
     除了阿里系和淘宝系之外,很多其它的大型互联网公司或者电商内部也已经大量使用 Netty 构建高性能、分布式的网络服务器。

  • 游戏行业:无论是手游服务端、还是大型的网络游戏,Java 语言得到了越来越广泛的应用。Netty 作为高性能的基础通信组件,它本身提供了 TCP/UDP 和 HTTP 协议栈,非常方便定制和开发私有协议栈。账号登陆服务器、地图服务器之间可以方便的通过 Netty 进行高性能的通信,架构示意图如下:
    Netty学习记录-初步认识Netty及I/O模型_第3张图片

  • 大数据领域:经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨节点通信,它的 Netty Service 基于 Netty 框架二次封装实现。  
        大数据计算往往采用多个计算节点和一个/N个汇总节点进行分布式部署,各节点之间存在海量的数据交换。由于 Netty 的综合性能是目前各个成熟 NIO 框架中最高的,因此,往往会被选中用作大数据各节点间的通信。

  • 企业软件:企业和 IT 集成需要 ESB,Netty 对多协议支持、私有协议定制的简洁性和高性能是 ESB RPC 框架的首选通信组件。事实上,很多企业总线厂商会选择 Netty 作为基础通信组件,用于企业的 IT 集成。

  • 通信行业:Netty 的异步高性能、高可靠性和高成熟度的优点,使它在通信行业得到了大量的应用。

IO了解

IO模型:解决的是用什么模样的通道进行数据发送和接收,这很大程度上决定了通讯的效率。

利用程序通讯为例,我们简单的了解,当“A”向"B" 发送一条消息的流程:
第一步:应用A把消息发送到 TCP发送缓冲区。
第二步: TCP发送缓冲区再把消息发送出去,经过网络传递后,消息会发送到B服务器的TCP接收缓冲区。
第三步:B再从TCP接收缓冲区去读取属于自己的数据。

图解:
Netty学习记录-初步认识Netty及I/O模型_第4张图片

BIO:

同步并阻塞IO模型,传统的 java.io 包,它是基于流模型实现的,交互的方式是同步、阻塞方式,也就是说在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调用时可靠的线性顺序。它的有点就是代码比较简单、直观;缺点就是 IO 的效率和扩展性很低,容易成为应用性能瓶颈。

我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要对每个请求建立一堆线程等待请求,而客户端发送请求后,先咨询服务端是否有线程响应,如果没有则会一直等待或者遭到拒绝请求,如果有的话,客户端线程会等待请求结束后才继续执行。

适用于连接少固定的架构,程序简单。

BIO演变的NIO的过程

Bio是一个阻塞式的io,不能够支持并发请求访问;可以多线程优化代码

这种方式也存在缺点:如果每个请求过来都使用一个线程,这时候非常浪费CPU的资源。

所以在网络编程服务器中,是否使用单线程提高响应的效率问题,所以nio出现。

NIO:

NIO 同步非阻塞IO 是 Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层高性能的数据操作方式。

NIO本身是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题: 在使用同步I/O的网络应用中,如果要同时处理多个客户端请求,或是在客户端要同时和多个服务器进行通讯,就必须使用多线程来处理。也就是说,将每一个客户端请求分配给一个线程来单独处理。这样做虽然可以达到我们的要求,但同时又会带来另外一个问题。由于每创建一个线程,就要为这个线程分配一定的内存空间(也叫工作存储器),而且操作系统本身对线程的总数也有一定的限制。如果客户端的请求过多,服务端程序可能会因为不堪重负而拒绝客户端的请求,甚至服务器可能会因此而瘫痪。
NIO基于Reactor,当socket有流可读或可写入socket时,操作系统会相应的通知应用程序进行处理,应用再将流读取到缓冲区或写入操作系统。 也就是说,这个时候,已经不是一个连接就要对应一个处理线程了,而是有效的请求,对应一个线程,当连接没有数据时,是没有工作线程来处理的。

Netty学习记录-初步认识Netty及I/O模型_第5张图片
适用于连接多并连接比较短,例如聊天系统等。

BIO与NIO一个比较重要的不同,是我们使用BIO的时候往往会引入多线程,每个连接一个单独的线程;而NIO则是使用单线程或者只使用少量的多线程,多个连接共用一个线程。BIO以流(基于字符字节流)方式处理数据,NIO以块(通道和缓存区)方式,面向缓存区。

NIO三大核心(重点)

Channel-通道
首先说一下Channel,国内大多翻译成“通道”。Channel和IO中的Stream(流)是差不多一个等级的。BIO中的Stream是单向的,只能读或者写,譬如:InputStream, OutputStream。而Channel是双向的,既可以用来进行读操作,又可以用来进行写操作,NIO中的Channel的主要实现有:FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel;通过看名字就可以猜出个所以然来:分别可以对应文件IO、UDP和TCP(Server和Client)。

Buffer-缓存区
NIO中的关键Buffer实现有:ByteBuffer、CharBuffer、DoubleBuffer、 FloatBuffer、IntBuffer、 LongBuffer,、ShortBuffer,分别对应基本数据类型: byte、char、double、 float、int、 long、 short。实质是内存块,底层是数组实现。

Selector-选择器
Selector 是NIO相对于BIO实现多路复用的基础,Selector 运行单线程处理多个 Channel,多个channel以事件的方式注册到selector中,如果你的应用打开了多个通道,但每个连接的流量都很低,使用 Selector 就会很方便。例如在一个聊天服务器中。要使用 Selector , 得向 Selector 注册 Channel,然后调用它的 select() 方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新的连接进来、数据接收等。

NIO非阻塞网络编程原理分析(重点)

1.当客户端连接时,会通过ServerSocketChannel得到SocketChannel。
2.将多个SocketChannel注册到Selector上,利用register(Selector,int)。
3.注册后返回一个selectionKey,会和该selector绑定关联。
4.selecto进行监听用select()方法,返回有事件方式的通道的个数。
5.进一步得到各个(有事件发生的)selectionKey。通过selectionKey反向获取socketChannel,通过方法channel()。
6.通过channel完成业务处理。

AIO:

异步非阻塞IO,是 Java 1.7 之后引入的包,是 NIO 的升级版本,提供了异步非堵塞的 IO 操作方式,所以人们叫它 AIO(Asynchronous IO),异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

当进行读写操作时,只须直接调用API的read或write方法即可。这两种方法均为异步的,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。 即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。

特点

  • 读完了再通知我
  • 不会加快IO,只是在读完后进行通知
  • 使用回调函数,进行业务处理

适用于连接多并连接长(重操作)的架构,充分调用OS参与并发,相册系统等。

我们用一个生活中的例子来理解BIO,NIO,AIO(重点理解)

BIO:假设一个水壶在烧水,而你需要在旁边一直等待水烧开,如果水不烧开,你不能去干别的事。

NIO:又是这个水壶在烧水,你不需要一直盯着水烧开,你可以去忙别的事,但是需要隔一段时间过来看一下水烧开没。

AIO:再次是这个水壶烧水,但是这是个高级水壶,你不需要盯着它也不需要中途来查看水烧开了没,这个水壶烧开后会有提示,这样你可以在烧水的时候去干其他任何事。

补充…

参考文献1

参考文献2

你可能感兴趣的:(netty,网络,分布式,java,netty)