✏️
blog
  • README
  • 2023 11
    • expect使用
  • 2023 10
    • 通过Appium给iOS应用自动化执行脚本
  • 2023 06
    • 三种ThreadLocal详解
    • 常见限流算法总结
    • 分布式ID生成算法
  • 2023 05
    • 线上机器CLOSE_WAIT连接数异常排查
    • 多数据源引发transactional事务回滚失效
  • 2023 04
    • MySQL中BufferPool
  • 2022 12
    • Linux IO
    • Netty总结
  • 2022 04
    • Thrift
  • 2022 03
    • JVM命令总结
    • 频繁FullGC定位思路
    • Redis总结
    • Spring常见问题总结
    • Kafka总结
  • 2022 02
    • Dubbo柔性服务天池大赛总结
  • 2021 12
    • 泛型中的extends和super
    • 手写一个Spring Boot Starter
  • 2021 11
    • 常用消息队列总结
  • 2021 10
    • swagger2快速使用
    • SpringBoot接口cors跨域访问
  • 2021 08
    • 常用shell命令总结
  • 2021 05
    • 线程cpu飙升排查
    • zookeeper install
  • 2021 04
    • Java虚拟机
    • [Spring Boot](2021-04/2021-04-04-Spring Boot.md)
    • [Spring MVC](2021-04/2021-04-04-Spring MVC.md)
    • 分布式ID
    • 消息队列
    • [Spring AOP](2021-04/2021-04-05-Spring AOP.md)
    • 布隆过滤器
    • Scala内核Spark阻塞排查
  • 2020 12
    • 使用Python优雅实现tail命令
  • 2020 11
    • Spark基础架构
    • 一文搞定Git
    • Spark线上问题引发的思考
  • 2020 04
    • 使用GitBook
  • 2019 05
    • SELinux、Netfilter、iptables、firewall和ufw五者关系
    • 安装npm和nodejs
    • 访问不到云服务器中的项目
  • 2019 04
    • 二叉树中节点与度数
    • 实现会话跟踪的技术有哪些
    • 计算机操作系统-死锁
    • Semaphore Count Down Latch Cyclic Barrier
    • Java内存模型
    • 双重检查锁定
    • synchronized实现底层
    • Lock接口
    • HTTP与HTTPS的区别
    • Java中线程池
    • Java中的阻塞队列
    • 排序算法
  • 2019 03
    • MySQL中索引
    • MySQL存储引擎
    • MySQL锁机制
    • n的阶乘结果后面0的个数
由 GitBook 提供支持
在本页
  • Java NIO基础介绍
  • Netty高性能总结
  • Netty关键组件
  • EventLoop
  • Channel
  • ChannelHandlerContext
  • ChannelHandler
  • ChannelPipeline
  • ByteBuf
  • Netty关键流程
  • ServerBootstrap启动流程
  • NioEventLoop事件循环,读事件触发流程
  • client connect

这有帮助吗?

  1. 2022 12

Netty总结

上一页Linux IO下一页2022 04

最后更新于2年前

这有帮助吗?

Java NIO基础介绍

参考 https://www.cnblogs.com/hamsure/p/15549612.html

Netty高性能总结

Netty关键组件

EventLoop

==>

  • BossGroup

  • WorkerGroup

  • 主从Reactor多线程模型

