Netty基础知识总结(Netty实战读书笔记)

版权声明:随便转, 记得给个链接过来哦 https://blog.csdn.net/wk52525/article/details/87931437

《Netty实战》是一本比较好的Netty入门书籍,在此对一些重要的知识点进行总结,方便复习和回顾

一、Netty的概念及体系结构

1.java I/O
  • 阻塞I/O
    Sample
  • NIO
    Sample
2.Netty组件简介
  • Channel
    • Channel 是 Java NIO 的一个基本构造,可以把 Channel 看作是传入(入站)或者传出(出站)数据的载体。
    • 基本的 I/O 操作( bind() 、 connect() 、 read() 和 write() )依赖于底层网络传输所提 供的原语。
  • EventLoop
    • EventLoop 定义了 Netty 的核心抽象,用于处理连接的生命周期中所发生的事件。
      Sample
      • 一个 EventLoopGroup 包含一个或者多个 EventLoop
      • 一个EventLoop在它的生命周期内只和一个Thread绑定
      • 所有由 EventLoop 处理的 I/O 事件都将在它专有的 Thread 上被处理
      • 一个Channel在它的生命周期内只注册于一个EventLoop
      • 一个 EventLoop 可能会被分配给一个或多个 Channel
  • ChannelFuture
    • Netty 中所有的 I/O 操作都是异步的。因为一个操作可能不会立即返回,Netty 提供了 ChannelFuture 接口,其 addListener() 方法注册了一个 ChannelFutureListener ,监听器的回调方法operationComplete(),将会在对应的操作完成时被调用 。然后监听器可以判断该操作是成功地完成了还是出错了。
  • ChannelHandler
    • Netty 使用不同的事件来通知我们状态的改变或者是操作的状态,每个事件都可以被分发给 ChannelHandler 类中的某个用户实现的方法。
      Sample
  • ChannelPipeline
    • ChannelPipeline 提供了 ChannelHandler 链的容器,并定义了用于在该链上传播入站 和出站事件流的 API。当 Channel 被创建时,它会被自动地分配到它专属的 ChannelPipeline 。
    • ChannelHandler安装到 ChannelPipeline 中的过程:
      • 一个 ChannelInitializer 的实现被注册到了 ServerBootstrap 中 ;
      • 当ChannelInitializer.initChannel() 方法被调用时,ChannelInitializer 将在 ChannelPipeline 中安装一组自定义的ChannelHandler;
      • ChannelInitializer 将它自己从ChannelPipeline 中移除。
    • 在 Netty 中,有两种发送消息的方式。你可以直接写到 Channel 中,也可以 写到和 ChannelHandler 相关联的 ChannelHandlerContext 对象中。前一种方式将会导致消息从 ChannelPipeline 的尾端开始流动,而后者将导致消息从 ChannelPipeline 中的下一个 ChannelHandler 开始流动。
  • Bootstrap
    • 服务器需要两组不同的 Channel 。第一组将只包含一个 ServerChannel ,代表服务 器自身的已绑定到某个本地端口的正在监听的套接字。而第二组将包含所有已创建的用来处理传 入客户端连接(对于每个服务器已经接受的连接都有一个)的 Channel。
      Sample
      • 与 ServerChannel 相关联的 EventLoopGroup 将分配一个负责为传入连接请求创建 Channel 的 EventLoop 。一旦连接被接受,第二个 EventLoopGroup 就会给它的 Channel 分配一个 EventLoop
3.传输
  • NIO传输
    Sample
4.ByteBuf - Netty的数据容器
  • ByteBuf 维护了两个不同的索引:一个用于读取,一个用于写入。当你从 ByteBuf 读取时, 它的 readerIndex 将会被递增已经被读取的字节数。同样地,当你写入 ByteBuf 时,它的 writerIndex 也会被递增。
    • 名称以 read 或者 write 开头的 ByteBuf 方法,将会推进其对应的索引,而名称以 set 或者 get 开头的操作则不会。后面的这些方法将在作为一个参数传入的一个相对索引上执行操作。
  • 使用模式
    • 堆缓冲区
      • 最常用的 ByteBuf 模式是将数据存储在 JVM 的堆空间中。 这种模式被称为支撑数组 (backing array),它能在没有使用池化的情况下提供快速的分配和释放。这种方式非常适合于有遗留的数据需要处理的情况。
    • 直接缓冲区
      • 直接缓冲区的内容将驻留在常规的会被垃圾回收的堆之外。这对于网络数据传输是理想的选择,因为JVM在通过套接字发送数据时会在内部把堆上缓冲区的数据复制到一个直接缓冲区中。主要缺点是,相对于基于堆的缓冲区,它们的分配和释放都较为昂贵。
    • 复合缓冲区
  • 字节级操作
    • 索引访问、读/写字节、索引管理、查找…
  • ByteBufHolder
    • 为 Netty 的高级特性提供了支持,如缓冲区池化,其中可以从池中借用 ByteBuf ,并且在需要时自动释放。
  • ByteBuf 分配
    • ByteBufAllocator 接口:按需分配
    • Unpooled 缓冲区
    • ByteBufUtil 类
