滴滴面试:谈谈你对Netty线程模型的理解?
Netty 线程模型是指 Netty 框架为了提供高性能、高并发的网络通信,而设计的管理和利用线程的策略和机制。
Netty 线程模型被称为 Reactor(响应式)模型/模式,它是基于 NIO 多路复用模型的一种升级,它的核心思想是将 IO 事件和业务处理进行分离,使用一个或多个线程来执行任务的一种机制。
1.Reactor三大组件
Reactor 包含以下三大组件:

其中:
- Reactor(反应器):Reactor 负责监听和分发事件,它是整个 Reactor 模型的调度中心。Reactor 监视一个或多个输入通道,如监听套接字上的连接请求或读写事件。当检测到事件发生时,Reactor 会将其分发给预先注册的处理器(Handler)进行处理。在 Netty 中,这个角色经常是由 EventLoop 或其相关的 EventLoopGroup 来扮演,它们负责事件的循环处理、任务调度和 I/O 操作。
- Acceptor(接收器):用于处理 IO 连接请求。当 Reactor 检测到有新的客户端连接请求时,会通知 Acceptor,后者通过 accept() 方法接受连接请求,并创建一个新的 SocketChannel(在 Netty 中是 Channel)来表示这个连接。随后,Acceptor 通常会将这个新连接的 Channel 注册到 Worker Reactor 或 EventLoop 中,以便进一步处理该连接上的读写事件。
- Handlers(处理器):Handlers 负责具体的事件处理逻辑,即执行与事件相关的业务操作。在 Netty 中,Handler 是一个或多个 ChannelHandler 的实例,它们形成一个责任链(ChannelPipeline),每个 Handler 负责处理一种或一类特定的事件(如解码、编码、业务逻辑处理等)。数据或事件在 ChannelPipeline 中从一个 Handler 传递到下一个,直至处理完毕或被消费。Handler 可以分为入站(inbound)和出站(outbound)两种,分别处理流入的数据或流出的数据。
2.Reactor三大模型
Reactor 模式支持以下三大模型:
- 单线程模型
- 多线程模型
- 主从多线程模型
具体内容如下。
2.1 单线程模型
在单线程模型中,所有的事件处理操作都由单个 Reactor 实例在单个线程下完成。Reactor 负责监控事件、分发事件和执行事件处理程序(Handlers),如下图所示:

单线程模型的实现 Demo 如下:
// 假设有一个单线程的Reactor,负责监听、接收连接、读写操作
class SingleThreadReactor {
EventLoop eventLoop; // 单个事件循环线程
SingleThreadReactor() {
eventLoop = new EventLoop(); // 初始化单个事件循环
}
void start(int port) {
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.socket().bind(new InetSocketAddress(port)); // 绑定端口
eventLoop.execute(() -> { // 在事件循环中执行
while (true) {
SocketChannel clientSocket = serverSocket.accept(); // 接受连接
if (clientSocket != null) {
handleConnection(clientSocket); // 处理连接
}
}
});
eventLoop.run(); // 启动事件循环
}
void handleConnection(SocketChannel clientSocket) {
// 读写操作,这里简化处理
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (clientSocket.read(buffer) > 0) {
// 处理读取的数据
buffer.flip();
// 假设处理数据逻辑...
buffer.clear();
}
// 写操作逻辑类似
}
}
优缺点分析
- 优点:简单、线程安全性好、适合编写简单的网络应用。
- 缺点:处理能力受限于单个线程的处理能力,无法充分利用多核 CPU,可能会影响性能。
2.2 多线程模型
在多线程模型中,连接 Acceptor 和业务处理(Handlers)是由不同线程分开执行的,其中 Handlers 是由线程池(多个线程)来执行的,如下图所示:

