Netty4 总结

主要构件

请添加图片描述

  • Channel: 抽象一个到实体(硬件、文件、Socket)的连接,封装了不同的I/O操作,屏蔽底层细节。用于执行所有的I/O操作。

  • ChannelHandler:事件处理器
    请添加图片描述

    • ChannelInboundHandler:处理入站事件(输入)
    • ChannelOutboundHandler:处理出战事件(输出)
  • ChannelPipeline: 包含一组事件处理器 – 处理某个Channel的I/O事件的流程

    • ChannelHandler的容器(有序表)
    • 每个Channel持有一个ChannelPipeline,其I/O事件由按顺序由ChannelPipeline内的ChannelHandler处理
  • EventLoop:事件循环–处理其负责的Channel的所有I/O和事件

  • EventLoopGroup:EventLoop池

  • Bootstrap : 启动网络处理

    • Bootstrap:引导客户端,连接远程主机
    • ServerBootstrap: 引导服务器,监听一个端口,接收连接并创建Channel进行通信
  • ChannelFuture:异步通知

    • 由异步操作返回,代表一个未完成的操作
    • 可向其添加监听器addListener(),以在操作完成时做出动作
  • ChannelPromise:继承自ChannelFuture,可写的ChannelFuture

Channel

  • 抽象一个到实体(硬件、文件、Socket)的连接,封装了不同的I/O操作,屏蔽底层细节。提供统一的I/O操作。
  • Channel被创建时,将被分配一个ChannelPipeline(包含用于处理其一切I/O数据和事件的Handler)和ChannelConfig(描述其配置)
  • 请添加图片描述
  • 为线程安全的
  • 实现类(内置的传输)
    • 基于NIO的传输(位于io.netty.channel.socket.nio包)–基于java.nio.channels包
      • NioServerSocketChannel 用于监听并接受(accept)连接
      • NioSocketChannel TCP通信
      • NioDatagramChannel UDP通信,收发报文
    • 基于Epoll的传输(位于io.netty.channel.epoll包)-- JNI 驱动的 epoll()。Linux下高负载时由于NIO。
    • 基于OIO的传输–基于java.net包,阻塞I/O
    • Local–通过JVM内部通道,进行本地通信
    • Embedded–用于测试,提供操作出入站数据的接口。
  • 生命周期:包含4个状态,在发送变化时触发响应的事件。
    • ChannelUnregistered :未注册到 EventLoop
    • ChannelRegistered :被注册到了 EventLoop
    • ChannelActive :处于活动状态,可进行传输
    • ChannelInactive:不可进行传输

