Java 面试宝典:请说下你对 Netty 中Reactor 模式的理解

大家好,我是大明哥,一个专注「死磕 Java」系列创作的硬核程序员。
本文已收录到我的技术网站:https://skjava.com。有全网最优质的系列文章、Java 全栈技术文档以及大厂完整面经


回答

Reactor 模式是一种高效处理并发网络事件的设计模式,它通过一组 Reactor 线程(事件循环组)来监听和分发网络事件(如连接、读取、写入),并结合非阻塞 I/O 和用户定义的事件处理器来实现。

Reactor 模式的核心思想是把响应 IO 事件和业务处理进行分离。它通过一个或者多个线程监听 I/O 事件,将已经准备就绪的 I/O 事件分发给业务线程去处理。其核心组件有三个:

  • Reactor 组件:这是 Reactor 模式的核心。Reactor 组件负责监听和分发事件。在一个无限循环中,它等待 I/O 事件的到来,然后将这些就绪的 I/O 事件快速分发给相应的处理程序。在 Netty 中,这通常对应于 EventLoop 组件。
  • Acceptor 组件:请求连接器。Reactor 组件接收到 client 连接事件后,会将其转发给 Acceptor,Acceptor 则会接受 Client 的连接,建立对应的Handler,并向 Reactor注册此Handler。
  • Handler 组件:求处理器,负责具体事件的处理程序。当 Reactor 组件将事件分发给它们时,它们负责处理这些事件。在 Netty 中,这些处理器通常是用户自定义的 ChannelHandler,用于处理特定的事件,如接收数据、异常处理等。

在 Reactor 模式中,主要有三种模型:

  • 单 Reactor 单线程模型。
  • 多线程 Reactor 模型。
  • 主从多 Reactor 多线程模型。

详解

单 Reactor 单线程模型

单线程 Reactor 模型,即所有的 I/O 处理和业务逻辑都在同一个线程(即 Reactor 线程)中执行。

处理流程如下

  • Reactor 通过 Select 监听 I/O 事件,收到事件后由 Dispatch 来分发。
  • 如果是建立连接事件,则由 Acceptor 进行处理,Acceptor 会通过 accept 方法获取链接,并创建一个 Handler 对象来处理后续的响应事件。
  • 如果不是建立连接事件,则将该事件交由当前连接的 Handler 来处理。Handler 按照 read —> 业务处理 —> send 的流程来完成整个事件。

优点

该模型是将所有处理逻辑放在一个线程中实现,模型简单,没有多线程、进程通信、竞争的问题

缺点

由于只有一个线程,无法充分利用多核CPU 的性能,性能堪忧。同时Handler 在处理某个连接上的业务时,整个进程无法处理其他连接事件,很容易导致性能瓶颈。

还有一个比较严重的可靠性问题,如果线程意外终止,或者进入死循环,则会导致整个线程都无法接受和处理事件了,造成节点故障。

单 Reactor 多线程

单线程存在性能瓶颈,那我们就引入多线程方案。

多线程 Reactor 模型,它将处理 I/O 就绪时间的线程和处理业务逻辑 Handler的线程分开了,每个 Handler 由一个独立的线程来处理。

Reactor 接受请求后,根据请求类型来进行分发,分发逻辑与单Reactor单线程模型一样,不同之处在于单 Reactor 多线程 的 Handler 不再进行业务处理了,它只负责接受和发送:Handler接受数据后,会将数据发送给 Worker 线程池中的线程处理,该线程才是处理业务的真正线程,线程将业务处理完成后,将数据发送给 Handler,由 Handler 再 send 出去。

优点

由于 Handler 使用了多线程模式,则可以利用充分利用CPU的性能。

缺点

Handler使用多线程模式,则会涉及到数据共享的问题,需要考虑互斥,实现肯定比单Reactor单线程模式复杂一些。但是在实际开发过程中,我们一般都会让业务处理是无状态的,一般不会用共享变量,所以在大多数业务场景中 Handler 的开发并不会复杂太多。

单Reactor,一个线程处理事件监听、分发、响应,对于高并发场景,容易造成性能瓶颈。

多 Reactor 多线程模型

单Reactor多线程模式虽然解决了 Handler 单线程的性能问题,但是 Reactor 还是单线程的,对于高并发场景还是会有性能瓶颈,所以需要对 Reactor 也调整为多线程模式

  • 主线程中的 MainReactor 对象通过 select 监听事件,接收到事件后通过 Dispatch 进行分发,如果事件类型为建立连接则将事件分发给 Acceptor 进行连接建立
  • 如果收到的事件不是连接,则他将事件分发个某个 SubReactor,SubrReactor 将连接加入到连接队列进行监听,并创建 Handler 进行各种事件处理
  • 如果有新的事件发生,SubReactor 则会调用当前连接的 Handler 来进行处理。Handler 通过 read 读取数据后,将数据发送给 Worker 线程进行处理,Worker 线程池则会分配线程进行业务处理,处理完成后返回结果,Handler 接受结果后,通过 send 发送给客户端

优点

该模式主线程和子线程分工明确,主线程只负责接收新连接,子线程负责完成后续的业务处理,同时主线程和子线程的交互也很简单,子线程接收主线程的连接后,只管业务处理即可,无须关注主线程

缺点

模型复杂。