多线程模型的实现 Demo 如下:
// 假设有两个线程,一个用于监听连接,一个用于处理连接后的操作
class MultiThreadReactor {
EventLoop acceptLoop;
EventLoop workerLoop;
MultiThreadReactor() {
acceptLoop = new EventLoop(); // 接收连接的线程
workerLoop = new EventLoop(); // 处理连接的线程
}
void start(int port) {
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.socket().bind(new InetSocketAddress(port));
acceptLoop.execute(() -> { // 在接受线程中监听
while (true) {
SocketChannel clientSocket = serverSocket.accept();
if (clientSocket != null) {
workerLoop.execute(() -> handleConnection(clientSocket)); // 将新连接交给工作线程处理
}
}
});
acceptLoop.run(); // 启动接受线程
workerLoop.run(); // 启动工作线程
}
// handleConnection 方法与单线程模型中的相同
}
优缺点分析
- 优点:此模式可以提高并发性能,充分利用多核 CPU,并且保持简单的编程模型。
- 缺点:多线程数据共享和数据同步比较复杂,并且 Reactor 需要处理所有事件监听和响应,在高并发场景依然会出现性能瓶颈。
2.3 主从多线程模型
主从多线程模型是一个主 Reactor 线程加多个子 Reactor 子线程,以及多个工作线程池来处理业务的,如下图所示:

