消息队列的网络模型详解:IO多路复用、Reactor模型、零拷贝

文章目录

  • 一、消息队列的网路模型拟解决问题
    • 单个请求性能优化
      • 1. 编解码速度
      • 2. 网络模块处理速度
    • 并发请求性能优化
      • 1. 高效的连接管理
      • 2. 快速处理高并发请求
      • 3. 大流量场景处理
  • 二、一些技术基础知识
    • 1. 基于多路复用技术管理 TCP 连接(提高性能)
      • (1)单条 TCP 连接的复用
      • (2)IO 多路复用技术
    • 2. 如何快速处理高并发请求——Reactor模型(提高性能)
      • (1)三个核心角色
        • Reactor(反应器/事件分发器)
        • Acceptor(连接处理器)
        • Handler(业务处理器)
      • (2)单 Reactor 单线程模式
        • 特点分析:
        • 优缺点对比:
      • (3)单 Reactor 多线程模式
        • 特点分析:
        • 工作流程:
        • 优缺点对比:
      • (4)主从 Reactor 多线程模式
        • 特点分析:
        • 工作流程:
        • 负载均衡策略:
        • 优缺点对比:
    • 3. Netty框架(提高稳定性)
    • 4. 零拷贝
  • 三、Kafka网络模型(Java NIO)
  • 四、RocketMQ网络模型(Netty)
  • 五、Pulsar网络模型(Netty)
  • 六、RabbitMQ网络模型
  • 七、消息队列网络模型总结

一、消息队列的网路模型拟解决问题

单个请求性能优化

1. 编解码速度

  • 选择高效的序列化协议(如 Protocol Buffers、MessagePack)
  • 优化编解码算法,减少 CPU 开销
  • 考虑使用零拷贝技术减少内存拷贝

2. 网络模块处理速度

  • 及时处理响应:确保业务线程处理完成后,网络模块能快速回包
  • 异步处理机制:避免阻塞主线程
  • 缓冲区管理:合理设置读写缓冲区大小

并发请求性能优化

1. 高效的连接管理

  • 连接池设计:复用 TCP 连接,减少连接建立/断开的开销
  • 连接生命周期管理:及时清理无效连接
  • 负载均衡:合理分配连接负载
  • 连接复用:支持多路复用技术(如 HTTP/2、gRPC)

2. 快速处理高并发请求

  • I/O 多路复用:使用 epoll/kqueue/IOCP 等高效 I/O 模型
  • 线程池设计:合理分配业务处理线程
  • 事件驱动架构:基于事件回调的非阻塞处理
  • 请求队列优化:高效的请求排队和调度机制

3. 大流量场景处理

  • 零拷贝技术:减少数据在用户态和内核态之间的拷贝
  • 内存池管理:预分配内存,减少 GC 压力
  • 批量处理:合并多个小请求进行批量处理
  • 流量控制:实现背压机制,防止系统过载

二、一些技术基础知识

1. 基于多路复用技术管理 TCP 连接(提高性能)

(1)单条 TCP 连接的复用

TCP 连接复用是指在一条 TCP 连接上传输多个独立的请求/响应,而不是为每个请求建立新的连接。
在这里插入图片描述

TCP 连接复用是指在一条 TCP 连接上传输多个独立的请求/响应,而不是为每个请求建立新的连接。能从一定程度上提高性能,缺点是在协议设计和编码实现的时候有额外开发工作量,而且近年随着异步 IO、IO 多路复用技术的发展,这种方案有点多余。因为语言特性、历史背景原因,RabbitMQ 用的就是这种方案。

(2)IO 多路复用技术

IO 多路复用技术,是指通过把多个 IO 的阻塞复用到同一个 selector 的阻塞上,让系统在单线程的情况下可以同时处理多个客户端请求。最大的优势是系统开销小,系统不需要创建额外的进程或者线程,降低了维护的工作量,也节省了资源。

