【Alibaba中间件技术系列】「RocketMQ技术专题」带你一起去探索RocketMQ服务架构的线程模型分析

本文涉及的产品
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
注册配置 MSE Nacos/ZooKeeper,118元/月
性能测试 PTS,5000VUM额度
简介: 【Alibaba中间件技术系列】「RocketMQ技术专题」带你一起去探索RocketMQ服务架构的线程模型分析

前言介绍


RocketMQ 是个消息服务器,也是个网络服务器。接下来我们将从网络 IO 模型,线程模型,看看 RocketMQ 是如何设计的。




IO 模型


RocketMQ 使用了 Netty 作为网络通信框架,自然而然使用了 Reactor 模型,或者说 Select 模型、Epoll 模型。即一个线程管理 N 个 Socket 的模式,此模式可管理海量连接,基本是所有网络服务器的首选。



配置相关的RocketMQ的配置


RocketMQ的Boss线程数为 1, Worker 线程数为 CPU * 2.

在说线程模型之前,先看看 RocketMQ 如何设计 Server 接口的。

image.png

RemotingService作为顶层接口,定义了 启动和关闭,另外还有注册 RPC 钩子,职责简单。他的两个子接口 RemotingServer 和 RemotingClient 各自增加了自己的抽象接口。


  • Server 专属的 localListenPort 和 getProcessorPair
  • Client 专属的 getNameServerAddressList 等


注意:两者都有 invokeSync 方法,但,参数不同,这也是因为他们自身的角色不同所影响的。


至于NettyRemotingAbstract 抽象类,这只是个简单的”抽取重复代码”的“简单操作”。

再下面,就是具体实现类,每个类,都有内部类,都是Netty各种Handler 的实现:

image.png

  • NettyConnectManageHandler 负责处理 注册,连接,异常等事件,继承自 ChannelDuplexHandler。
  • NettyServerHandler 则是关键的业务处理类,处理真正的 Msg,继承自 SimpleChannelInboundHandler。
  • HandshakeHandler 负责处理握手程序,这里就不解释了。


以上 3 个是 Server 端的 Handler,都是NettyRemotingServer的内部类。



线程模型


NettyServerHandler作为处理业务的关键类,每个 worker 线程都有自己的单独实例,但该类只是做个包装或者桥接而已,作用不大, NettyRemotingServer才是关键。


当 Request 进入到 Server 中,MQ 会根据 请求类型 code 找到对应的处理器,MQ 有多种处理器,如下:

image.png


他们都继承自 NettyRequestProcessor 接口:

image.png

此接口只有 2 个方法,处理请求和拒绝请求,处理请求的参数是 Netty 的 context 和自身的RemotingCommand 对象,这是个大对象:

image.png


RemotingCommand 的成员变量,这里说下 flag 的作用,其他就不说了。


flag表示这次请求是什么类型。


  • 倒数第一位,0 表示请求,1 表示返回。
  • 倒数第二位,1 表示 oneWay。



NettyRequestProcessor


刚刚提到 NettyRequestProcessor ,这是个处理器,在 MQ 中,每个 NettyRequestProcessor 都绑定了一个线程池,在 MQ 的抽象里,有个 Pair 对象,如下:

public class Pair<T1, T2> {
    private T1 object1;
    private T2 object2;
    public Pair(T1 object1, T2 object2) { this.object1 = object1; 
                                         this.object2 = object2;}
    public T1 getObject1() { return object1;}
    public void setObject1(T1 object1) {this.object1 = object1; }
    public T2 getObject2() { return object2;}
    public void setObject2(T2 object2) {  this.object2 = object2;}
}
复制代码

同时,还有个 Hash 表,用 code 映射了 Pair。如此,就实现了:通过请求 code 找到“线程池和处理这种请求的处理器”,然后,提交一个任务到该线程池,任务中,会调用该处理器的 processRequest 方法,或 rejectRequest 方法。

image.png

上图中,为处理请求的关键步骤。执行钩子就不说了,我们知道,设计代码时,关键步骤都加钩子,便于扩展和以后加代码。


其中,会调用 processRequest 方法,执行具体业务,并得到返回值。然后使用 netty 的 ctx 对象,将返回值直接写回 Socket。


如果发生错误了,也将错误构造成消息,写回客户端。


注意,这里一直有个操作 就是 response.setOpaque(opaque) ,就是设置请求 ID,这是 IO 多路复用的关键。


Netty 每次请求,都会调用 NettyRemotingServer 的 processRequestCommand 方法。


而 NettyRemotingServer 保存了请求 code 和 Pair<处理器,线程池> 的hash 映射表。


每次请求,根据 code 找到线程池,生成一个新任务,提交到线程池,任务里,会执行“处理器” 的processRequest 方法得到返回值,最后写回客户端。


MQ 为每种类型的任务,使用了不同的线程池,即线程池隔离。同时,也根据每种不同的任务类型,设置了不同的线程池参数。




参数介绍


  • Send 发送消息任务,线程池大小是1。
  • pull 拉取消息任务,线程池大小是 16 + CPU*2
  • query 查询任务,线程池大小是 8 + CPU*2;


当然还有其他的,这里就不枚举了,注意:大部分线程池都是多线程,只有 send 任务默认是单线程。


send 操作是个写操作,最后是要上锁的,虽然锁的粒度已经足够小,但仍然是有锁的。如果是有锁的,多线程的是不划算的。这也是 RocketMQ 的设计决定只写一个 CommitLog。


