rocketmq源码分析2-broker的消息接收
broker消息接收,假设接收的是一个普通消息(即没有事务),此处分析也只分析master上动作逻辑,不涉及ha。
1. 如何找到消息接收处理入口
可以通过broker的监听端口10911顺藤摸瓜式的找到 NettyClientConfig.setListenPort-->BrokerStartup-->BrokerController-->NettyRemotingServer
com.alibaba.rocketmq.remoting.netty.NettyDecoder com.alibaba.rocketmq.remoting.netty.NettyRemotingServer.NettyServerHandler.channelRead0(ChannelHandlerContext, RemotingCommand)
也可以顺着broker的启动脚本找到
BrokerStartup-->BrokerController-->NettyRemotingServer
因为rocketmq连接层默认使用netty开发,如果熟悉netty的话,
可以直接查找ChannelInitializer或者pipeline().addLast等
2. 调试NettyDecoder
com.alibaba.rocketmq.remoting.netty.NettyDecoder.decode(ChannelHandlerContext, ByteBuf)
会调用RemotingCommand.decode(byteBuffer)组装RemotingCommand
在com.alibaba.rocketmq.remoting.protocol.RemotingCommand.decode(ByteBuffer) 中断点 排除如下code
cmd.getCode() != 0 && cmd.getCode() != 34 && cmd.getCode() != 15
&& cmd.getCode() != 38 && cmd.getCode() != 11
用producer的client发一条消息到broker
发现RemotingCommand.decode解析出来的RemotingCommand的code为310 310对应RequestCode.SEND_MESSAGE_V2 发送消息
此时处理线程是:Thread [NettyServerWorkerThread_2]
RemotingCommand主要描述了操作code、opaque号、body即消息体。
3. 调试NettyServerHandler
对com.alibaba.rocketmq.remoting.netty.NettyRemotingServer.NettyServerHandler.channelRead0(ChannelHandlerContext, RemotingCommand)断点
断点条件属性是msg.getCode() == 310
此时处理线程是:Thread [NettyServerWorkerThread_2]
4. NettyRemotingAbstract
com.alibaba.rocketmq.remoting.netty.NettyRemotingAbstract.processRequestCommand(ChannelHandlerContext, RemotingCommand)
方法负责分发给相应的NettyRequestProcessor实例
负责处理的是com.alibaba.rocketmq.broker.processor.SendMessageProcessor@17fb0278
处理线程是:Thread [SendMessageThread_1],跟上面的处理已经不在一个线程上了,异步
5. SendMessageProcessor
SendMessageProcessor.processRequest(ChannelHandlerContext, RemotingCommand)介入处理
构建SendMessageRequestHeader
进入SendMessageProcessor.sendMessage(ChannelHandlerContext, RemotingCommand, SendMessageContext, SendMessageRequestHeader)
int queueIdInt = requestHeader.getQueueId(); 作用是什么 什么时候确定的id
构建MessageExtBrokerInner实例 tags转tagsCode 就是tags的String的hashcode
PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner);
交给MessageStore进行put(store,进行存放)
6. DefaultMessageStore
com.alibaba.rocketmq.store.DefaultMessageStore.putMessage(MessageExtBrokerInner) 消息topic的长度校验 不能超过127
消息properties转成字符串后,长度不能超过32767
下面交个CommitLog进行putMessage
7. CommitLog
com.alibaba.rocketmq.store.CommitLog.putMessage(MessageExtBrokerInner)
设置存储时间
设置消息体CRC校验值
交给MapedFile进行存储mapedFile.appendMessage(msg, this.appendMessageCallback)
8. MapedFile
mapedFile.appendMessage(msg, this.appendMessageCallback)
获取当前文件已经写到什么位置了
文件已经做了map map到mappedByteBuffer 讲当前的mappedByteBuffer 割出来并设置position为当前写位置
交由callback做append
callback是CommitLog$DefaultAppendMessageCallback
传给callback的参数有
- 1. 这个文件的offset,意思是:一个broker要存储很多消息,那么一个文件肯定不够存,当存到第二个文件的时候,这个文件里的第一条消息相对于整个broker中的消息有个offset,此值是文件名。
- 2. 从store文件映射的buffer中割出来的byteBuffer
- 3. 文件的剩余空间
- 4. 消息体
8.1 callback中append逻辑:
计算wroteOffset 即整个broker中的offset, 代码注释中称之为物理offset,计算逻辑也很简单即上面参数1+这条消息在这个文件中的position
计算消息id,逻辑使用主机物理IP加上一步的wroteOffset计算,用了ByteBuffer处理,比较高效,待完善验证用例。
获取这个topic的这个队列的offset(一个topic写多个队列),这个offset有啥用?估计是用于快速查找
将消息bean对象用msgStoreItemMemory进行以约定消息体的形式进行byte的put
将msgStoreItemMemory put到上面传进来的参数2的buffer 即写入磁盘
构建append结果,没啥逻辑,主要是一些信息 AppendMessageResult
将消息在这个队列中的offset加1
更新MapedFile的wrotePostion,就是将原来的wrotePostion加上这次写入的字节数
此时订阅断已经收到消息,(应该更早,待确认,待分析消息如何送到consume的)
8.2 回CommitLog--:
构建 PutMessageResult对象。
8.3 处理同异步刷盘逻辑
同步刷盘 用GroupCommitService, 其中使用了多条消息一起刷的设计,并且设计了刷盘如果超时的异常场景的反馈
异步刷盘 用CommitLog$FlushRealTimeService(是一个线程,此时会叫醒他)
8.4 处理主从双机同异步同步逻辑
同步形式同步从节点 交由HAService 实时同步,并等待同步结果。
异步不用管。
9. 收集统计数据
耗时等等
10. 对非oneway的消息做response处理
rocketmq源码分析2-broker的消息接收的更多相关文章
- RocketMQ源码分析之从官方示例窥探:RocketMQ事务消息实现基本思想
摘要: RocketMQ源码分析之从官方示例窥探RocketMQ事务消息实现基本思想. 在阅读本文前,若您对RocketMQ技术感兴趣,请加入RocketMQ技术交流群 RocketMQ4.3.0版本 ...
- RocketMQ源码详解 | Broker篇 · 其四:事务消息、批量消息、延迟消息
概述 在上文中,我们讨论了消费者对于消息拉取的实现,对于 RocketMQ 这个黑盒的心脏部分,我们顺着消息的发送流程已经将其剖析了大半部分.本章我们不妨乘胜追击,接着讨论各种不同的消息的原理与实现. ...
- RocketMQ 源码分析 —— Message 发送与接收
1.概述 Producer 发送消息.主要是同步发送消息源码,涉及到 异步/Oneway发送消息,事务消息会跳过. Broker 接收消息.(存储消息在<RocketMQ 源码分析 —— Mes ...
- 【RocketMQ源码分析】深入消息存储(3)
前文回顾 CommitLog篇 --[RocketMQ源码分析]深入消息存储(1) ConsumeQueue篇 --[RocketMQ源码分析]深入消息存储(2) 前面两篇已经说过了消息如何存储到Co ...
- 【RocketMQ源码分析】深入消息存储(2)
前文回顾 CommitLog篇 --[RocketMQ源码分析]深入消息存储(1) MappedFile篇 --[RocketMQ源码分析]深入消息存储(3) 前文说完了一条消息如何被持久化到本地磁盘 ...
- RocketMQ源码详解 | Broker篇 · 其三:CommitLog、索引、消费队列
概述 上一章中,已经介绍了 Broker 的文件系统的各个层次与部分细节,本章将继续了解在逻辑存储层的三个文件 CommitLog.IndexFile.ConsumerQueue 的一些细节.文章最后 ...
- RocketMQ源码分析之RocketMQ事务消息实现原理上篇(二阶段提交)
在阅读本文前,若您对RocketMQ技术感兴趣,请加入 RocketMQ技术交流群 根据上文的描述,发送事务消息的入口为: TransactionMQProducer#sendMessageInTra ...
- 【RocketMQ源码分析】深入消息存储(1)
最近在学习RocketMQ相关的东西,在学习之余沉淀几篇笔记. RocketMQ有很多值得关注的设计点,消息发送.消息消费.路由中心NameServer.消息过滤.消息存储.主从同步.事务消息等等. ...
- RocketMQ源码详解 | Broker篇 · 其一:线程模型与接收链路
概述 在上一节 RocketMQ源码详解 | Producer篇 · 其二:消息组成.发送链路 中,我们终于将消息发送出了 Producer,在短暂的 tcp 握手后,很快它就会进入目的 Broker ...
- RocketMQ源码详解 | Broker篇 · 其五:高可用之主从架构
概述 对于一个消息中间件来讲,高可用功能是极其重要的,RocketMQ 当然也具有其对应的高可用方案. 在 RocketMQ 中,有主从架构和 Dledger 两种高可用方案: 第一种通过主 Brok ...
随机推荐
- SDOI 2018二轮题解(除Day2T1)
博主诈尸啦 虽然一轮之后就退役了但是二轮还是要去划划水呀~ 然鹅学了不到一个月文化课再回来看OI的东西有一种恍如隔世的感觉,烤前感觉也没啥可复习的,就补一补去年二轮的题吧. 题目思路基本都参考自sha ...
- https的网站使用百度地图的问题
https的网站使用百度地图,如果你引用的地址没写对的话,加载不出来百度地图,被认为是不安全的JS内容. 引用的地址:http://api.map.baidu.com/api?v=2.0&ak ...
- 字符串在forEach方法里面可以使用include函数
今天在写项目的时候,发现了一个问题,使用forEach函数,arr数组里面的字符串可以调用include方法,我查阅了很多地方,string里面没有这个方法. 但是在forEach函数里面确实可以这样 ...
- equals()方法详解
Java语言中equals()方法的使用可以说比较的频繁,但是如果轻视equals()方法,一些意想不到的错误就会产生.哈哈,说的有点严重了~ 先谈谈equals()方法的出身.equals()方法在 ...
- Python3+Selenium3+webdriver学习笔记7(选择多链接的结果、iframe、下拉框)
#!/usr/bin/env python# -*- coding:utf-8 -*- from selenium import webdriverfrom selenium.webdriver.co ...
- 洛谷 P2176 [USACO14FEB]路障Roadblock
题目描述 每天早晨,FJ从家中穿过农场走到牛棚.农场由 N 块农田组成,农田通过 M 条双向道路连接,每条路有一定长度.FJ 的房子在 1 号田,牛棚在 N 号田.没有两块田被多条道路连接,以适当的路 ...
- 使用工具Source Monitor测量您Java代码的环复杂度
代码的环复杂度(Cyclomatic complexity,有时也翻译成圈复杂度)是一种代码复杂度的衡量标准,在1976年由Thomas J. McCabe, Sr. 提出. 来看看计算公式. 代码环 ...
- MySQL安装未响应解决方法
安装MySQL出示未响应,一般显示在安装MySQL程序最后2步的3,4项就不动了. 这种情况一般是你以前安装过MySQL数据库服务项被占用了. 1.卸载MySQL 2.删除安装目录及数据存放目录 3. ...
- codeforces Gym 100286H Hell on the Markets
紫书上面的题,队友做的,WA了freopen..爆了int... UVA 1614 - Hell on the Markets 奇怪的股市(贪心,结论)
- equals和HashCode的羁绊
equals和hashcode我一直没弄明白到底怎么回事,今天终于弄懂了. 如下图: 在Person类没有重写equals和hashcode方法时,是如下情况: 但是当我重写了equals方法时,是如 ...