目前支持 IO 多路复用的系统调用有 Select、Poll、Epoll 等,Java NIO 库底层就是基于 Epoll 机制实现的。

不过,即使用了这两种技术,单机能处理的连接数还是有上限的。

第一个上限是操作系统的 FD 上限,如果连接数超过了 FD 的数量,连接会创建失败。
第二个限制是系统资源的限制,主要是 CPU 和内存。频繁创建、删除或者创建过多连接会消耗大量的物理资源,导致系统负载过高。

2. 如何快速处理高并发请求——Reactor模型(提高性能)

Reactor模型是一种事件驱动的并发编程模型,主要用于处理高并发I/O操作。它的核心思想是:当有事件发生时,才进行处理,而不是主动轮询

事件类型
事件循环
连接事件
读事件
写事件
Reactor
事件分发器
Acceptor
连接处理器
Handler1
业务处理器
Handler2
业务处理器
Handler3
业务处理器
客户端1
客户端2
客户端3
新客户端连接

(1)三个核心角色

Reactor(反应器/事件分发器)
  • 职责:事件循环的核心,负责监听和分发事件
  • 功能
    • 使用 select/epoll/kqueue 等系统调用监听多个文件描述符
    • 当有事件发生时,将事件分发给对应的处理器
    • 管理事件注册和注销
  • 特点:单线程运行,负责事件的分发,不处理具体业务逻辑
Acceptor(连接处理器)
  • 职责:专门处理新连接事件
  • 功能
    • 接受新的客户端连接
    • 为每个新连接创建对应的 Handler
    • 将新连接注册到 Reactor 的事件监听中
  • 特点:只在有新连接时被调用
Handler(业务处理器)
  • 职责:处理具体的业务逻辑
  • 功能
    • 处理已建立连接的读写事件
    • 实现具体的业务逻辑
    • 处理数据编解码
  • 特点:每个连接对应一个 Handler 实例

(2)单 Reactor 单线程模式

单线程事件循环
主Reactor
单线程
Acceptor
连接处理
Handler1
业务处理
Handler2
业务处理
Handler3
业务处理
客户端1
客户端2
客户端3
特点分析:
  • 架构简单:只有一个 Reactor 线程,所有操作都在同一个线程中完成
  • 无并发问题:不存在线程安全问题,不需要加锁
  • 性能瓶颈:所有 Handler 都在同一个线程中执行,容易成为性能瓶颈
  • 适用场景:连接数较少,业务逻辑简单的场景
优缺点对比:
优点缺点
实现简单,易于理解单线程处理,性能有限
无线程安全问题无法充分利用多核CPU
资源消耗少一个Handler阻塞会影响其他连接
适合小规模应用不适合高并发场景

(3)单 Reactor 多线程模式

工作线程池
主线程
Handler1
业务处理
Handler2
业务处理
Handler3
业务处理
线程池
工作线程1
工作线程2
工作线程3
工作线程4
主Reactor
单线程
Acceptor
连接处理
客户端1
客户端2
客户端3
特点分析:
  • 职责分离:Reactor 只负责事件分发,Handler 在独立线程中处理业务逻辑
  • 并发处理:业务逻辑可以并发执行,提高处理能力
  • 线程安全:需要处理线程安全问题,Handler 之间可能需要同步
  • 资源管理:需要管理线程池,避免线程过多导致资源浪费
工作流程:
  1. Reactor 线程接收事件并分发
  2. Acceptor 处理新连接(仍在主线程)
  3. Handler 将业务逻辑提交到线程池
  4. 工作线程执行具体的业务处理
  5. 处理完成后,通过回调或消息队列返回结果
优缺点对比:
优点缺点
业务逻辑可以并发处理需要处理线程安全问题
充分利用多核CPU线程切换有一定开销
适合CPU密集型业务线程池管理复杂
响应性好内存占用相对较高

(4)主从 Reactor 多线程模式