EventLoop & EventLoopGroup

  • EventLoop处理某个Channel的I/O和事件的整体流程(监听I/O,分配事件)

  • 一个EventLoop在生命周期内之和一个Thread绑定(只有一个线程)

  • 使用非阻塞I/O时,一个EventLoop处理一个或多个Channel的I/O和事件

  • 使用阻塞I/O时,一个EventLoop处理一个Channel

  • EventLoopGroup即EventLoop的池,相当于一个线程池

  • 任务(Runnable、Callable)可以提交给EventLoop进行调度执行(

    • schedule方法:指定时间后执行
    • scheduleAtFixRate方法:以指定周期调用
  • 事件和任务是以先进先出(FIFO)的顺序执行的,以保证数据顺序的正确

  • 继承关系:
    请添加图片描述

ChannelHandler

请添加图片描述

  • ChannelInboundHandler:处理入站事件(输入)

  • ChannelOutboundHandler:处理出战事件(输出)

  • 适配器-ChannelInboundHandlerAdapter&ChannelOutboundHandlerAdapter

    • 提供基本实现:将事件直接传入下一个Hundler
    • 实现一个Handler时不必将其方法全部实现一遍
  • 共享的ChannelHandler:在多个ChannelPipeline内安装同一个ChannelHandler对象(可用于跨连接收集数据),需将该ChannelHandler类声明为可以共享的(使用注解**@Sharable**)

  • 当某个 ChannelInboundHandler 的实现重写 **channelRead()**方法时

    • 要么将消息传递给下一个Handler
    • 要么负责显式地释放相关的池化的ByteBuf(可使用ReferenceCountUtil.release(…))
  • 异常处理

    • 入站过程的异常将流过ChannelPipeline,直到被某个ChannelInboundHandler的exceptionCaught方法捕获。
    • 出站过程:ChannelOutboundHandler的大多数方具有ChannelPromise参数。通过setFailure(Throwable cause)方法通知操作失败,并携带异常

ChannelHandlerContext

  • 一个ChannelHandlerContext对象代表ChannelHandler和ChannelPipeline之间的关联
  • ChannelHandler插入ChannelPipeline时创建
  • ChannelHandler在生命周期内一直与该ChannelHandlerContext绑定
  • ChannelHandler与在同一个Pipeline中相邻Handler的交互(事件的向下传递)实际上是通过Context对象进行
  • 请添加图片描述
  • 在ChannelHandlerContext上调用write(),数据将从尾端经过所有ChannelOutboundHandler到头部,传入Channel。
  • 在ChannelHandlerContext上调用read(),从Channel读取数据(按正常流程执行,通过Pipeline)

Bootstrap

  • 配置并运行服务器/客户端

  • 请添加图片描述

  • Bootstrap类,引导客户端

    • 负责为客户端和使用无连接协议的应用程序创建 Channel,与服务器通信
    • 无连接的客户端使用Bootstrap的bind() ,创建一个Channel绑定指定端口收发UDP包
    • 有连接的客户端使用Bootstrap的connect(),连接到远程主机
  • ServerBootstrap类,引导服务器

    • 负责使用一个父Channel监听并接受来自客户端的连接,创建子Channel与客户端进行通信
    • 调用bind(),创建一个ServerChannel用于监听并接受来自客户端的连接
    • 收到来自客户端的连接后,创建一个Channel来负责该连接

ByteBuf

Netty交换和处理数据的容器。替代Java的ByteBuffer。

  • 维护两个索引: 读索引readerIndex、写索引writerIndex

    • readXXX() 将推进readerIndex; writeXXX()将推进writerIndex. (getXXX(), putXXX()不会改变索引)

    • 有效的字节在 [readerIndex, writerIndex) 上

    • 请添加图片描述

    • 调用discardReadBytes() 回收可丢弃字节(极有可能导致内存复制)

    • 请添加图片描述

  • 数据存储方式

    • 支撑数组(backing array) : 将数据储存在JVM堆空间中,即使用一个Java数组。
      • buf.hasArray() 判断是否有支撑数组
      • buf.array() 获取其数组
    • 直接缓冲区: 通过本地调用获取内存,直接向操作系统申请的内存。不会被垃圾回收。如果数据不在直接缓冲区,通过socket发送数据时,会将JVM堆中的数据复制到直接缓冲区,使用直接缓冲区更快。
  • 复合缓冲区 通过ByteBuf的子类CompositeByteBuf创建两个缓冲区的组合视图。

    //两个ByteBuf组合为一个ByteBuf,不会发生拷贝
    ByteBuf b = Unpooled.wrappedBuffer(b1,b2);
    
  • 创建缓冲区:

    • 使用ByteBufAllocator创建ByteBuf。
    • 可通过**Channel或ChannelHandlerContext的alloc()**获取ByteBufAllocator实例。
    • ByteBufAllocator内置实现:
      • PooledByteBufAllocator: 池化ByteBuf
      • UnpooledByteBufAllocator: 不进行池化
    • 默认(4.1.x)使用PooledByteBufAllocator(引导服务器时可配置)
    • 可使用Unpooled工具类创建未池化的ByteBufByteBuf b = Unpooled.buffer(n);
  • 自动扩容 - 超过初始大小时,自动扩容。

  • 引用计数

    • ByteBuf使用引用计数管理资源
    • buf.realse() 计数减1
    • buf.retain() 计数加1

编解码器框架 (编解码器框架–内置的一些列ChannelHandler)请添加图片描述

  • 解码器 Decoder
    • ByteToMessageDecoder : 从Channel读取的数据–>程序内部的数据格式
    • MessageToMessageDecoder :将消息由T类型转换其他类型(转换两个对象的InboundHandler)
    • ReplyingDecoder:便于积累数据到足够长度后进行转换
    • TooLongFrameException 数据长度超过解码器设定的限制,抛出该异常
  • 编码器 Encoder
    • MessageToByteEncoder : 程序内部的数据格式 --> 适合传输的数据 (由Channel传出)
    • MessageToMessageEncoder :将消息由T类型转换其他类型(转换两个对象的OutboundHandler)
  • 编解码器 Codec – 将编码器 和 解码器 组合到一个类中
    • ChannelDuplexHandler :同时实现InboundHandler和OutboundHandler的Adapter
常用预置编解、码器
对HTTP(S)的支持

Netty中HTTP相关的类:

请添加图片描述

  • 编解码Http请求和响应
    • HttpRequestEncoder
    • HttpRequestDecoder
    • HttpResponseEncoder
    • HttpResponseDecoder
    • HttpClientCodec (HttpRequestEncoder + HttpResponseDecoder)
    • HttpServerCodec (HttpRequestDecoder + HttpResponseEncoder)
  • 聚合HTTP消息
    • HttpObjectAggregator 将HttpMessage跟HttpContent聚合为FullHttpRequest或FullHttpResponse
  • HTTP压缩
    • HttpContentDecompressor 客户端用于解压响应
    • HttpContentCompressor 服务器端进行压缩
  • HTTPS
    • SslHandler (一般作为第一个Handler加入)
  • WebSocket
    • WebSocketServerProtocolHandler(“/websocket”) 处理WebSocket协议,以"/websocket"为进行升级握手的URI
    • TextFrameHandler() 处理WebSocket的Text帧
其他
  • 处理空闲

    • IdleStateHandler(…) 空闲(既没有受到消息,也没有发出消息)超过指定时间,触发IdleStateEvent事件。
    • ReadTimeoutHandler(…) 在指定时间间隔内未受到消息,触发ReadTimeoutException
    • WriteTimeoutHandler(…) 在指定时间间隔内未发出消息,触发WriteTimeoutException
  • 使用分隔符分割

    • DelimiterBasedFrameDecoder(分割符) 按指定分隔符,分割
    • LineBasedFrameDecoder 按’\n’ 或 '\r\n’分割
  • 基于长度的分割

    • FixedLengthFrameDecoder 按指定长度分割
    • LengthFieldBasedFrameDecoder 根据帧头部的长度进行分割
  • 序列化

    • JDK序列化
      • CompatibleObjectDecoder
      • CompatibleObjectEncoder
      • ObjectDecoder
      • ObjectEncoder
传输大文件
  • 使用FileRegion进行零拷贝的传输。(实现类: DefaultFileRegion)
  • 需要将文件内容复制到用户内存再传输时,使用ChunkedInput(需在Pipeline中添加 ChunkedWriteHandler),可避免大量内存消耗。
  • 请添加图片描述
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绫零依

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值