003-Rocket源码分析

源码分析

分析

源码从启动类开始看起
看一下在启动的过程中启动和处理了哪些事情
从主干到分支

启动类

namesrv

org.apache.rocketmq.namesrv.NamesrvStartup

broker

org.apache.rocketmq.broker.BrokerStartup

主要流程

NamesrvStartup

nameSrv主要是用于

  1. broker 的注册和发现
  2. Topic的管理 : 维护Topic与Broker 的关系
  3. 负载均衡 : 分发不同的broker给客户端
  4. 集群管理 : 监控Broker的心跳

分析main方法
读取配置
调用启动start(NamesrvController controller);
在这里插入图片描述

源码分析

  1. initialize()中
    this.kvConfigManager.load();
    初始化remotingServer=new NettyRemotingServer(、remotingExecutor
    调用了registerProcessor()
    设置了2个定时任务
    NamesrvController.this.routeInfoManager.scanNotActiveBroker();
    NamesrvController.this.kvConfigManager.printAllPeriodically();

  2. registerProcessor中
    注册了DefaultRequestProcessor

  3. start()中
    remotingServer.start();

在这里插入图片描述
设置HandshakeHandler handshakeHandler、NettyConnectManageHandler connectionManageHandler
在这里插入图片描述
启动NettyEventExecutor 异步读取 eventQueue
在这里插入图片描述

BrokerStartup

主要负责消息的收发

源码分析
  1. main() 中
    brokerConfig = new BrokerConfig();
    nettyServerConfig = new NettyServerConfig();
    nettyClientConfig = new NettyClientConfig();
    controller = new BrokerController

controller.initialize();

注册了异步线程池及定时处理处理:
BrokerController.this.getBrokerStats().record();
BrokerController.this.consumerOffsetManager.persist();
BrokerController.this.consumerFilterManager.persist();
BrokerController.this.protectBroker();
BrokerController.this.printWaterMark();
BrokerController.this.brokerOuterAPI.fetchNameServerAddr();
BrokerController.this.printMasterAndSlaveDiff();

然后就是加载三个功能:
initialTransaction();
initialAcl();
initialRpcHooks();

业务流程

心跳注册

入口就是BrokerController#start方法:
调用brokerOuterAPI#needRegister方法:
就是向所有nameServer发起请求(请求code为QUERY_DATA_VERSION,322),获取所有nameserver的DataVersion数据,然后一一对比自身的DataVersion数据是否一致,如果有一个nameserver的数据版本不一致则重新注册。

doRegisterBrokerAll方法的逻辑也很简单,就是向所有nameServer发起请求。

是调用另一个registerBroker方法,该方法真正的执行向一个nameserver发起注册的请求。

broker注册请求为同步请求,code为REGISTER_BROKER,103,注册的信息主要包括自身的所有topic数据、dataVersion、filterServerList、以及包括集群名、broker地址、broker名、brokerId等等在内的一些broker自身的信息。

Broker发送了心跳包之后,nameserver会进行专门的处理,保存或者更新broker上报的心跳包数据。

NameServer的默认网络处理器是DefaultRequestProcessor,因此心跳请求的入口也就是DefaultRequestProcessor#processRequest方法。

processRequest方法是一个通用的请求处理入口方法,内部会根据请求的不同requestCode进入分发处理,心跳请求的requestCode就是REGISTER_BROKER,103。

该方法用于注册broker,也就是对broker的各种路由信息进行更新或者注册。

其主要步骤为:

  1. 加写锁,保证线程安全。 存入或者更新brokerName信息集合clusterAddrTable。
  2. 存入或者更新broker基本信息集合brokerAddrTable。
  3. 存入一个brokerData对象。
  4. 如果当前broker是主broker节点。更新或者创建topic的队列配置信息集合topicQueueTable。
  5. 存入或者更新中broker状态信息集合brokerLiveTable。存入或者更新的信息包括最新的更新时间戳设置为当前时间,brokerLiveTable被nameServer用于执行心跳检测操作。
  6. 存入或者更新消费过滤信息集合filterServerList。ClassFilter模式的消费过滤集合的操作。
  7. 如果当前broker不是主broker节点。对返回结果result设置HaServerAddr以及MasterAddr的地址。
  8. 释放写锁。

scanNotActiveBroker扫描清除不活跃broker

发送消息

DefaultMQProducer#send方法作为源码分析的入口方法,该方法被使用者直接调用。
defaultMQProducerImpl中

  1. 同步消息send方法发送。
  2. 单向消息使用sendOneway发送。
  3. 异步消息使用带有callback函数的send方法发送。

sendDefaultImpl发送消息该方法的大概步骤为:

  1. 调用makeSureStateOK方法,确定此producer的服务状态正常,如果服务状态不是RUNNING,那么抛出异常。
  2. 调用checkMessage方法,校验消息的合法性。
  3. 调用tryToFindTopicPublishInfo方法,尝试查找消息的一个topic路由,用以发送消息。
  4. 计算循环发送消息的总次数timesTotal,默认情况下,同步模式为3,即默认允许重试2次,可更改重试次数;其他模式为1,即不允许重试,不可更改。实际上异步发送消息也会重试,最多两次,只不过不是通过这里的逻辑重试的。
  5. 调用selectOneMessageQueue方法,选择一个消息队列MessageQueue,该犯法支持失败故障转移。
  6. 调用sendKernelImpl方法发送消息,异步、同步、单向发送消息的模式都是通过该方法实现的。
  7. 调用updateFaultItem方法,更新本地错误表缓存数据,用于延迟时间的故障转移的功能。
  8. 根据发送模式执行不同的处理,如果是异步或者单向模式则直接返回,如果是同步模式,如果开启了retryAnotherBrokerWhenNotStoreOK开关,那么如果返回值不是返回SEND_OK状态,则仍然会执行重试发送。
  9. 此过程中,如果抛出了RemotingException、MQClientException、以及部分MQBrokerException异常时,那么会进行重试,如果抛出了InterruptedException,或者因为超时则不再重试。

selectOneMessageQueue方法用于查找一个可用的消息队列,该方法内部调用mqFaultStrategy#selectOneMessageQueue方法

接收消息

registerProcessor注册消息处理器
SendMessageProcessor这个处理器被用来专门处理发送消息请求,也就是说Producer的发送消息类请求都是通过这个处理器来处理的。这些处理器会连同对应的执行器线程池一起构建一个Pair对象,然后以requestCode为key,Pair对象为value注册到processorTable集合缓存中。

当Netty服务端接收到消息的时候,首先会在NettyServerHandler中进行处理。具体的处理器方法就是processMessageReceived方法了

文件存储

入口在:DefaultMessageStore.putMessage

  1. commitLog写入
  2. 分发ConsumeQueue和IndexFile
    在DefaultMessageStore的start方法中,会启动一个后台线程reputMessageService每隔1毫秒就会去拉取CommitLog中最新更新的一批消息,然后分别转发到ComsumeQueue和IndexFile里去了恢复索引文件的方法在DefaultMappedStore#load
  3. 文件刷盘
    入口:CommitLog.submitFlushRequest
  4. CommigLog主从复制
    入口:CommitLog.submitReplicaRequest
    HAService:
    acceptSocketService主要负责维护Master与Slave之间的TCP连接
    groupTransferService主要与主从同步复制有关
    而slave相关的则是haClient
  5. 过期文件删除
    入口: DefaultMessageStore.addScheduleTask ->DefaultMessageStore.this.cleanFilesPeriodically()

延时消息

理入口在scheduleMessageService、在broker启动时也一起加载

  1. 消息写入
    入口:CommitLog.putMessage
    在CommitLog写入消息时,会判断消息的延迟级别,然后修改Message的Topic和Queue,达到转储Message的目的
  2. 消息转储到目标Topic
    核心:scheduleMessageService
    只在master节点启用、其他节点关闭

长轮询

当Broker接收到Consumer的Pull请求时,判断如果没有对应的消息,不用直接给Consumer响应(给响应也是个空的,没意义),而是就将这个Pull请求给缓存起来。当Producer发送消息过来时,增加一个步骤去检查是否有对应的已缓存的Pull请求,如果有,就及时将请求从缓存中拉取出来,并将消息通知Consumer。

consumer

org.apache.rocketmq.broker.processor.PullMessageProcessor#processRequest
在这里插入图片描述
在这里插入图片描述
如果ResponseCode.SUCCESS 则返回
如果ResponseCode.PULL_NOT_FOUND 则暂停拉取请求suspendPullRequest
加入pullRequestList

producer

org.apache.rocketmq.store.DefaultMessageStore.ReputMessageService#doReput

this.messageArrivingListener = new NotifyMessageArrivingListener(this.pullRequestHoldService);

org.apache.rocketmq.broker.longpolling.PullRequestHoldService#notifyMessageArriving中
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值