业务处理线程池
子Reactor线程组
主线程
Handler1
Handler2
Handler3
Handler4
Handler5
Handler6
业务线程池
工作线程1
工作线程2
工作线程3
工作线程4
子Reactor1
读写处理
子Reactor2
读写处理
子Reactor3
读写处理
主Reactor
连接处理
Acceptor
连接分发
客户端1
客户端2
客户端3
特点分析:
  • 分层架构:主 Reactor 专门处理连接,子 Reactor 处理读写事件
  • 负载均衡:多个子 Reactor 可以负载均衡处理连接
  • 高并发:充分利用多核CPU,支持更高的并发连接数
  • 复杂管理:需要管理多个 Reactor 和线程池
工作流程:
  1. 主 Reactor 监听连接事件
  2. Acceptor 接受新连接,分配给某个子 Reactor
  3. 子 Reactor 负责该连接的后续读写事件
  4. Handler 处理具体业务逻辑,可提交到业务线程池
  5. 工作线程 执行CPU密集型业务处理
负载均衡策略:
  • 轮询分配:新连接轮流分配给子 Reactor
  • 最少连接:分配给连接数最少的子 Reactor
  • 哈希分配:根据客户端IP等特征哈希分配
优缺点对比:
优点缺点
支持超高并发连接架构复杂,实现困难
充分利用多核CPU调试和问题排查复杂
连接处理和读写处理分离内存占用较高
适合大规模应用需要精心调优参数

3. Netty框架(提高稳定性)

在 Java 中,网络编程的核心是一个基础的类库——Java NIO 库,它的底层是基于 Linux/Unix IO 复用模型 Epoll 实现的。如果我们要基于 Java NIO 库开发一个 Server,需要处理网络的闪断、客户端的重复接入、连接管理、安全认证、编解码、心跳保持、半包读写、异常处理等等细节,工作量非常大。

所以在消息队列的网络编程模型中,为了提高稳定性或者降低成本,选择现成的、成熟的 NIO 框架是一个更好的方案。

Netty是一个基于Java NIO的高性能网络应用框架,采用异步非阻塞的事件驱动架构,支持多种网络协议(HTTP、WebSocket、TCP、UDP等)。它的核心优势在于高性能、低延迟和高度可扩展性,通过零拷贝技术、高效的线程模型和模块化设计,能够轻松处理大量并发连接。Netty广泛应用于RPC框架、游戏服务器、聊天应用、代理服务器、API网关等场景,已成为Java网络编程的事实标准,被众多知名项目如gRPC、Dubbo、Elasticsearch等采用。

在这里插入图片描述

4. 零拷贝

看这篇:https://blog.csdn.net/Tracycoder/article/details/148957098

三、Kafka网络模型(Java NIO)

Kafka 的网络层没有用 Netty 作为底层的通信库,而是直接采用 Java NIO 实现网络通信。

在网络模型中,也是参照 Reactor 多线程模型,采用多线程、多 Selector 的设计。看整个网络层的结构图。Processor 线程和 Handler 线程之间通过 RequestChannel 传递数据,RequestChannel 中包含一个 RequestQueue 队列和多个 ResponseQueues 队列。每个 Processor 线程对应一个 ResponseQueue。

在这里插入图片描述

  • 具体流程上:
    • 一个 Acceptor 接收客户端建立连接的请求,创建 Socket 连接并分配给 Processor 处理。
    • Processor 线程把读取到的请求存入 RequestQueue 中,Handler 线程从 RequestQueue 队列中取出请求进行处理。
    • Handler 线程处理请求产生的响应,会存放到 Processor 对应的 ResponseQueue 中,Processor 线程从其对应的 ResponseQueue 中取出响应信息,并返回给客户端。

四、RocketMQ网络模型(Netty)

RocketMQ 采用 Netty 组件作为底层通信库,遵循 Reactor 多线程模型,同时又在 Reactor 模型上做了一些扩展和优化。

