RocketMQ 源码分析之初涉 Broker (一)

455 阅读2分钟

Broker 是 RocketMQ 中最核心的模块,也是最难啃的骨头

但是,没关系,单点突破,积少成多,一点点来攻破它

上一节中讲到了消息发送,那接着这个突破口,看看 Broker 中是怎样处理消息生产者发送过来的消息的

消息生产者 调用方法发送消息到 Broker ,方法 org.apache.rocketmq.remoting.netty.NettyRemotingAbstract#invokeSyncImpl

底层网络发送的数据全部封装到 RemotingCommand 类中

RemotingCommand

image-20220508111637881

发送请求时调用 createRequestCommand 方法构造 RemotingCommand

属性 code 用来区别是什么类型的请求

像消息生产者生产消息的 code 就有很多种

  • SEND_MESSAGE(10): 发送消息 v1
  • SEND_MESSAGE__V2(310): 发送消息 v2
  • SEND_BATCH_MESSAGE(320): 发送批量消息
  • ...

image-20220508112214106

Broker 怎样处理发送消息的请求呢?

  1. 注册处理器

    方法 org.apache.rocketmq.broker.BrokerController#registerProcessor

    image-20220508114044620

在这个方法中,对于生产消息的请求,都注册处理器 SendMessageProcessor

方法 org.apache.rocketmq.remoting.netty.NettyRemotingAbstract#processRequestCommand

image-20220508114409688

在 processsRequestCommand 方法中,会查找对应请求类型的处理器

生产消息类的请求处理器都是 SendMessageProcessor

SendMessageProcessor

image-20220508201218700

image-20220508202031923

继续追踪,调用方法 asyncSendMessage 异步处理请求

image-20220508202304701

image-20220508202338946

image-20220508202407492

追踪 asyncSendMessage ,可以发现方法调用层级还是挺深的,最后定位到方法 asyncPutMessages

org.apache.rocketmq.store.DefaultMessageStore#asyncPutMessages

asyncPutMessages

image-20220508202505459

asyncPutMessages 方法先判断存储组件是否可以存储数据

image-20220508203311389

不可以存储消息的几种情况:

  • shutdown 状态
  • Broker 是从机
  • 磁盘写满了
  • 操作系统页缓存繁忙

image-20220508203821556

image-20220508204229600

追踪方法 org.apache.rocketmq.store.CommitLog#asyncPutMessages

在这个方法里,找到要写入的 MappedFile

再调用MappedFile 的 appendMessages 写入消息数据

image-20220508204501859

appendMessages 调用方法appendMessagesInner

先获取MappedFile的写指针

如果写指针大于等于文件大小,返回异常信息

如果写指针小于文件大小,通过 slice 方法获取一个原 ByteBuffer 共享的内存区域

但是新的 ByteBuffer 维护自己的 position、limit、capacity 属性

这里设置 position 为当前写指针位置

然后调用doAppend方法

doAppend

image-20220508224046823

在 doAppend 方法中,调用 byteBuffer.put(preEncodeBuffer) 将消息数据写入内存中