RocketMQ——Broker篇

本文详细介绍了RocketMQ Broker的初始化过程和启动流程,包括加载配置文件、初始化DefaultMessageStore、启动Netty服务、注册事件处理器、定时任务设置、主备同步以及处理客户端请求等内容,揭示了Broker在RocketMQ中的核心功能和运行机制。
摘要由CSDN通过智能技术生成

1 Broker的初始化过程

调用BrokerController对象的initialize方法进行初始化工作。大致逻辑如下:

1、加载topics.json、consumerOffset.json、subscriptionGroup.json文件,分别将各文件的数据存入TopicConfigManager、ConsumerOffsetManager、SubscriptionGroupManager对象中;在初始化BrokerController对象的过程中,初始化TopicConfigManager对象时,默认初始化了"SELF_TEST_TOPIC"、"TBW102"(自动创建Topic功能是否开启BrokerConfig.autoCreateTopicEnable=false,线上建议关闭)、"BenchmarkTest"、BrokerClusterName(集群名称)、BrokerName(Broker的名称)、"OFFSET_MOVED_EVENT"这5个topic的信息并存入了topicConfigTable变量中,在向NameServer注册时发给NameServer进行登记;

2、初始化DefaultMessageStore对象,该对象是应用层访问存储层的访问类;

2.1)AllocateMapedFileService服务线程,当需要创建MappedFile时(在MapedFileQueue.getLastMapedFile方法中),向该线程的requestQueue队列中放入AllocateRequest请求对象,该线程会在后台监听该队列,并在后台创建MapedFile对象,即同时创建了物理文件。

2.2)创建DispatchMessageService服务线程,该服务线程负责给commitlog数据创建ConsumeQueue数据和创建Index索引。

2.3)创建IndexService服务线程,该服务线程负责创建Index索引;

2.4)还初始化了如下服务线程,在调用DispatchMessageService对象的start方法时启动这些线程:

服务类名 作用
FlushConsumeQueueService 逻辑队列刷盘服务,每隔1秒钟就将ConsumeQueue逻辑队列、TransactionStateService.TranRedoLog变量的数据持久化到磁盘物理文件中
CleanCommitLogService 清理物理文件服务,定期清理72小时之前的物理文件。
CleanConsumeQueueService 清理逻辑文件服务,定期清理在逻辑队列中的物理偏移量小于commitlog中的最小物理偏移量的数据,同时也清理Index中物理偏移量小于commitlog中的最小物理偏移量的数据。
StoreStatsService 存储层内部统计服务
HAService 用于commitlog数据的主备同步
ScheduleMessageService 用于监控延迟消息,并到期后执行
TransactionStateService 用于事务消息状态文件,在RocketMQ-3.1.9版本中可以查看源码

2.5)初始化CommitLog对象,在初始化该对象的过程中,第一,根据刷盘类型初始化FlushCommitLogService线程服务,若为同步刷盘(SYNC_FLUSH),则创建初始化为GroupCommitService线程服务;若为异步刷盘(ASYNC_FLUSH)则创建初始化FlushRealTimeService线程服务;第二,初始化DefaultAppendMessageCallback对象;

2.6)启动AllocateMapedFileService、DispatchMessageService、IndexService服务线程。

3、调用DefaultMessageStore.load加载数据:

3.1)调用ScheduleMessageService.load方法,初始化延迟级别列表。将这些级别("1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h")的延时存入延迟级别delayLevelTable:ConcurrentHashMap<Integer /* level */, Long/* delay timeMillis */>变量中,例如1s的kv值为1:1000,5s的kv值为2:5000,key值依次类推;每个延迟级别即为一个队列。

3.2)调用CommitLog.load方法,在此方法中调用MapedFileQueue.load方法,将$HOME /store/commitlog目录下的所有文件加载到MapedFileQueue的List<MapedFile>变量中;

3.3)调用DefaultMessageStore.loadConsumeQueue方法加载consumequeue文件数据到DefaultMessageStore.consumeQueueTable集合中。

3.4)调用TransactionStateService.load()方法加载tranStateTable文件和tranRedoLog文件;

3.5)初始化StoreCheckPoint对象,加载$HOME/store/checkpoint文件,该文件记录三个字段值,分别是物理队列消息时间戳、逻辑队列消息时间戳、索引队列消息时间戳。

3.6)调用IndexService.load方法加载$HOME/store/index目录下的文件。对该目录下的每个文件初始化一个IndexFile对象。然后调用IndexFile对象的load方法将IndexHeader加载到对象的变量中;再根据检查是否存在abort文件,若有存在abort文件,则表示Broker表示上次是异常退出的,则检查checkpoint的indexMsgTimestamp字段值是否小于IndexHeader的endTimestamp值,indexMsgTimestamp值表示最后刷盘的时间,若小于则表示在最后刷盘之后在该文件中还创建了索引,则要删除该Index文件,否则将该IndexFile对象放入indexFileList:ArrayList<IndexFile>索引文件集合中。

3.7)恢复内存数据。

1)恢复每个ConsumeQueue对象的maxPhysicOffset变量的值(最后一个消息的物理offset),遍历consumeQueueTable集合中的每个topic/queueId下面的ConsumeQueue对象,调用ConsumeQueue对象recover方法。

