Netty-架构与原理

概述

Netty是一个异步的基于事件驱动的网络框架。
NIO的概念是指:

  1. 没当客户端请求时,创建一个Socket Channel,并注册到Selector(多路复用器)上去。
  2. Selector关注服务器的IO读写事件,此时客户端不用等待IO事件完成,继续work
  3. 一旦服务器端完成IO操作,Selector会收到通知,同时告诉客户端已完成IO
  4. 客户端就可以通过Socket Channel获取相应的数据了

Selector并不是真正意义上的异步,是需要通过线程阻塞的方式监听IO事件变更,只是这种方式没有让客户端等待,是Selector在等待IO返回,并通知客户端去获取数据。

基于NIO

  1. Netty封装了NIO,不需要关注NIO的具体实现细节
  2. 对网络连接和访问做了处理
  3. 处理数据灵活,支持多种序列化框架
  4. 提供了线程池和Buffer机制

核心组件

  1. Channel:当客户端和服务器连接时会创建Channel,可以理解为Socket连接,负责基本的IO操作,如bind()、connect()、read()、write()
  2. EventLoop和EventLoopGroup:
    2.1 消息的请求和响应组成了Event,如:连接已激活;数据读取;用户事件;异常事件;打开链接;关闭链接等
    2.2 每个Channel都被分配给个EventLoop,一个EventLoop可以服务多个Channel,每个EventLoop占用一个Thread,同时这个Thread又会处理EventLoop上面发生的所有IO操作和事件
    2.3 而EventLoopGroup就是用来生成EventLoop的,一个EventLoopGroup包含了多个EventLoop,EventLoopGroup创建一个新的Channel,并分配到EventLoop,在异步传输模式下,一个EventLoop可以处理多个Channel产生的事件,主要的工作是事件的发现和通知
    2.4 相当于之前是一个Channel占用一个Thead,现在是多个Channel使用一个Thead。当客户端发送消息到服务端时,EventLoop告诉服务器去取消息同时客户端继续work,当服务器端发送消息到客户端,EventLoop通知客户端取消息。
  3. ChannelHandler,ChannelPipeline 和 ChannelHandlerContext,
    3.1 ChannelHandler事件的处理者,在ChannelHandler中添加一些业务代码,如数据转换,业务处理等,针对入口数据和出口数据分别有不同的handler,ChannelInBoundHandler和ChannelOutBoundHandler
    3.2 ChannelPipeline为ChannelHandler链提供容器
    3.3 ChannelHandlerContext就是各个ChannelHandler之间的关联,ChannelHandlerContext参数贯穿ChannelPipeline

数据容器

Netty将ByteBuf作为数据容器,存放数据。

堆缓冲区

ByteBuf将数据存储在JVM,通过数组实现,可以快速访问,被JVM管理

直接缓冲区

堆外分配内存,不占用JVM,在Socket传输时性能好,直接从缓冲区发送数据

复合缓冲区

Netty提供了CompsiteByteBuf,可以将堆缓存和直接缓冲区数据放在一起使用更方便。

Bootstrap

Bootstrap的作用就是将Netty的核心组件配置到程序中,run起来。
分别有bootstrap和serverBootstrap
Bootstrap通过bind()绑定再通过connect()创建Channel
ServerBootstrap通过bind()之后创建ServerChannel
ServerBootstrap需要两个EventLoopGroup,第一组 ServerChannel 监听本地端口的套接字。第二组用来监听客户端请求的套接字。

粘包问题

TCP为了提高性能,会将需要发送的数据放到缓冲区,满了之后就发送给接收端,同样接收端也有缓冲区机制,来接收数据。
由于TCP本身是无界的数据流,本身是没办法避免的,只能在应用层协议控制:

  1. 使用定长消息,每次读完既定长度内容作为消息,FixedLengthFrameDecoder
  2. 使用带消息头协议、消息头存储标志位和长度,LengthFieldBasedFrameDecoder与LengthFieldPrepender
  3. 设置消息边界,比如在消息尾部设置换行符,LineBasedFrameDecoder与DelimiterBasedFrameDecoder

AIO

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

Reactor

高性能网络编程模式

单线程Reactor

在这里插入图片描述
单线程模型就是一个reactor(select+循环),客户端(client)注册进来由reactor接收注册事件,然后再由reactor分发(dispatch)出去,由下面的处理器(read、decode、compute等)去处理

多线程Reactor

在这里插入图片描述
多线程Reactor中,注册接收事件都是由Reactor来做,其它的计算,编解码由一个线程池来做。单独一个线程接收请求,另一个线程池处理其它业务。这种模型的问题就是,使用线程池处理的时候,很多地方会有多次线程切换,上下文切换,导致效率比较低

Multiple Reactor

在这里插入图片描述
有多个Reactor,一个boss Reactor负责接收,另外几个worker Reactor负责读写,把业务部分的处理还是放到线程池中来做。

netty对三种Java基本的Reactor模式都是支持的
如果需要很复杂的计算,建议在handler中加入线程池进行处理。尽量不要让IO线程池阻塞。

https://mp.weixin.qq.com/s/UIZL78m105btP2HWFmQmlw
https://www.cnblogs.com/guos/p/12188495.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值