这种模式适用于高并发场景,广泛运用于各种项目中,如大名鼎鼎的Netty。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/297012.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大商创多用户商城系统 多处SQL注入漏洞复现

0x01 产品简介 大商创多用户商城系统是一个功能强大、灵活多变的新零售电商系统服务商。该系统支持平台自营和商家入驻,实现多元化经营模式,能够全面整合供应商、生产商、经销商和消费者等产业链资源,提高产品多样性,加快资金流动速度,并有助于减少不必要的成本输出。 0…

Python学习笔记-Flask接收post请求数据并存储数据库

1.引包 from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy 2.配置连接,替换为自己的MySQL 数据库的实际用户名、密码和数据库名 app Flask(__name__) #创建应用实列 app.config[SQLALCHEMY_DATABASE_URI] mysqlpymysql://ro…

数据结构算法题(力扣)——链表

以下题目建议大家先自己动手练习,再看题解代码。这里只提供一种做法,可能不是最优解。 1. 移除链表元素(OJ链接) 题目描述:给一个链表的头节点 head 和一个整数 val ,删除链表中所有满足值等于 val 的节点…

【Python系列】Python中的YAML数据读取与解析

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

WebSocket用户验证

在WebSocket中,如何携带用户的验证信息 一、在OnMessage中进行验证 客户端在连接到服务器后,客户端通过发送消息,服务器端在OnMessage方法中,进行信息验证,这种方式需要将用户身份验证及接收用户消息进行混合处理&am…

Docker实战教程 第2章 Docker基础

3-1 Docker介绍 什么是Docker 虚拟化,容器 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上&…

VSCODE目录树缩进调整

VSCode默认的缩进太小了,简直看不出来,很容易弄混目录。在设置里修改就行了。 修改后效果:

Netty经典32连问

文章目录 1、Netty是什么,它的主要特点是什么?2、Netty 应用场景了解么?3、Netty 核心组件有哪些?分别有什么作用?4、Netty的线程模型是怎样的?如何优化性能?5、EventloopGroup了解么?和 Event…

基于springboot+vue实现的小区物业管理系统

作者主页:Java码库 主营内容:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】:Java 【框架】:spring…

蓝桥杯 - 受伤的皇后

解题思路: 递归 回溯(n皇后问题的变种) 在 N 皇后问题的解决方案中,我们是从棋盘的顶部向底部逐行放置皇后的,这意味着在任何给定时间,所有未来的行(即当前行之下的所有行)都还没…

如何在pgAdmin中用替换的值更新jsonb列?(二)

上一篇提到怎么替换jsonb,链接如下: 如何在pgAdmin中用替换的值更新jsonb列?-CSDN博客 那么当jsonb嵌套jsonb应该怎么替换呢?像这样,类型依然是jsonb,只不过嵌套一层,JsonData:&qu…

GDPU 竞赛技能实践 天码行空6

📖 敌兵布阵 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工…

统计子矩阵(前缀和+双指针)

题目描述 给定一个 N M 的矩阵 A,请你统计有多少个子矩阵 (最小 1 1,最大 N M) 满足子矩阵中所有数的和不超过给定的整数 K? 输入格式 第一行包含三个整数 N, M 和 K. 之后 N 行每行包含 M 个整数,代表矩阵 A. 输出格式 一个整数…

MySQL InnoDB引擎

InnoDB的逻辑存储结构如下图所示: 存储结构 表空间 表空间是InnoDB存储引擎逻辑结构的最高层, 如果用户启用了参数 innodb_file_per_table(在8.0版本中默认开启) ,则每张表都会有一个表空间(xxx.ibd),一个…

MySQL 索引底层探索:为什么是B+树?

MySQL 索引底层探索:为什么是B树? 1. 由一个例子总结索引的特点2. 基于哈希表实现的哈希索引3. 高效的查找方式:二分查找4. 基于二分查找思想的二叉查找树5. 升级版的BST树:AVL 树6. 更加符合磁盘特征的B树7. 不断优化的B树&#…

Tailscale:随时随地远程和使用服务器

文章目录 Tailscale是什么?Tailscale能做什么?1、传输文件2、远程开发3、代理 Tailscale怎么用?Windows下安装OpenSSH在线安装离线安装连接SSH服务器 Reference相关阅读 彩蛋:Pycharm远程连接服务器并运行代码 Tailscale是什么&am…

【MySQL】数据库的基本操作

目录 一、数据库的库操作 二、数据库的表操作 一、数据库的库操作 数据库的创建 create database (if not exists) 库名 这里的if not exists 是一个判断用的,如果数据库存在,就不执行语句,如果数据库不存在,则执行该语句。 创建…

npm install node-sass报错

前言 在使用 node-sass 时,你可能会遇到安装 node-sass 时出现各种错误的情况。在本文中,我们将探讨一些常见的 node-sass 安装错误,以及如何解决它们。 无论你是初学者还是有经验的开发者,本文都将为你提供有用的信息和技巧&…

PHP在线加密系统网站源码

源码介绍 PHP在线加密系统网站源码,这个是sg的加密,免费可用(目前)并不会收费 源码说明:下载直接上传即可 下载地址 蓝奏云下载:https://wfr.lanzout.com/i6c331togiji

路由Vue-Router使用

Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。 介绍 | Vue Router (vuejs.org) 1. 安装 npm install vue-router4 查看安装好的vue-router 2. 添加路由 新建views文件夹用来存放所有的页面,在…