2)根据是否有abort文件来确定选择何种方法恢复commitlog数据,若有该文件则调用CommitLog对象的recoverAbnormally方法进行恢复,否则调用CommitLog对象的recoverNormally方法进行恢复。主要是恢复MapedFileQueue对象的commitedWhere变量值(即刷盘的位置),删除该commitedWhere值所在文件之后的commitlog文件以及对应的MapedFile对象。

3)恢复CommitLog对象的topicQueueTable :HashMap<String/* topic-queueid */, Long/* offset */>变量值;遍历consumeQueueTable集合,逻辑如下:

A)对每个topic/queueId下面的ConsumeQueue对象,获取该对象的最大偏移量,等于MapedFileQueue.getMaxOffset/20;然后以topic-queueId为key值,该偏移量为values,存入topicQueueTable变量中;

B)以commitlog的最小物理偏移量修正ConsumeQueue对象的最小逻辑偏移量minLogicOffset;

4)调用TransactionStateService.tranRedoLog:ConsumeQueue对象的recover()方法恢复tranRedoLog文件;

5)调用TransactionStateService.recoverStateTable(boolean lastExitOK)方法恢复tranStateTable文件,

5.1)若存在abort文件则上一次退出是异常关闭,采用如下恢复方式:

A)删除tranStateTable文件;

B)新建tranStateTable文件,然后从tranRedoLog文件的开头开始偏移,找出所有事务消息状态为PREPARED的记录,该记录为每个事务消息在commitlog的物理位置;

C)遍历这些PREPARED状态的事务消息的物理位置集合,以物理位置commitlogoffset值从commitlog文件中找出获取每个事务消息的commitlogoffset、msgSize、StoreTimeStamp以及producerGroup的hash值,然后调用TransactionStateService.appendPreparedTransaction(long clOffset, int size, int timestamp, int groupHashCode)方法将这些信息写入新建的tranStateTable文件中,并更新TransactionStateService.tranStateTableOffset变量值(表示在tranStateTable文件中的消息个数);

5.2)若不存在abort文件则上一次是正常关闭,采用如下恢复方式:

与调用ConsumeQueue对象的recover方法恢复ConsumeQueue数据的逻辑是一样的;在恢复完tranStateTable文件数据之后计算该文件中的消息个数并赋值给TransactionStateService.tranStateTableOffset变量值,计算方式为MapedFileQueue.getMaxOffset()/24;

4、初始化Netty服务端NettyRemotingServer对象;

5、初始化发送消息线程池(sendMessageExecutor)、拉取消息线程池(pullMessageExecutor)、管理Broker线程池(adminBrokerExecutor)、客户端管理线程池(clientManageExecutor)。

6、注册事件处理器,包括发送消息事件处理器(SendMessageProcessor)、拉取消息事件处理器、查询消息事件处理器(QueryMessageProcessor,包括客户端的心跳事件、注销事件、获取消费者列表事件、更新更新和查询消费进度consumerOffset)、客户端管理事件处理器、结束事务处理器(EndTransactionProcessor)、默认事件处理器(AdminBrokerProcessor)。

7、启动如下定时任务:

1)Broker的统计功能;

2)每隔5秒对ConsumerOffsetManager.offsetTable: ConcurrentHashMap<String/* topic@group */, ConcurrentHashMap<Integer, Long>>变量的内容进行持久化操作,持久化到consumerOffset.json文件中;

3)扫描被删除的topic,将offsetTable中的对应的消费进度记录也删掉。大致逻辑是遍历ConsumerOffsetManager.offsetTable变量:

A)以group和topic为参数调用ConsumerManager.findSubscriptionData(String group, String topic)方法获取当前该topic和group的订阅数据;若获取的数据为空,则认为该topic和group已经不在当前订阅关系中。

B)遍历该topic@group下面的所有队列的消费进度(ConsumerOffsetManager.offsetTable变量的values值),检查每个队列的消费进度是否都大于该队列最小逻辑偏移量;

C)若该topic和group已经不在当前订阅数据表中,而且在offsetTable中的消费进度已经小于ConsumeQueue的最小逻辑偏移量minLogicOffset,则从offsetTable变量中删除该记录。

8、检查Broker配置的Name Server地址是否为空,若不为空,则更新Broker的Netty客户端BrokerOuterAPI.NettyRemotingClient的Name Server地址;若为空且配置了允许从地址服务器找Name Server地址,则启动定时任务,地址服务器的路径是"http://&quot; + WS_DOMAIN_NAME + ":8080/rocketmq/" + WS_DOMAIN_SUBGROUP ;其中WS_DOMAIN_NAME由配置参数rocketmq.namesrv.domain设置,WS_DOMAIN_SUBG由配置参数rocketmq.namesrv.domain.subgroup设置;

9、若该Broker为主用,则启动定时任务打印主用Broker和备用Broker在Commitlog上的写入位置相差多少个字节。

主用Broker的写入位置计算方式:获取最后一个MappedFile的fileFromOffset和wrotePostion值,相加即为最新的写入位置。

备用Broker的写入位置从HAService. push2SlaveMaxOffset获得,该值表示主用Broker同步到Slave的最大Offset。

10、若该Broker为备用,首先检查是否配置了主用Broker的地址,在备用Broker可以在broker.properties配置文件中设置haMasterAddress参数来指定主用Broker的地址,若设置了,则更新HAService.HAClient.masterAddress的值&

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值