5.ChannelHandler和ChannelPipeline
  • Channel生命周期
    • registered->active->inactive->unregistered
  • 资源管理
    • 每当通过调用 ChannelInboundHandler.channelRead() 或者 ChannelOutboundHandler.write() 方法来处理数据时,你都需要确保没有任何的资源泄漏
    • 通过调用 ReferenceCountUtil.release() 方法释放资源
    • ByteToMessageDecoder的channelRead()中默认会release(),所以自定义解码可继承此类并重写decode(),否则需手动release()
  • ChannelPipeline
    • 每一个新创建的 Channel 都将会被分配一个新的 ChannelPipeline 。这项关联是永久性的
  • ChannelHandlerContext
    • 代表了 ChannelHandler 和 ChannelPipeline 之间的关联,每当有 ChannelHandler 添加到 ChannelPipeline 中时,都会创建 ChannelHandlerContext
      Sample

二、编解码

1.解码器(实现ChannelInboundHandler)
  • 抽象类 ByteToMessageDecoder
  • 抽象类 ReplayingDecoder
    • 扩展了 ByteToMessageDecoder 类,使我们不必调用 readableBytes() 方法。通过使用一个自定义的 ByteBuf 实现:ReplayingDecoderByteBuf。
  • 抽象类 MessageToMessageDecoder
    • 在两个消息格式之间进行转换(例如从一种 POJO 类型转换为另一种)
  • LineBasedFrameDecoder
    • 使用了行尾控制字符( \n 或者 \r\n )来解析消息数据
  • HttpObjectDecoder
    • HTTP 数据的解码器
2.编码器(实现ChannelOutboundHandler)
  • 抽象类 MessageToByteEncoder
  • 抽象类 MessageToMessageEncoder
3.编解码器类(同时实现ChannelInboundHandler和ChannelOutboundHandler)
  • 抽象类 ByteToMessageCodec
  • 抽象类 MessageToMessageCodec
  • CombinedChannelDuplexHandler 类
    • 这个类充当了 ChannelInboundHandler 和 ChannelOutboundHandler (该类的类型 参数 I 和 O )的容器。通过提供分别继承了解码器类和编码器类的类型,我们可以实现一个编解码器,而又不必直接扩展抽象的编解码器类。
4.预置的ChannelHandler和编解码器
  • SSL/TLS
    • SslHandler:内部使用 SSLEngine
  • HTTP/HTTPS
    • HttpObjectDecoder
    • HttpRequestEncoder/Decoder(继承HttpObjectDecoder)
    • HttpResponseEncoder/Decoder(继承HttpObjectDecoder)
    • HttpRequestDecoder(聚合上述RequestEncoder/Decoder)
    • HttpContentDecompressor:HTTP 压缩
  • WebSocket
    • WebSocketServerProtocolHandler
  • 空闲的连接和超时
    • IdleStateHandler:检测空闲时间,触发IdleStateEvent
    • ReadTimeoutHandler:指定时间间隔无入站数据抛出ReadTimeoutException 并关闭对应的 Channel
    • WriteTimeoutHandler:指定时间间隔无出站数据抛出WriteTimeoutException 并关闭对应的 Channel
  • 基于分隔符的协议
    • DelimiterBasedFrameDecoder:由用户提供的分隔符来提取帧
    • LineBasedFrameDecoder:使用行尾控制字符( \n或者\r\n )来解析
  • 基于长度的协议
    • FixedLengthFrameDecoder:提取在调用构造函数时指定的定长帧
    • LengthFieldBasedFrameDecoder:根据编码进帧头部中的长度值提取帧
  • 写大型数据
    • ChunkedWriteHandler
  • 序列化数据
    • JDK
      • CompatibleObjectEecoder/Decoder
      • ObjectEncoder/Decoder
    • JBoss Marshalling
      • CompatibleMarshallingEncoder/Decoer
      • MarshallingEncoder/Decoder
    • Protocol Buffers
      • ProtobufEncoder/Decoder
      • ProtobufVarint32LengthFieldPrepender
      • ProtobufVarint32FrameDecoder
5.编解码器中的引用计数
  • 引用计数需要特别的注意。对于编码器和解码器来说:一旦消息被编码或者解码,它就会被 ReferenceCountUtil.release(message) 调用自动释放。如果你需要保留引用以便稍后使用,那么你可以调用 ReferenceCountUtil.retain(message) 方法。这将会增加该引用计数,从而防止该消息被释放。

三、网络协议

1.WebSocket:(一个webSocket服务的示例)
2.UDP:(一个UDP广播服务的示例)

四、案例研究

(主要讲解了各大公司如何使用netty及他们的网络服务架构)

猜你喜欢

转载自blog.csdn.net/wk52525/article/details/87931437