Netty入门

 

什么是Netty?

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

Netty和Tomcat有什么区别?

Netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,他实质是一个基于http协议的web容器。但是Netty可以通过编程自定义各种协议,因为Netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和tomcat最大的不同。

 Netty为什么高并发

Netty是基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,对比于BIO(Blocking I/O,阻塞IO),他的并发性能得到了很大提高。这里可以用两张图来了解他们之间的区别。

阻塞IO的通信方式
非阻塞IO
的通信方式

 

从图片可以看出NIO的单线程处理的连接数量要比BIO要多的多。而为什么NIO的单线程能处理更多的连接呢?因为图二中的selector。

当一个连接建立之后,他会遵循两步,第一部是接收客户端发送过来的完全数据,第二步是服务器处理完请求业务后返回response给客户端。而NIO和BIO的区别主要在于第一步。

在BIO中,等待客户端发送数据这一步骤是阻塞的,这样就造成了一个线程只能处理一个请求,而机器能支持的最大线程量是有限的,所以这就是BIO并不支持高并发的原因。

而NIO中,当一个Socket建立好之后,Thread并不会阻塞去接受一个Socket,而是将这个请求交给selector,selector会不断去遍历所有的Socket,一旦有一个Scoket建立完成,他会通知Thread,然后Thread处理完数据后再返回给客户端——这个过程是不阻塞的,这样能让一个Thread处理多个请求。

其实给我感觉就是BIO像是买东西排队一样,你没到店员面前无法买东西,一直要站着等。而NIO像是现在的手机下单一样,我们可以很多个人一起下单,然后我们就可以去干其他事情了。

下面是两张图基于BIO的处理流程和NIO的处理流程:

BIO的处理流程

 

NIO的处理流程

除了BIO和NIO之外还有很多IO模型。下面是常见的5种模型处理流程:

常见的5种IO模型
  • BIO,同步阻塞IO,阻塞整个步骤,如果连接少,他的延迟是最低的,因为一个线程只处理一个连接,适用于少连接且延迟低的场景,比如说数据库连接。
  • NIO,同步非阻塞IO,阻塞业务处理但不阻塞数据接收,适用于高并发且处理简单的场景,比如聊天软件。
  • 多路复用IO,他的两个步骤处理是分开的,也就是说,一个连接可能他的数据接收是线程a完成的,数据处理是线程b完成的,他比BIO能处理更多请求。
  • 信号驱动IO,这种IO模型主要用在嵌入式开发。
  • 异步IO,他的数据请求和数据处理都是异步的,数据请求一次返回一次,适用于长连接的业务场景。

 

以上摘自Linux IO模式及 select、poll、epoll详解

Netty为什么传输快?

Netty传输快其实就是依赖了NIO的一个特性——零拷贝。我们都知道java的内存有堆内存、栈内存和字符串常量池等等。其中堆内存是占用空间最大的一块,也就是java存储对象的地方。一般我们的数据如果需要从IO读取到堆内存,中间需要经过Socket缓冲区,也就是说,一个数据在读取中会被拷贝两次才能到达终点。如果数据量过大的话会造成不必要的资源浪费。

而Netty针对这种情况,使用了NIO中的零拷贝,当他需要接收数据的时候,他会在堆内存之外开辟一个新的内存,数据就是直接从IO读到这块的内存中,然后Netty会通过ByteBuf可以对数据进行直接操作,从而加快了他的传输速度。

下两图就介绍了两种拷贝方式的区别,摘自Linux 中的零拷贝技术,第 1 部分

传统数据拷贝

 

零拷贝

传统传输需要经过Socket缓冲区而他会对数据进行备份,而零拷贝则是不经过Socket缓存区,直接将数据传输到另一个内存中,再通过ByteBuf直接操作。

Netty的一些重要概念 

  • Channel:数据传输流,与Channel相关的概念有以下四个。上一张图让你了解Netty中的Channel。
Channel一览

 

  • Channel:表示一个连接,可以理解为每一个请求,就是一个Channel。
  • ChannelHandler:核心处理业务就在这里,用于处理业务请求。
  • ChannelHandlerContext:用于传输业务数据。
  • ChannelPipeline:用于保存处理过程需要用到的ChannelHandler和ChannelHandlerContext。

     

  • ByteBuf

ByteBuf是一个存储字节的容器,最大的特点就是使用方便。他有自己的读索引和写索引方式,方便你对整段的字节缓存进行读写。也支持get/set,方便你对每个字节进行读写,他的数据结构如下图所示:

ByteBuf数据结构

 他有三种使用模式:

1.Heap Buffer 堆缓冲区

堆缓冲区是ByteBuf最常用的模式,他讲数据存储在堆空间。

2.Direct Buffer 直接缓冲区

直接缓冲区是ByteBuf的另一种常见模式,他的内存分配都不在堆中,jdk1.4后引入NIO的ByteBuffer类允许JVM通过本地方法调用分配内存。

通过这样免去中间的交换内存拷贝,提升IO处理速度,直接缓存区的内容可以留在在垃圾回收扫描的堆区以外。

DirectBuffer在(-XX:MaxDirectMemorySize=xxM)大小的限制下,使用Heap之外的内存。GC无法处理,也就意味着规避了在高负载下频繁的GC过程对应用线程的中断影响。

3.Composite Buffer 复合缓冲区

复合缓冲区相当于多个不同的ByteBuf的视图,这里是Netty提供的。jdk不具备这样的功能。

除此之外,他还提供一大堆api方便你使用,在这里我就不一一列出了,具体参见ByteBuf字节缓存

Codec

Netty中的编码/解码器,通过他你能完成字节与pojo、pojo与pojo的相互转换,从而达到自定义协议的目的。
在Netty里面中比较常用的的就是HttpRequestDecoder和HttpResponseEncoder。

写在最后

本篇文章很大参考了Netty入门教程——认识Netty,侵删。本人也是新手,在学习的路上,文中有些是自己看完之后的感觉并不一定正确,如有错误或者不足的的地方可以提出,感谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值