能像Kafka一样,同时写多个文件,是不是就可以利用多线程了呢?


当然,这里不是说多线程一定好,只是表达另外一种思路。如果单线程就能触发 MQ 瓶颈,多线程也没啥意义。


总结


image.png


相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
17天前
|
运维 Kubernetes Cloud Native
云原生技术:容器化与微服务架构的完美结合
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术以其灵活性和高效性成为企业的新宠。本文将深入探讨云原生的核心概念,包括容器化技术和微服务架构,以及它们如何共同推动现代应用的发展。我们将通过实际代码示例,展示如何在Kubernetes集群上部署一个简单的微服务,揭示云原生技术的强大能力和未来潜力。
|
25天前
|
运维 持续交付 API
从零构建微服务架构:一次深度技术探索之旅####
【10月更文挑战第28天】 本文记录了作者在从零开始构建微服务架构过程中的深刻技术感悟,通过实战案例详细剖析了微服务设计、开发、部署及运维中的关键要点与挑战。文章首先概述了微服务架构的核心理念及其对企业IT架构转型的重要性,随后深入探讨了服务拆分策略、API网关选型、服务间通信协议选择、容器化部署(Docker+Kubernetes)、以及持续集成/持续部署(CI/CD)流程的设计与优化。最后,分享了在高并发场景下的性能调优经验与故障排查心得,旨在为读者提供一套可借鉴的微服务架构实施路径。 ####
57 3
|
2月前
|
消息中间件 存储 Java
RocketMQ(一):消息中间件缘起,一览整体架构及核心组件
【10月更文挑战第15天】本文介绍了消息中间件的基本概念和特点,重点解析了RocketMQ的整体架构和核心组件。消息中间件如RocketMQ、RabbitMQ、Kafka等,具备异步通信、持久化、削峰填谷、系统解耦等特点,适用于分布式系统。RocketMQ的架构包括NameServer、Broker、Producer、Consumer等组件,通过这些组件实现消息的生产、存储和消费。文章还提供了Spring Boot快速上手RocketMQ的示例代码,帮助读者快速入门。
|
2月前
|
边缘计算 Cloud Native 安全
构建灵活高效的下一代应用架构 随着企业数字化转型的加速,云原生技术正逐渐成为构建现代化应用程序的关键支柱。
随着企业数字化转型加速,云原生技术逐渐成为构建现代化应用的关键。本文探讨了云原生的核心概念(如容器化、微服务、DevOps)、主要应用场景(如金融、电商、IoT)及未来发展趋势(如无服务器计算、边缘计算、多云架构),并分析了面临的挑战,如架构复杂性和安全问题。云原生技术为企业提供了更灵活、高效的应用架构,助力数字化转型。
70 4
|
15天前
|
存储 分布式计算 关系型数据库
架构/技术框架调研
本文介绍了微服务间事务处理、调用、大数据处理、分库分表、大文本存储及数据缓存的最优解决方案。重点讨论了Seata、Dubbo、Hadoop生态系统、MyCat、ShardingSphere、对象存储服务和Redis等技术,提供了详细的原理、应用场景和优缺点分析。
|
17天前
|
监控 API 微服务
后端技术演进:从单体架构到微服务的转变
随着互联网应用的快速增长和用户需求的不断演化,传统单体架构已难以满足现代软件开发的需求。本文深入探讨了后端技术在面对复杂系统挑战时的演进路径,重点分析了从单体架构向微服务架构转变的过程、原因及优势。通过对比分析,揭示了微服务架构如何提高系统的可扩展性、灵活性和维护效率,同时指出了实施微服务时面临的挑战和最佳实践。
42 7
|
15天前
|
传感器 算法 物联网
智能停车解决方案之停车场室内导航系统(二):核心技术与系统架构构建
随着城市化进程的加速,停车难问题日益凸显。本文深入剖析智能停车系统的关键技术,包括停车场电子地图编辑绘制、物联网与传感器技术、大数据与云计算的应用、定位技术及车辆导航路径规划,为读者提供全面的技术解决方案。系统架构分为应用层、业务层、数据层和运行环境,涵盖停车场室内导航、车位占用检测、动态更新、精准导航和路径规划等方面。
66 4
|
2月前
|
Kubernetes Cloud Native 持续交付
云端新纪元:云原生技术重塑IT架构####
【10月更文挑战第20天】 本文深入探讨了云原生技术的兴起背景、核心理念、关键技术组件以及它如何引领现代IT架构迈向更高效、灵活与可扩展的新阶段。通过剖析Kubernetes、微服务、Docker等核心技术,本文揭示了云原生架构如何优化资源利用、加速应用开发与部署流程,并促进企业数字化转型的深度实践。 ####
|
16天前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代应用架构中的实践与思考
【10月更文挑战第38天】随着云计算的不断成熟和演进,云原生(Cloud-Native)已成为推动企业数字化转型的重要力量。本文从云原生的基本概念出发,深入探讨了其在现代应用架构中的实际应用,并结合代码示例,展示了云原生技术如何优化资源管理、提升系统弹性和加速开发流程。通过分析云原生的优势与面临的挑战,本文旨在为读者提供一份云原生转型的指南和启示。
31 3
|
18天前
|
网络协议 数据挖掘 5G
适用于金融和交易应用的低延迟网络:技术、架构与应用
适用于金融和交易应用的低延迟网络:技术、架构与应用
44 5

相关产品

  • 云消息队列 MQ