Netty实战与源码剖析(三)——Netty线程模型

简介: Netty实战与源码剖析(三)——Netty线程模型

1 线程模型基本介绍


不同的线程模式,对于程序的性能有很大的影响,Netty为何具有如此高的性能,很大程度上是得益于Netty采用的线程模型。


目前主流存在的线程模型有两种:


传统阻塞IO模型

Reactor模型

然而根据Reactor的数量和处理资源线程的数量不同,又可以将Reactor模型分为三种:


单Reactor 单线程

单Reactor 多线程

主从Reactor 多线程


Netty基于主从Reactor多线程模型做了一定的改进,其中主从Reactor多线程模型有多个Reactor。


1.1 传统阻塞IO模型


工作原理图:


939c8d954d324874ac5b725a9020f470.png

模型特点:


采用阻塞IO模式获取输入的数据

每个连接都要独立的线程来完成数据的输入、业务处理、数据的输出返回

问题分析:


当并发度很大,就会创建大量的线程,占用很大的系统开销

当连接创建后,如果当前线程暂时没有数据可读,该线程会阻塞在read操作,造成线程资源的浪费


解决方案:


基于IO复用模型:多个连接共用一个阻塞对象,应用程序只需要在一个阻塞对象等待,无需阻塞等待所有连接。当某个连接有数据可用时,操作系统通知应用程序,线程从阻塞状态返回,处理业务逻辑。


基于线程池复用线程资源:不必再为每个连接创建一个线程,将连接完成后的业务处理交给线程,这样可以使得线程池中的每一个线程都可以处理多个连接的业务逻辑。


1.2 Reactor模式


上述说的IO复用模型结合线程池机制,就形成了Reactor模式。


工作原理图:


image.png


模型特点:


Reactor模式是通过一个或多个输入同时传递给服务处理器的模式,基于事件驱动

服务端程序处理连接的多个请求,并把请求分派给相应的处理线程,故Reactor模式也叫Dispatcher模式

Reactor模式使用IO复用模型,监听事件,收到事件后,分发给某个线程或进程,这也是网络服务器高并发处理的关键


核心组件:


Reactor:其实就是上图中的ServiceHandler

Handler:其实就是上图中处理线程的EventHandler


1.3 单Reactor单线程模式


前面的博客中,Java NIO编程其实就是一种单Reactor单线程,Selector相当于Reactor,得到SelectKey后的操作其实就是在一个线程中完成的,这就是一个Handler。


优点:模型简单,无多线程、线程通信、上下文切换、锁竞争等问题


缺点


性能低,只用了一个线程,无法完全发挥多核CPU的性能

可用性低,线程若意外终止,或进入死循环,导致整个通信模块不可用


使用场景:客户端数量有限,业务处理快速等


1.4 单Reactor多线程模式


和单Reactor单线程模式比较类似,不同的地方在于,当Reactor收到事件,如果是连接事件,则交给一个特定的线程处理连接后的业务;如果不是连接时间,则由Reactor分发到不同的Handler,但Handler只负责相应事件,不做具体的业务处理,只是通过read读取数据后,交给worker线程池进行处理业务,worker线程池会分配一个线程来处理业务,并将结果返回给Handler,Handler再返回结果给客户端。


优点:充分利用多核CPU的处理能力


缺点


多线程数据共享和访问较为复杂,线程安全问题;

Reactor是单线程中运行的,处理所有的事件监听和相应,高并发下有性能瓶颈


1.5 主从Reactor多线程模式


Reactor主线程MainReactor对象通过select监听连接事件,收到连接事件后,则交给一个特定的线程处理连接后的业务;如果是其他事件,MainReactor会将事件分配给从线程的SubReactor对象,然后SubReactor将事件分发到不同的Handler,但Handler只负责相应事件,不做具体的业务处理,只是通过read读取数据后,交给worker线程池进行处理业务,worker线程池会分配一个线程来处理业务,并将结果返回给Handler,Handler再返回结果给客户端。


优点:父线程与子线程的数据交互简单,职责明确,父线程只需要接受新连接,子线程则完成后续的业务逻辑处理;父子线程数据交互简单,主线程只需要把非连接的事件传递给子线程,子线程无需返回数据


缺点:复杂度高


这种模型在许多项目中广泛使用,包括Nginx主从Reactor多进程模型,Memcached主从多线程,Netty主从多线程模型的支持。


2 Netty线程模型


如同所示:

image.png


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


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


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 中维护了很多的处理器(拦截处理器、过滤处理器、自定义处理器等)。

相关文章
|
6月前
|
存储 SQL 安全
Java 无锁方式实现高性能线程实战操作指南
本文深入探讨了现代高并发Java应用中单例模式的实现方式,分析了传统单例(如DCL)的局限性,并提出了多种无锁实现方案。包括基于ThreadLocal的延迟初始化、VarHandle原子操作、Record不可变对象、响应式编程(Reactor)以及CDI依赖注入等实现方式。每种方案均附有代码示例及适用场景,同时通过JMH性能测试对比各实现的优劣。最后,结合实际案例设计了一个高性能配置中心,展示了无锁单例在实际开发中的应用。总结中提出根据场景选择合适的实现方式,并遵循现代单例设计原则以优化性能和安全性。文中还提供了代码获取链接,便于读者实践与学习。
117 0
|
2月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
266 0
|
4月前
|
数据采集 消息中间件 并行计算
Python多线程与多进程性能对比:从原理到实战的深度解析
在Python编程中,多线程与多进程是提升并发性能的关键手段。本文通过实验数据、代码示例和通俗比喻,深入解析两者在不同任务类型下的性能表现,帮助开发者科学选择并发策略,优化程序效率。
283 1
|
7月前
|
算法 Java 容器
Netty源码—4.客户端接入流程
本文主要介绍了关于Netty客户端连接接入问题整理、Reactor线程模型和服务端启动流程、Netty新连接接入的整体处理逻辑、新连接接入之检测新连接、新连接接入之创建NioSocketChannel、新连接接入之绑定NioEventLoop线程、新连接接入之注册Selector和注册读事件、注册Reactor线程总结、新连接接入总结
|
7月前
|
安全 Java 调度
Netty源码—3.Reactor线程模型二
本文主要介绍了NioEventLoop的执行总体框架、Reactor线程执行一次事件轮询、Reactor线程处理产生IO事件的Channel、Reactor线程处理任务队列之添加任务、Reactor线程处理任务队列之执行任务、NioEventLoop总结。
|
7月前
|
安全 Java
Netty源码—2.Reactor线程模型一
本文主要介绍了关于NioEventLoop的问题整理、理解Reactor线程模型主要分三部分、NioEventLoop的创建和NioEventLoop的启动。
|
6月前
|
算法 Java 测试技术
深度优化OSS上传性能:多线程分片上传 vs 断点续传实战对比
本文深入解析对象存储服务(OSS)文件上传性能优化技术,重点探讨多线程分片上传与断点续传两种方案。通过理论分析、代码实现和性能测试,对比其在不同场景下的表现差异,并提供选型建议与最佳实践,助力提升大文件上传效率与稳定性。
544 0
|
6月前
|
数据采集 网络协议 前端开发
Python多线程爬虫模板:从原理到实战的完整指南
多线程爬虫通过并发请求大幅提升数据采集效率,适用于大规模网页抓取。本文详解其原理与实现,涵盖任务队列、线程池、会话保持、异常处理、反爬对抗等核心技术,并提供可扩展的Python模板代码,助力高效稳定的数据采集实践。
278 0

热门文章

最新文章