"Netty real" summary

Foreword

We all know Netty is a framework to create a high-performance network for advanced applications, but the actual work actually go directly Netty scene like much (I did anyway). In fact, Netty everywhere, a lot of the underlying communication middleware framework are used in Netty, dubbo, rocketMQ, Elasticsearch other commonly used frameworks and middleware actually uses Netty. Recently read "Netty combat" this book, do a brief summary of the knowledge of it, omits some sections (such as Netty for unit testing, etc.).

Asynchronous and event-driven

bio threading model:

nio threading model:

Netty core components

  • Channel
  • Callback
  • Future
  • Events and ChannelHandler

Netty components and design

Netty Network Abstraction representatives

  • Channel— Socket
  1. EmbeddedChannel
  2. LocalServerChannel
  3. NioDatagramChannel
  4. NioSctpChannel
  5. NioSocketChannel
  • EventLoop- control flow, multithreading, concurrent
  • ChannelFuture- asynchronous notification

ChannelHandler 和 ChannelPipeline

  • Business logic of the application typically reside in one or more of ChannelInboundHandler
  • ChannelPipeline provides a container chain ChannelHandler
  • In Netty, there are two ways to send the message. You can write directly Channel, or you can write to and ChannelHandler associated ChannelHandlerContext object. The former approach will result in the message begins to flow from the trailing end of ChannelPipeline, which will cause the message flow from the start of the next ChannelPipeline ChannelHandler.
  • channelHandler applications: the encoder and decoder
  • Server EventLoopGroup

transmission

classification

  1. OIO-- blocking transmission
  2. NIO-- Asynchronous Transfer
  3. Asynchronous communication inside the JVM - Local
  4. Embedded——测试你的ChannelHandler

channel

  • 每个 Channel 都将会被分配一个 ChannelPipeline 和 ChannelConfig。 ChannelConfig 包含了该 Channel 的所有配置设置,并且支持热更新。
  • Netty 的 Channel 实现是线程安全的。
  • NIO处理channel状态
  • 关注linux的epoll实现
  • 应用程序最佳传输实现

数据容器ByteBuf

优点

  1. 可以被用户自定义的缓冲区类型扩展
  2. 通过内置的复合缓冲区类型实现了透明的零拷贝
  3. 容量可以按需增长(类似于 JDK 的 StringBuilder)
  4. 在读和写这两种模式之间切换不需要调用 ByteBuffer 的 flip()方法
  5. 读和写使用了不同的索引
  6. 支持方法的链式调用
  7. 支持引用计数
  8. 支持池化

ByteBuf使用模式

  1. 堆缓冲区,支撑数组
  2. 直接缓冲区
  3. 复合缓冲区

字节级操作

  1. 丢弃字节:discardReadBytes()
  2. 索引复位:clear()
  3. 切片:slice();副本:copy()

重要的类

  1. ByteBufHolder,持有ByteBuf引用,可以存储额外信息
  2. ByteBufAllocator,获取池化ByteBuf,可以从Channel或者ChannelHandlerContext获取ByteBufAllocator的引用
  3. Unpooled,获取未池化ByteBuf
  4. ByteBufUtil,工具类

引用计数

ReferenceCounted接口

ChannelHandler和ChannelPipeline

  • 当某个 ChannelInboundHandler 的实现重写 channelRead()方法时,它将负责显式地 释放与池化的 ByteBuf 实例相关的内存。Netty 为此提供了一个实用方法 ReferenceCount- Util.release()
public class DiscardHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ReferenceCountUtil.release(msg); 
    }
}

资源管理

  1. 每当通过调用 ChannelInboundHandler.channelRead()或者 ChannelOutboundHandler.write()方法来处理数据时,都需要确保没有任何的资源泄漏。除非调用了ChannelHandlerContext.fireChannelRead()交给下一个处理器处理。
  2. ChannelOutboundHandler.write()不仅要释放资源,还要通知ChannelPromise。否则可能会出现 ChannelFutureListener 收不到某个消息已经被处理了的通知的情况。
  3. 资源泄露检测类——ResourceLeakDetector
    利用了JDK的虚引用,配置参数java -Dio.netty.leakDetectionLevel=ADVANCED

ChannelPipeline接口

  1. 每一个新创建的 Channel 都将会被分配一个新的 ChannelPipeline。这项关联是永久性的; Channel 既不能附加另外一个 ChannelPipeline,也不能分离其当前的。在 Netty 组件 的生命周期中,这是一项固定的操作,不需要开发人员的任何干预。
  2. ChannelInboundHandler从头部开始处理,ChannelOutboundHandler从尾部开始处理

