您现在的位置是:网站首页 / 大后端大后端

从零开始学RocketMQ(1) - RocketMQ构图整理概览及源码编译

自由达人2021-04-23 1092人围观

简介 RocketMQ是现在十分火热的一款高性能,低延迟,高可用的消息中间件,经过历年双十一的考验,以出色的成绩捕获了很多技术员的芳心,所以我以零基础的角度来梳理RocketMQ,本文介绍了RocketMQ架构和简单的介绍了模块的组成,以及用源码搭建了一套本地环境,从生产者发送消息到消费者消费到消息,由浅到深的带领你上手RocketMQ

提到RocketMQ就不得不铺一下Message Queue简称MQ。我理解为其实消息队列是一种具备规则的数据结构,比如FIFO。这种的模型可以抽象出来形成生产者消费者模式,即生产者将数据放在队列中,然后消费者从队列中取数据。这个过程中生产者和消费者可以不在同一个项目,也可以是不同业务类型的应用,并且生产者和消费者对数据处理能力也一样。所以能总结出消息队列的几个作用

  1. 业务解耦:比如销售系统在用户支付成功之后会更新订单状态,并且会将下单时锁定的库存进行扣减。传统单体项目可能是一条业务线走到底,但随着互联网发展,在业务单一原则下很多服务只处理一类型的业务了,这样MQ就可以充当业务解耦的作用,支付系统在支付成功后发送一条消息告知消费者交易成功,那么订阅这个队列的消费者就可以收到,进行订单更新,进行库存扣减了。
  2. 削峰填谷:这个比较好理解,在高并发的场景下,某些业务不是必须马上执行的,利用MQ可以有效降低系统压力。比如登陆送积分业务,如果有1000人同时登陆系统,如果不使用MQ就可能是登陆后进行积分增加,记录日志等,串行化的处理业务会增加登陆响应时间,这是使用MQ可以将并发量转换到了MQ上,而积分系统可以按照自己的吞吐量去消化掉这些业务,而不是正面抗高并发的请求,将波峰的流量平缓的处理掉。
  3. 异步化:从上面两点都可以看出,不管是业务解耦合还是削峰填谷都不是串行化的执行,生产者和消费者其实是异步化的。
    好了,回到RocketMQ上来,它是阿里开源的一款MQ中间件,早期阿里内部为了将交易核心数据的流转,需要一款能存储海量消息并且支持顺序消息的MQ,所以内部开始了研发了叫MetaQ的中间件,到了2012年经过版本迭代后包装成了RocketMQ并开源出来。在阿里内部经过历年双十一大促和内部成千上万个应用的检验,RocketMQ已经是一款性能高,可用性高,稳定性强的一款消息中间件了。
    安利了RocketMQ这么多,那我们就先一窥它的结构吧
    RocketMQ架构图
    RocketMQ架构图

从上图中可以看出RocketMQ分为几个部分构成的,分别有Producer集群、Consumer集群、NameServer集群、Broker集群组构成,下面逐一梳理下每个部分的作用及工作流程。

消息

消息其实就是一个PO对象,包含一些特殊的属性,譬如Topic,唯一MessageId,消息体等

Producere 生产者

是业务发送数据方的系统的代名词,生产者会将消息按照RocketMQ规定的格式投递给Broker。那么问题来了,他是如何得知Broker的通讯地址呢?下面介绍完NameServer后便清楚了。生产者投递消息可以分为顺序投递,同步投递,异步投递,单向投递的方式进行投递消息。

Consumer 消费者

作为下游业务系统的代名词,消费者会从Broker以Push和Pull的方式来获取消息进行后续业务,具体从哪个Broker获取消息和Producer的原理一致

NameServer 类似Zookeeper的注册中心

在现在的分布式架构设计中,注册中心扮演着举足轻重的角色。在RocketMQ集群环境中中Broker会和每个NameServer节点连接并保持心跳通讯,将Broker的连接信息,Topic等信息同步给NameServer。每个NameServer包含了集群中所有Broker的信息,比如Topic对应的Broker信息,当Producer和Consumer根据Topic来生产或者消费信息时就会返回对应的Broker信息,然后在Broker和Produer/Consumer之间建立连接进行发送和消费消息,但是NameServer与NameServer之间互不通讯。

Broker 我一直没有想好对他安利一个什么名字比较好,官方叫它是代理服务器

Broker在RocketMQ架构中扮演着最重要的角色,它会和所有NameServer进行连接通讯以达到高可用,负责接收Producer投递的消息的存储、转发,负责Topic的创建与管理。

下面就将RocketMQ运行起来,首先从GitHub上得到源码,如果是新学者可以下载已经编译好的二进制文件,这里我就以源码的形式来启动RocketMQ,为后续深入了解RocketMQ做准备。GitHub地址https://github.com/apache/rocketmq.git 已经编译好的RocketMQ连接https://www.apache.org/dyn/closer.cgi?path=rocketmq/4.8.0/rocketmq-all-4.8.0-bin-release.zip

RocketMQ源码结构
RocketMQ源码结构

上面已经简单的介绍了模块作用可以得知Producer、Consumer、Broker都依赖NameServer,所以先启动NameServer,对应源码模块是namesrv,启动类org.apache.rocketmq.namesrv.NamesrvStartup#main,初次启动RocketMQ会报‘Please set the ROCKETMQ_HOME variable in your environment to match the location of the RocketMQ installation’,在环境变量中设置ROCKETMQ_HOME=/rocketmq/distribution即可正常启动,当输出下图代表NameServer启动成功
NameServer启动成功
NameServer启动成功

然后启动Broker,启动类org.apache.rocketmq.broker.BrokerStartup#main,同样的首次启动也会需要在配置好ROCKET_MQ的前提下进行,并且从上面的架构图可以看到Broker是要和NameServer建立连接的,所以我们要指定NameServer的地址,所以在环境变量中指定NAMESRV_ADDR=localhost:9876 ,然后启动成功后会出如下图
Broker启动成功
Broker启动成功

接下来启动生产者和消费者,生产者和消费者我这就先用源码中的示例代码来演示,后面梳理各个模块时在写一些代码来演示
首先启动生产者org.apache.rocketmq.example.quickstart.Producer#main, 这里可以看到代码注释中有写 Specify name server addresses.Alternatively, you may specify name server addresses via exporting environmental variable: NAMESRV_ADDR,意思是启动生产者需要指定NameServer,可以通过配置环境变量NAMESRV_ADDR,其实还可以在DefaultMQProducer类设置namesrvAddr属性,这里我使用第二种设置为localhost:9876, 如图
启动生产者
启动生产者
可以看到启动生产者后已经在往RocketMQ发送消息了,同理启动消费者,如图
启动消费者
启动消费者
可以看到消费者启动成功后立马就在消费刚刚生产者产生的1000条消息了,证明启动是成功的。

到此,如果将MQ的基本原理作用,RocketMQ概念和发展历程以及RocketMQ的架构图和各个模块的作用都进行梳理了一遍,最后以源码的角度构建了单机版的RocketeMQ生产和消费,到这里RocketMQ已经算是入门了,后面我从源码的角度深入梳理每个模块的原理以及以实例来演示。

我是小码哥,保持空杯心态,学海无涯,总有你不会的,欢迎点赞留言。如有错误也请指教

  • 7 点赞
  • 0 收藏
  • 分享

作品评论