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

相关文章
|
2月前
|
Java
网络 I/O:单 Selector 多线程(单线程模型)
网络 I/O:单 Selector 多线程(单线程模型)
|
1月前
|
人工智能 JSON 前端开发
【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)
【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)
|
13天前
|
设计模式 安全 Java
Java并发编程实战:使用synchronized关键字实现线程安全
【4月更文挑战第6天】Java中的`synchronized`关键字用于处理多线程并发,确保共享资源的线程安全。它可以修饰方法或代码块,实现互斥访问。当用于方法时,锁定对象实例或类对象;用于代码块时,锁定指定对象。过度使用可能导致性能问题,应注意避免锁持有时间过长、死锁,并考虑使用`java.util.concurrent`包中的高级工具。正确理解和使用`synchronized`是编写线程安全程序的关键。
|
2月前
|
Java Unix Linux
【Netty技术专题】「原理分析系列」Netty强大特性之Native transports扩展开发实战
当涉及到网络通信和高性能的Java应用程序时,Netty是一个强大的框架。它提供了许多功能和组件,其中之一是JNI传输。JNI传输是Netty的一个特性,它为特定平台提供了高效的网络传输。 在本文中,我们将深入探讨Netty提供的特定平台的JNI传输功能,分析其优势和适用场景。我们将介绍每个特定平台的JNI传输,并讨论其性能、可靠性和可扩展性。通过了解这些特定平台的JNI传输,您将能够更好地选择和配置适合您应用程序需求的网络传输方式,以实现最佳的性能和可靠性。
52 7
【Netty技术专题】「原理分析系列」Netty强大特性之Native transports扩展开发实战
|
22天前
|
NoSQL Redis
Netty实战:模拟Redis的客户端
Netty实战:模拟Redis的客户端
11 0
|
1月前
|
Java 数据处理
Java8的新特性parallelStream()的概念、对比线程优势与实战
parallelStream() 是 Java 8 中新增的一个方法,它是 Stream 类的一种扩展,提供了将集合数据并行处理的能力。普通的 stream() 方法是使用单线程对集合数据进行顺序处理,而 parallelStream() 方法则可以将集合数据分成多个小块,分配到多个线程并行处理,从而提高程序的执行效率。
43 3
|
2月前
|
安全 Java 开发者
Python多线程编程实战:提高程序执行效率的策略
Python多线程编程实战:提高程序执行效率的策略
120 1
|
2月前
|
消息中间件 安全 Java
多线程(初阶七:阻塞队列和生产者消费者模型)
多线程(初阶七:阻塞队列和生产者消费者模型)
30 0
|
3月前
|
缓存 NoSQL 安全
Redis 新特性篇:多线程模型解读
Redis 新特性篇:多线程模型解读
49 5
|
7月前
|
监控 Java Linux
由浅入深Netty基础知识NIO网络编程1
由浅入深Netty基础知识NIO网络编程
38 0