ChannelHandlerContext接口

  1. ChannelHandlerContext 有很多的方法,其中一些方法也存在于 Channel 和 Channel- Pipeline 本身上,但是有一点重要的不同。如果调用 Channel 或者 ChannelPipeline 上的这 些方法,它们将沿着整个 ChannelPipeline 进行传播。而调用位于 ChannelHandlerContext 上的相同方法,则将从当前所关联的 ChannelHandler 开始,并且只会传播给位于该 ChannelPipeline 中的下一个能够处理该事件的 ChannelHandler。
  2. 重要组件之间的关系
  3. 事件传播

异常处理

  • 通过调用 ChannelPromise 上的 setSuccess()和 setFailure()方法,可以使一个操作的状态在 ChannelHandler 的方法返回给其调用者时便即刻被感知到

EventLoop和线程模型

类层次结构

EventLoop实现细节

  1. 执行逻辑
  2. 分配方式

引导

Bootstrap——客户端或无连接协议

  • Bootstrap 类负责为客户端和使用无连接协议的应用程序创建 Channel

ServerBootstrap——服务端

  • ServerChannel 的实现负责创建子 Channel,这些子 Channel 代表了已被接受的连接

DatagramChannel——无连接

Bootstrap bootstrap = new Bootstrap();
bootstrap.group(new OioEventLoopGroup()).channel(
OioDatagramChannel.class).handler(new SimpleChannelInboundHandler<DatagramPacket>(){
    @Override
    public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
        // Do something with the packet
    }
);}
ChannelFuture future = bootstrap.bind(new InetSocketAddress(0));
future.addListener(new ChannelFutureListener() {
    @Override
    public void operationComplete(ChannelFuture channelFuture) throws Exception {
        if (channelFuture.isSuccess()) {
            System.out.println("Channel bound");
        } else {
            System.err.println("Bind attempt failed");
            channelFuture.cause().printStackTrace(); 
        }
}); 

关闭

  • EventLoopGroup.shutdownGracefully()
  1. 它将处理任何挂起的事件和任务,并且随后释放所有活动的线程

编解码器

编码器操作出站数据,而解码器处理入站数据。编解码器中的引用计数是会自动处理的,ReferenceCountUtil.release(message)

解码器

  1. ByteToMessageDecoder
  2. ReplayingDecoder
  3. MessageToMessageDecoder
  4. TooLongFrameException 防止解码器缓冲的数据耗尽内存

编码器

  1. MessageToByteEncoder
  2. MessageToMessageEncoder

编解码器

  1. ByteToMessageCodec
  2. MessageToMessageCodec
  3. CombinedChannelDuplexHandler

预置的 ChannelHandler 和编解码器

SslHandler

在大多数情况下,SslHandler将是ChannelPipeline中的第一个ChannelHandler。 这确保了只有在所有其他的 ChannelHandler 将它们的逻辑应用到数据之后,才会进行加密。

HTTP 解码器、编码器和编解码器

  1. HttpRequestEncoder
  2. HttpResponseEncoder
  3. HttpRequestDecoder
  4. HttpResponseDecoder
  5. HttpObjectAggregator——聚合 HTTP 消息
  6. HttpContentCompressor && HttpContentDecompressor——HTTP 压缩和解压

WebSocketProtocolHandler

空闲的连接和超时

  1. IdleStateHandler——可以用来实现心跳
  2. ReadTimeoutHandler
  3. WriteTimeoutHandler

基于分隔符的协议

  1. DelimiterBasedFrameDecoder
  2. LineBasedFrameDecoder——比DelimiterBasedFrameDecoder效率高

基于长度的协议

LineBasedFrameDecoder

  1. FixedLengthFrameDecoder
  2. LengthFieldBasedFrameDecoder

写大型数据

  1. FileRegion
  • 通过支持零拷贝的文件传输的 Channel 来发送的文件区域
  • 只适用于文件内容的直接传输,不包括应用程序对数据的任何处理
  1. ChunkedWriteHandler
  • 支持将数据从文件系统复制到用户内存中
  • 支持异步写大型数据流,而又不会导致大量的内存消耗

序列化数据

  1. JBoss Marshalling
  2. Protocol Buffers

扩展——研究Netty中碰到的思考

  1. netty解决的epoll空轮询
  2. FastThreadLocal实现原理
  3. EventLoopGroup分配EventLoop的实现细节

类似于轮询,用原子变量来实现索引递增,做了一个优化,如果总数是2的倍数,会通过位移来计算余数

  1. ChannelProgressivePromise实时获取传输进度怎么实现
  2. 流量整形 ChannelTrafficShapingHandler 和 GlobalTrafficShapingHandler
  3. 链路空闲检测 IdleStateHandler

本文由博客一文多发平台 OpenWrite 发布!

发布了7 篇原创文章 · 获赞 4 · 访问量 10万+

Guess you like

Origin blog.csdn.net/Forest441/article/details/104430508