所以它的网络模型是 Netty 的网络模型,Netty 底层采用的是主从 Reactor 多线程模型,模型的原理逻辑跟前面讲到的主从 Reactor 多线程模型是一样的。

主从 Reactor 多线程模型的理论基础上,我们来分析一下 RocketMQ 中 NettyRemotingServer 的具体实现形式。

在这里插入图片描述

  • 具体流程上:
    • 一个 Reactor 主线程负责监听 TCP 网络连接请求,建立好连接,创建 SocketChannel,并注册到 Selector 上。RocketMQ 的源码中会自动根据 OS 的类型选择 NIO 和 Epoll,也可以通过参数配置,监听真正的网络数据。
    • 接收到网络数据后,会把数据传递给 Reactor 线程池处理。
    • 真正执行业务逻辑之前,会进行 SSL 验证、编解码、空闲检查、网络连接管理,这些工作在 Worker 线程池处理(defaultEventExecutorGroup)。
    • 处理业务操作,放在业务 Processor 线程池中执行。

五、Pulsar网络模型(Netty)

Pulsar基于Netty框架构建网络层,Netty底层使用操作系统的IO多路复用技术,底层也是基于I/O多路复用技术(自动选择最优,优先Epoll):

// Pulsar Broker 网络服务初始化
public class PulsarServer {private final EventLoopGroup bossGroup;private final EventLoopGroup workerGroup;public PulsarServer(PulsarService pulsar) {// 根据操作系统选择最优的 EventLoopGroupif (Epoll.isAvailable()) {// Linux: 使用 EpollEventLoopGroup (epoll)this.bossGroup = new EpollEventLoopGroup(1);this.workerGroup = new EpollEventLoopGroup(pulsar.getConfiguration().getNumIOThreads());} else {// Windows/macOS: 使用 NioEventLoopGroup (select/kqueue)this.bossGroup = new NioEventLoopGroup(1);this.workerGroup = new NioEventLoopGroup(pulsar.getConfiguration().getNumIOThreads());}}
}

与RocketMQ类似,也采用主从Reactor多线程模式(多Reactor多线程)

六、RabbitMQ网络模型

RabbitMQ底层基于select/poll,以及Erlang的Actor网络模型,其中,轻量级进程切换开销极小:

┌─────────────────────────────────────────────────────────────┐
│                    Erlang Actor Model                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │   Process   │  │   Process   │  │   Process   │          │
│  │   (Actor)   │  │   (Actor)   │  │   (Actor)   │          │
│  │             │  │             │  │             │          │
│  │ ┌─────────┐ │  │ ┌─────────┐ │  │ ┌─────────┐ │          │
│  │ │ Message │ │  │ │ Message │ │  │ │ Message │ │          │
│  │ │ Queue   │ │  │ │ Queue   │ │  │ │ Queue   │ │          │
│  │ └─────────┘ │  │ └─────────┘ │  │ └─────────┘ │          │
│  │             │  │             │  │             │          │
│  │ ┌─────────┐ │  │ ┌─────────┐ │  │ ┌─────────┐ │          │
│  │ │ Process │ │  │ │ Process │ │  │ │ Process │ │          │
│  │ │ Logic   │ │  │ │ Logic   │ │  │ │ Logic   │ │          │
│  │ └─────────┘ │  │ └─────────┘ │  │ └─────────┘ │          │
│  └─────────────┘  └─────────────┘  └─────────────┘          │
│         │                │                │                 │
│         ▼                ▼                ▼                 │
│  ┌────────────────────────────────────────────────────────┐ │
│  │              Scheduler Thread Pool                     │ │
│  └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

七、消息队列网络模型总结

特性RabbitMQKafkaRocketMQPulsar
语言ErlangJavaJavaJava
网络模型ActorReactorReactorReactor
IO多路复用select/pollepollepollepoll
零拷贝
并发模型轻量级进程线程池线程池线程池
协议AMQP自定义自定义自定义

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

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

相关文章

【生成模型】【模型介绍】(一)视频生成Wan2.1速度质量简单评测

基础模型:FramePack https://github.com/kijai/ComfyUI-FramePackWrapper huggingface-cli download Comfy-Org/HunyuanVideo_repackaged --local-dir Comfy-Org/HunyuanVideo_repackaged --resume-download huggingface-cli download Comfy-Org/sigclip_vision_3…

微信小程序之滑块scroll-view

我们要做的东西&#xff1a; 滑块的视频 我们先做个基本的图片和文字(wxm;)&#xff1a; <scroll-view><view class"scrollItem"><image src"https://bkimg.cdn.bcebos.com/pic/fc1f4134970a304e251fd88e8191b086c9177f3ef634?x-bce-processim…

如何写出优秀的单元测试?

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 写出优秀的单元测试需要考虑以下几个方面&#xff1a; 1. 测试用例设计 测试用例应该覆盖被测试代码的不同场景和边界情况&#xff0c;以尽可能发现潜在的问题。…

Python LangChain 3.0 详解:重构大模型应用开发范式

引言 在人工智能技术日新月异的今天&#xff0c;大模型应用开发框架的迭代速度直接决定了AI落地的效率。LangChain作为这一领域的领军者&#xff0c;于2024年正式发布3.0版本&#xff0c;通过架构重构与功能扩展&#xff0c;为开发者提供了更强大的工具集。本文将深入解析Lang…

Java模板设计模式详解

以下是Java模板设计模式的详细解析&#xff1a; 一、核心定义 模板模式&#xff08;Template Method Pattern&#xff09;是一种‌行为型设计模式‌&#xff0c;通过定义算法骨架并允许子类重写特定步骤&#xff0c;实现代码复用与扩展。其核心在于控制‌流程标准化‌&#x…

Word 中批量转换 LaTeX 公式为标准数学格式的终极方法(附宏设置教程)

在学术写作中&#xff0c;我们常常需要将 LaTeX 格式的公式插入到 Word 文档中。但如果你有一大段公式使用 $...$ 或 LaTeX 命令&#xff0c;手动转换无疑非常耗时。本文将介绍一种“一键转换所有 LaTeX 公式为 Word 数学公式”的方法&#xff0c;只需设置一次宏&#xff0c;后…

linux上查看文件系统类型

假设 有文件系统mount在/data-pool&#xff1a; df -h ./ 文件系统 大小 已用 可用 已用% 挂载点 data-pool 1.5T 345M 1.5T 1% /data-pool如何查看 data-pool 这个文件系统的文件系统类型&#xff08;格式&#xff09;&#xff0c;比如是 ext4、btrfs、z…

Android14-HAL分析

文章目录 一、HAL综述二、Android各版本HAL的演进三、传统HAL(< Android7)四、HIDL HAL(Android8-10)1、参考资料2、概述2、架构3、实现一个HIDL HAL1&#xff09;HIDL的开发流程2&#xff09;HIDL HAL的语法3&#xff09;创建HAL接口&生成impl库4&#xff09;Service实…

【WebSocket】学习总结

是一种协议&#xff1b; 作用与Web应用程序和服务端之间&#xff1b; 实时的、双向的&#xff1b; 通过单一的TCP提供了持久化连接&#xff1b; 优势&#xff1a; 实时、双向、可以减少网络的负载&#xff1b; 劣势&#xff1a; 需要客户端和服务端双方都支持&#xff1b; 连续…

“组件协作”模式之策略模式

目录 策略模式引例动机 Motivation模式定义结构要点总结 策略模式 引例 税务计算系统&#xff0c;根据各个国家的税法&#xff0c;进行税务计算。各个国家税法规定差别很大&#xff0c;需对应进行相应的实现。 常规解耦前写法 使用if-else语句或switch-case语句进行结构化分…

VS Git巨坑 切换分支失败导致原分支被修改

VS2013Git 首先当前分支&#xff08;分支A&#xff09;的变更已经提交&#xff0c;应该可以正常切换分支。 想切换到一个比较老的分支B&#xff08;跟当前分支存在较大差异&#xff0c;增加了很多文件&#xff09;&#xff0c;VS中提示切换失败&#xff0c;当前分支仍然是分支A…

uniapp页面间通信uni.$on与通过uni.navigateTo中eventChannal的方式的区别

背景。无意间开发uniapp程序用到了页面跳转数据传递的两种方式。但各用于什么场景&#xff0c;有什么区别记录一下。大模型给的内容较多&#xff0c;贴出一些结论。eventChannel文档链接uni.$emit文档链接 页面跳转而非全局事件通知&#xff0c;优先选择eventChanel的方式。 首…

理解对话上下文

1、pom依赖 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><langchain4j.version>…

【Java高频面试问题】数据库篇

【Java高频面试问题】数据库篇 为什么MySQL选择B树作为索引一、B 树的优势特性二、与常见数据结构的对比 索引优化一、索引类型及使用场景二、索引优化核心策略1. 避免索引失效场景2. 性能优化实践3. 表结构与架构优化 三、高频面试问题参考答案总结&#xff1a;面试核心要点 数…

《Whisper:开启语音识别新时代的钥匙》

Whisper 模型:技术革新的基石 在当今科技飞速发展的时代,自动语音识别(ASR)技术作为人工智能领域的关键分支,正深刻地改变着人们的生活与工作方式。从智能语音助手到实时字幕生成,从语音交互设备到智能客服系统,ASR 技术无处不在,为人们带来了前所未有的便利与效率提升…

关于 pdd:anti_content参数分析与逆向

一、逆向目标 目标&#xff1a;获取pdd商品列表接口数据网址&#xff1a;aHR0cHM6Ly93d3cucGluZHVvZHVvLmNvbS9ob21lL2hvbWUv 二、逆向步骤 2.1 anti_content 入口定位 >1 找到需加密参数 >2 全局搜索定位 这里只出来一个结果&#xff0c;很明显&#xff0c;点进去。 …

限流系列之五:TDMQ RabbitMQ Serverless 版限流机制深度解析与实践指南

导语 分布式集群限流是保障云服务高可用性的核心技术手段&#xff0c;其意义不仅在于防止系统过载&#xff0c;更是构建弹性架构、优化资源效率、实现业务可持续性的关键策略。未来&#xff0c;随着边缘计算和 Serverless 的普及&#xff0c;限流技术将进一步与底层基础设施深…

官方链接内容整理的 Spark-TTS Windows 安装完整流程

官方链接内容整理的 Spark-TTS Windows 语音克隆 安装完整流程 官方链接内容整理的 Spark-TTS Windows 安装完整流程&#xff1a; Spark TTS&#xff1a;基于大型语言模型的文本转语音模型 Spark-TTS 是一个先进的文本转语音系统&#xff0c;利用大型语言模型&#xff08;LLM…

Spring Cloud Config动态刷新实战指南

以下是利用 Spring Cloud Config + Bus 实现配置动态刷新的完整步骤和原理说明: 一、核心原理 消息总线机制 Bus 通过消息代理(如 RabbitMQ/Kafka)建立公共 Topic(默认 springCloudBus),当配置变更时,任一服务触发刷新请求,消息会广播至所有监听该 Topic 的服务实例,实…

Linux 修改密码教程

Linux 修改密码教程 Linux 系统中修改密码是非常常见的管理操作&#xff0c;无论是修改当前用户密码还是其他用户的密码&#xff0c;通常都可以通过终端完成。本文将详细介绍如何在 Linux 系统中修改密码&#xff0c;并包括修改其他用户密码的方法。 1. 修改当前用户密码 修改…