参考链接:https://blog.csdn.net/qq_43203949/article/details/119395403

  1. Netty 抽象出两组线程池:BossGroup 和 WorkerGroup,也可以叫做 BossNioEventLoopGroup 和 WorkerNioEventLoopGroup。每个线程池中都有 NioEventLoop 线程。BossGroup 中的线程专门负责和客户端建立连接,WorkerGroup 中的线程专门负责处理连接上的读写。BossGroup 和 WorkerGroup 的类型都是 NioEventLoopGroup。

  2. NioEventLoopGroup 相当于一个事件循环组,这个组中含有多个事件循环,每个事件循环就是一个 NioEventLoop。

  3. NioEventLoop 表示一个不断循环的执行事件处理的线程,每个 NioEventLoop 都包含一个 Selector,用于监听注册在其上的 Socket 网络连接(Channel)。

  4. NioEventLoopGroup 可以含有多个线程,即可以含有多个 NioEventLoop。

  5. 每个 BossNioEventLoop 中循环执行以下三个步骤:

    • select:轮训注册在其上的 ServerSocketChannel 的 accept 事件(OP_ACCEPT 事件)

    • processSelectedKeys:处理 accept 事件,与客户端建立连接,生成一个 NioSocketChannel,并将其注册到某个 WorkerNioEventLoop 上的 Selector 上

    • runAllTasks:再去以此循环处理任务队列中的其他任务

  6. 每个 WorkerNioEventLoop 中循环执行以下三个步骤:

    • select:轮训注册在其上的 NioSocketChannel 的 read/write 事件(OP_READ/OP_WRITE 事件)

    • processSelectedKeys:在对应的 NioSocketChannel 上处理 read/write 事件

    • runAllTasks:再去以此循环处理任务队列中的其他任务

  7. 在以上两个processSelectedKeys步骤中,会使用 Pipeline(管道),Pipeline 中引用了 Channel,即通过 Pipeline 可以获取到对应的 Channel,Pipeline 中维护了很多的处理器(拦截处理器、过滤处理器、自定义处理器等)。

建立channel 注册channel的过程及实现 可见下文

主从Reactor多线程模型实现

参考链接:https://www.kancloud.cn/luoyoub/network-programming/2234086

其他:单Reactor单线程模型 单Reactor多线程模型

Channel

==>

  • NioServerSocketChannel

  • NioSocketChannel

Channel: A nexus to a network socket or a component which is capable of I/O operations such as read, write, connect, and bind.

NioServerSocketChannel的继承实现

NioSocketChannel的继承实现

ChannelHandlerContext

==>

  • DefaultChannelHandlerContext

  • ChannelOutboundInvoker

  • ChannelInboundInvoker

主要功能:

  1. 使ChannelHandler能够与其ChannelPipeline和其他处理程序进行交互

  2. 处理程序可以通知ChannelPipeline中的下一个ChannelHandler

  3. 可以动态修改它所属的ChannelPipeline

  4. 可以通过AttributeKey存储一些和Channel/ChannelHandler相关的状态信息

ChannelHandler

==>

  • ChannelInBoundHandler (处理InBound事件(入站),ChannelInboundHandlerAdapter为其默认实现)

  • ChannelOutBoundHandler (处理OutBound事件(出站),ChannelInboundHandlerAdapter为其默认实现)

  • ChannelDuplexHandler (既处理InBound也处理OutBound)

  • SimpleChannelInboundHandler (可以用于处理特定类型的消息)

  • ChannelInitializer

  • Encoder Decoder (TCP粘包/拆包)

主要功能:

  1. 处理或拦截IO事件,并将其转发到其ChannelPipeline中的下一个Handler

  2. 通过使用ChannelHandlerContext对象,ChannelHandler可以向上游或下游传递事件,动态修改管道,或存储特定于处理程序的信息(使用AttributeKeys)。

一个ChannelHandler可以对应多个ChannelHandlerContext (ChannelHandler.Sharable)

几种常见的Handler

DelimiterBasedFrameDecoder

通过指定的字符切割ByteBuf,将ByteBuf解码为Message

构造器

 /**
  * Creates a new instance.
  *
  * @param maxFrameLength  the maximum length of the decoded frame.
  *                        A {@link TooLongFrameException} is thrown if
  *                        the length of the frame exceeds this value. (最大长度,如果超过直接异常)
  * @param stripDelimiter  whether the decoded frame should strip out the
  *                        delimiter or not (数据中是否保留分割符)
  * @param failFast  If <tt>true</tt>, a {@link TooLongFrameException} is
  *                  thrown as soon as the decoder notices the length of the
  *                  frame will exceed <tt>maxFrameLength</tt> regardless of
  *                  whether the entire frame has been read.
  *                  If <tt>false</tt>, a {@link TooLongFrameException} is
  *                  thrown after the entire frame that exceeds
  *                  <tt>maxFrameLength</tt> has been read.
  * @param delimiters  the delimiters (支持多个分割符)
  */
 public DelimiterBasedFrameDecoder(
         int maxFrameLength, boolean stripDelimiter, boolean failFast, ByteBuf... delimiters) {}