主从多线程模型的实现 Demo 如下:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class MainReactorModel {
public static void main(String[] args) {
// 主Reactor,用于接受连接
EventLoopGroup bossGroup = new NioEventLoopGroup();
// 从Reactor,用于处理连接后的读写操作
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
// 在这里添加业务处理器,如解码器、编码器、业务逻辑处理器
ch.pipeline().addLast(new MyBusinessHandler());
}
});
ChannelFuture future = bootstrap.bind(8080).sync();
System.out.println("Server started at port 8080");
future.channel().closeFuture().sync(); // 等待服务器关闭
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
优缺点分析
- 优点:可以充分利用多核 CPU 的资源,提高系统的整体性能和并发处理能力。
- 缺点:模型相对复杂,实现和维护成本较高。
课后思考
NioEventLoop 是如何实现的?它能够保证 Channel 操作的线程安全吗?为什么?
本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。
滴滴面试:谈谈你对Netty线程模型的理解?的更多相关文章
- Netty系列之Netty线程模型
Reference: http://www.infoq.com/cn/articles/netty-threading-model 1. 背景 1.1. Java线程模型的演进 1.1.1. 单线程 ...
- 彻底搞懂 netty 线程模型
编者注:Netty是Java领域有名的开源网络库,特点是高性能和高扩展性,因此很多流行的框架都是基于它来构建的,比如我们熟知的Dubbo.Rocketmq.Hadoop等.本文就netty线程模型展开 ...
- eventloop & actor模式 & Java线程模型演进 & Netty线程模型 总结
eventloop的基本概念可以参考:http://www.ruanyifeng.com/blog/2013/10/event_loop.html Eventloop指的是独立于主线程的一条线程,专门 ...
- Netty线程模型
一.Reactor模型 1.单线程模型 Reactor单线程模型,指的是所有的IO操作都在同一个NIO线程上面完成,NIO线程的职责如下: 1)作为NIO服务端,接收客户端的TCP连接: 2)作为NI ...
- Netty 线程模型
一.线程模型概述 线程模型表明了代码的执行方式.从最开始的使用单线程,后来出现了多线程,之后是线程池.当有要执行的任务时,任务会被传到线程池,从线程池中获得空闲的线程来执行任务,执行完了后会将线程返回 ...
- Netty源码死磕一(netty线程模型及EventLoop机制)
引言 好久没有写博客了,近期准备把Netty源码啃一遍.在这之前本想直接看源码,但是看到后面发现其实效率不高, 有些概念还是有必要回头再细啃的,特别是其线程模型以及EventLoop的概念. 当然在开 ...
- Java后端进阶-网络编程(Netty线程模型)
前言 我们在使用Netty进行服务端开发的时候,一般来说会定义两个NioEventLoopGroup线程池,一个"bossGroup"线程池去负责处理客户端连接,一个"w ...
- Netty 线程模型(Reactor 线程模型)
更多内容,前往个人博客 当说到 Netty 线程模型的时候,一般首先会想到经典的 Reactor 线程模型,尽管不同的 NIO 框架对于 Reactor 模式的实现存在差异,但本质上还是遵循了 Rea ...
- Reactor三种线程模型与Netty线程模型
文中所讲基本都是以非阻塞IO.异步IO为基础.对于阻塞式IO,下面的编程模型几乎都不适用 Reactor三种线程模型 单线程模型 单个线程以非阻塞IO或事件IO处理所有IO事件,包括连接.读.写.异常 ...
- Netty核心概念(8)之Netty线程模型
1.前言 第7节初步学习了一下Java原本的线程池是如何工作的,以及Future的为什么能够达到其效果,这些知识对于理解本章有很大的帮助,不了解的可以先看上一节. Netty为什么会高效?回答就是良好 ...
随机推荐
- 简单介绍 Vue 3.0 项目创建
一.前期转杯 确保电脑上已安装 node.js. 可通过命令 npm --version进行查询,如果展示了版本号,则说明已安装,若提示 npm 不是有内部或外部命令,也不是可运行的程序,则说明未安装 ...
- Webpack Proxy工作原理?为什么能解决跨域?
一.是什么 webpack proxy,即webpack提供的代理服务 基本行为就是接收客户端发送的请求后转发给其他服务器 其目的是为了便于开发者在开发模式下解决跨域问题(浏览器安全策略限制) 想要实 ...
- react中<link>和<navlink>区别
两者都是实现路由的跳转.但 点击<Link>时,url会更新,组件会被重新渲染,但是页面不会重新加载...使用to链接组件时,它的值既可是字符串,也可以是location对象(包含path ...
- 暑期集训 Day9 —— 模拟赛复盘
${\color{Green} \mathrm{Problem\ 1 :大河的序列 }} $ 巨思维... 其实只需要输出序列 max 即可. 死因: \({\tiny 去你的}\) 快速幂 int ...
- 好的 MySQL 兼容性可以做到什么程度? PolarDB-X 如何做生态兼容
简介: 2003 年淘宝网成立之后,业务飞速发展,其后台架构也进行了多次迭代.2009 年之前,淘宝网后台的数据库架构是经典的 IOE 组合.IOE 是指 IBM 的小型机. Oracle 的数据库加 ...
- OpenYurt 深度解读:如何构建 Kubernetes 原生云边高效协同网络?
作者 | 郑超 导读:OpenYurt 是阿里巴巴开源的云边协同一体化架构,与同类开源方案相比,OpenYurt 拥有可实现边缘计算全场景覆盖的能力.在之前的一篇文章中,我们介绍了 OpenYurt ...
- 云原生数据仓库AnalyticDB支撑双11,大幅提升分析实时性和用户体验
简介:2021年双十一刚刚落幕,已连续多年稳定支持双十一大促的云原生数据仓库AnalyticDB,今年双十一期间仍然一如既往的稳定.除了稳定顺滑的基本盘之外,AnalyticDB还有什么亮点呢?下面 ...
- Flink on Zeppelin 流计算处理最佳实践
简介: 欢迎钉钉扫描文章底部二维码进入 EMR Studio 用户交流群 直接和讲师交流讨论~ 点击以下链接直接观看直播回放:https://developer.aliyun.com/live/247 ...
- dotnet CBB 为什么决定推送 Tag 才能打包
通过推送 Tag 才打 NuGet 包的方法的作用不仅仅是让打包方便,让打包这个动作可以完全在本地执行,无需关注其他系统的使用步骤.更重要的是可以强制每个可能被安装的 NuGet 包版本都能有一个和他 ...
- 将Go开发的代码部署到k8s集群
一.在服务器上编译go程序 1.1 编译go语言程序 # 安装go yum install go -y mkdir /root/test && cd /root/test # 设置代理 ...