• Netty源码剖析之线程模型


    背景

    1. NIO 的类库和 API 繁杂,使用麻烦:需要熟练掌握 Selector、ServerSocketChannel、SocketChannel、ByteBuffer等。
    2. 需要具备其他的额外技能:要熟悉 Java 多线程编程,因为 NIO 编程涉及到 Reactor 模式,必须对多线程和网络编程非常熟悉,才能编写出高质量的 NIO 程序。
    3. 开发工作量和难度都非常大:例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常流的处理等等。
    4. JDK NIO 的 Bug:臭名昭著的 Epoll Bug,它会导致 Selector 空轮询,最终导致 CPU 100%

    Netty简介

    Netty 是由 JBOSS 提供的一个 Java 开源框架。Netty 提供异步的、基于事件驱动的网络应用程序框架,用以快速开发高性能、高可靠性的网络 IO 程序。 Netty 是一个基于 NIO 的网络编程框架,使用Netty 可以帮助你快速、简单的开发出一 个网络应用,相当于简化和流程化了 NIO 的开发过程。 作为当前最流行的 NIO 框架,Netty 在互联网领域、大数据分布式计算领域、游戏行业、 通信行业等获得了广泛的应用,知名的 Elasticsearch 、Dubbo 框架内部都采用了 Netty。

    在这里插入图片描述

    线程模型

    线程模型对于线程的处理性能非常重要,目前线程模型

    • 传统阻塞 I/O 模型
    • Reactor 模型
      根据 Reactor 的数量和处理资源池线程的数量不同,有 3 种典型的实现
      • 单 Reactor 单线程
      • 单 Reactor 多线程
      • 主从 Reactor 多线程

    1、传统阻塞IO线程模型

    一个请求一个线程
    在这里插入图片描述
    问题:

    • 每个请求需要创建独立的线程,创建线程是需要JVM内存开销的,默认好像是1kb,如果说并发比较大,资源占用比较大(调小)
    • 瞬时并发,请求回落,线程浪费严重(线程池)
    • 线程在业务处理过程中,可能会碰到IO,消费者数据消费更不上生产者线程等等,这些势必会导致线程堵塞等待(reactor-stream)
    • 连接建立后,当前线程中发现inputStram中没有数据可读,也会导致线程堵塞

    2、单Reactor单线程模型

    在这里插入图片描述
    Reactor 模式也叫 Dispatcher模式. Reactor 模式使用IO 复用监听事件, 收到事件后,分发给某个线程(进程), 这点就是网络服务器高并发处理关键.

    缺点:

    1. 性能问题: 只有一个线程,无法完全发挥多核 CPU 的性能。Handler 在处理某个连接上的业务时,整个进程无法处理其他连接事件,很容易导致性能瓶颈
    2. 可靠性问题: 线程意外终止或者进入死循环,会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障

    3、单Reactor多线程模型

    在这里插入图片描述
    问题:

    1、多线程数据共享和访问比较复杂, reactor 处理所有的事件的监听和响应,在单线程运行, 在高并发场景容易出现性能瓶颈
    2、Reactor线程压力过大,既要接受建立连接又要分发请求

    4、主从Reactor多线程模型

    在这里插入图片描述
    问题:
    这种模式的缺点是编程复杂度较高。但是由于其优点明显,在许多项目中被广泛使用,包括Nginx、Memcached、Netty 等。这种模式也被叫做服务器的 1+M+N 线程模式,即使用该模式开发的服务器包含一个(或多个,1 只是表示相对较少)连接建立线程+M 个 IO 线程+N 个业务处理线程。这是业界成熟的服务器程序设计模式。

    5、Netty线程模型

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    • Netty 抽象出两组线程池:BossGroup 和 WorkerGroup,也可以叫做BossNioEventLoopGroup 和 WorkerNioEventLoopGroup。每个线程池中都有NioEventLoop 线程。BossGroup 中的线程专门负责和客户端建立连接,WorkerGroup 中的线程专门负责处理连接上的读写。BossGroup 和 WorkerGroup 的类型都是NioEventLoopGroup
    • NioEventLoopGroup 相当于一个事件循环组,这个组中含有多个事件循环
    • NioEventLoop 表示一个不断循环的执行事件处理的线程每个 NioEventLoop 都包含一个Selector,用于监听注册在其上的 Socket 网络连接(Channel)
    • NioEventLoopGroup 可以含有多个线程,即可以含有多个 NioEventLoop
      每个 BossNioEventLoop 中循环执行以下三个步骤
      • select:轮训注册在其上的 ServerSocketChannel 的 accept 事件(OP_ACCEPT 事件)
      • processSelectedKeys:处理 accept 事件,与客户端建立连接,生成一个
        NioSocketChannel,并将其注册到某个 WorkerNioEventLoop 上的 Selector 上
      • runAllTasks:再去以此循环处理任务队列中的其他任务
    • 每个 WorkerNioEventLoop 中循环执行以下三个步骤
      • select:轮训注册在其上的 NioSocketChannel 的 read/write 事件
        (OP_READ/OP_WRITE 事件)
      • processSelectedKeys:在对应的 NioSocketChannel 上处理 read/write 事件
      • runAllTasks:再去以此循环处理任务队列中的其他任务在以上两个
    • 以上processSelectedKeys步骤中,会使用 Pipeline(管道),Pipeline 中引用了Channel,即通过 Pipeline 可以获取到对应的 Channel,Pipeline 中维护了很多的处理器(拦截处理器、过滤处理器、自定义处理器等)。

    在这里插入图片描述

  • 相关阅读:
    MySQl表的增删查改(聚合查询+联合查询)
    【2023年数学建模国赛】D题解题思路
    Word中标点符号单独一行
    学习SpringMVC的第四天
    uniapp使用scroll-view,设置横向,内容重叠的问题解决
    刷题之搜索二维矩阵(leetcode)
    J2EE项目部署与发布(Windows版本)
    Flink1.15源码解析--启动脚本----start-cluster.sh
    java毕业设计电子病历系统mybatis+源码+调试部署+系统+数据库+lw
    如何在国庆抓住收益红利?这家酒店集团最佳实践值得一看
  • 原文地址:https://blog.csdn.net/qq_44787816/article/details/126833167