LineBasedFrameDecoder

按行(\n 或 \r\n)解码ByteBuf转为Obj

FixedLengthFrameDecoder

固定长度解码ByteBuf转为Obj

LengthFieldBasedFrameDecoder

通过长度的字段标识消息长度

构造器参数

 /**
  * Creates a new instance.
  *
  * @param byteOrder
  *        the {@link ByteOrder} of the length field
  * @param maxFrameLength
  *        the maximum length of the frame.  If the length of the frame is
  *        greater than this value, {@link TooLongFrameException} will be
  *        thrown.
  * @param lengthFieldOffset
  *        the offset of the length field
  * @param lengthFieldLength
  *        the length of the length field
  * @param lengthAdjustment
  *        the compensation value to add to the value of the length field
  * @param initialBytesToStrip
  *        the number of first bytes to strip out from the decoded frame
  * @param failFast
  *        If <tt>true</tt>, a {@link TooLongFrameException} is thrown as
  *        soon as the decoder notices the length of the frame will exceed
  *        <tt>maxFrameLength</tt> regardless of whether the entire frame
  *        has been read.  If <tt>false</tt>, a {@link TooLongFrameException}
  *        is thrown after the entire frame that exceeds <tt>maxFrameLength</tt>
  *        has been read.
  */
 public LengthFieldBasedFrameDecoder(
         ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength,
         int lengthAdjustment, int initialBytesToStrip, boolean failFast) {}

HttpServerCodec

http server的handler,一般和HttpObjectAggregator组合使用

ChannelPipeline

核心要点:

  1. 外部事件被动触发 Inbound

  2. 内部操作主动触发 Outbound

 *
 *                                                 I/O Request
 *                                            via {@link Channel} or
 *                                        {@link ChannelHandlerContext}
 *                                                      |
 *  +---------------------------------------------------+---------------+
 *  |                           ChannelPipeline         |               |
 *  |                                                  \|/              |
 *  |    +---------------------+            +-----------+----------+    |
 *  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |              /|\                                  |               |
 *  |               |                                  \|/              |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |              /|\                                  .               |
 *  |               .                                   .               |
 *  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
 *  |        [ method call]                       [method call]         |
 *  |               .                                   .               |
 *  |               .                                  \|/              |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |              /|\                                  |               |
 *  |               |                                  \|/              |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |
 *  |    +----------+----------+            +-----------+----------+    |
 *  |              /|\                                  |               |
 *  +---------------+-----------------------------------+---------------+
 *                  |                                  \|/
 *  +---------------+-----------------------------------+---------------+
 *  |               |                                   |               |
 *  |       [ Socket.read() ]                    [ Socket.write() ]     |
 *  |                                                                   |
 *  |  Netty Internal I/O Threads (Transport Implementation)            |
 *  +-------------------------------------------------------------------+
 *

ByteBuf

=>

  • ByteBufHolder

  • ByteBufAllocator

  • ByteBufUtil

  • CompositeByteBuf

  • UnpooledByteBufAllocator

  • PooledByteBufAllocator

  • DirectByteBuf

  • HeapByteBuf

// todo 源码实现待阅读

Netty关键流程

ServerBootstrap启动流程

NioEventLoop事件循环,读事件触发流程

NioEventLoop#run
   => processSelectedKeys 
   ==> processSelectedKeysOptimized 
   ===> processSelectedKey
   ====> AbstractNioByteChannel#read 
   =====> DefaultChannelPipeline#fireChannelRead
   =====> DefaultChannelPipeline#fireChannelReadComplete

client connect

  1. 通过channelFactory new出一个channel

  2. 初始化channel(添加pipeline和一些config),并注册到EventLoopGroup中

  3. address解析 调用channel connect

  4. 调用channel的pipeline connect,从pipline尾部开始分别执行对应context中的handler

  5. 调用Socket的connect

ChannelOptions
NioServerSocketChannel
NioSocketChannel