从本文开始,我们来分析rocketMq
消息接收、分发以及投递流程。
RocketMq
消息处理整个流程如下:
- 消息接收:消息接收是指接收
producer
的消息,处理类是SendMessageProcessor
,将消息写入到commigLog
文件后,接收流程处理完毕; - 消息分发:
broker
处理消息分发的类是ReputMessageService
,它会启动一个线程,不断地将commitLong
分到到对应的consumerQueue
,这一步操作会写两个文件:consumerQueue
与indexFile
,写入后,消息分发流程处理 完毕; - 消息投递:消息投递是指将消息发往
consumer
的流程,consumer
会发起获取消息的请求,broker
收到请求后,调用PullMessageProcessor
类处理,从consumerQueue
文件获取消息,返回给consumer
后,投递流程处理完毕。
以上就是rocketMq
处理消息的流程了,接下来我们就从源码来看相关流程的实现。
1. remotingServer
的启动流程
在正式分析接收与投递流程前,我们来了解下remotingServer
的启动。
remotingServer
是一个netty服务,他开启了一个端口用来处理producer
与consumer
的网络请求。
remotingServer
是在BrokerController#start
中启动的,代码如下:
public void start() throws Exception {
// 启动各组件
...
if (this.remotingServer != null) {
this.remotingServer.start();
}
...
}
复制代码
继续查看remotingServer
的启动流程,进入NettyRemotingServer#start
方法:
public void start() {
...
ServerBootstrap childHandler =
this.serverBootstrap.group(this.eventLoopGroupBoss, this.eventLoopGroupSelector)
...
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(defaultEventExecutorGroup,
HANDSHAKE_HANDLER_NAME, handshakeHandler)
.addLast(defaultEventExecutorGroup,
encoder,
new NettyDecoder(),
new IdleStateHandler(0, 0,
nettyServerConfig.getServerChannelMaxIdleTimeSeconds()),
connectionManageHandler,
// 处理业务请求的handler
serverHandler
);
}
});
...
}
复制代码
这就是一个标准的netty
服务启动流程了,套路与nameServer
的启动是一样的。关于netty
的相关内容,这里我们仅关注pipeline
上的channelHandler
,在netty
中,处理读写请求的操作为一个个ChannelHandler
,remotingServer
中处理读写请求的ChanelHandler
为NettyServerHandler
,代码如下:
@ChannelHandler.Sharable
class NettyServerHandler extends SimpleChannelInboundHandler<RemotingCommand> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, RemotingCommand msg) throws Exception {
processMessageReceived(ctx, msg);
}
}
复制代码
这块的操作与nameServer
对外提供的服务极相似(就是同一个类),最终调用的是NettyRemotingAbstract#processRequestCommand
方法:
public void processRequestCommand(final ChannelHandlerContext ctx, final RemotingCommand cmd) {
// 根据 code 从 processorTable 获取 Pair
final Pair<NettyRequestProcessor, ExecutorService> matched
= this.processorTable.get(cmd.getCode());
// 找不到默认值
final Pair<NettyRequestProcessor, ExecutorService> pair =
null == matched ? this.defaultRequestProcessor : matched;
...
// 从 pair 中拿到 Processor 进行处理
NettyRequestProcessor processor = pair.getObject1();
// 处理请求
RemotingCommand response = processor.processRequest(ctx, cmd);
....
}
复制代码
如果进入源码去看,会发现这个方法非常长,这里省略了异步处理、异常处理及返回值构造等,仅列出了关键步骤:
- 根据
code
从processorTable
拿到对应的Pair
- 从
Pair
里获取Processor
最终处理请求的就是Processor
了。
2. Processor
的注册
从上面的分析中可知, Processor
是处理消息的关键,它是从processorTable
中获取的,这个processorTable
是啥呢?
processorTable
是NettyRemotingAbstract
成员变量,里面的内容是BrokerController
在初始化时(执行BrokerController#initialize
方法)注册的。之前在分析BrokerController
的初始化流程时,就提到过Processor
的提供操作,这里再回顾下:
BrokerController
的初始化方法initialize
会调用 BrokerController#registerProcessor
,Processor
的注册操作就在这个方法里:
public class BrokerController {
private final PullMessageProcessor pullMessageProcessor;
/**
* 构造方法
*/
public BrokerController(...) {
// 处理 consumer 拉消息请求的
this.pullMessageProcessor = new PullMessageProcessor(this);
}
/**
* 注册操作
*/
public void registerProcessor() {
// SendMessageProcessor
SendMessageProcessor sendProcessor = new SendMessageProcessor(this);
sendProcessor.registerSendMessageHook(sendMessageHookList);
sendProcessor.registerConsumeMessageHook(consumeMessageHookList);
// 处理 Processor
this.remotingServer.registerProcessor(RequestCode.SEND_MESSAGE,
sendProcessor, this.sendMessageExecutor);
this.remotingServer.registerProcessor(RequestCode.SEND_MESSAGE_V2,
sendProcessor, this.sendMessageExecutor);
this.remotingServer.registerProcessor(RequestCode.SEND_BATCH_MESSAGE,
sendProcessor, this.sendMessageExecutor);
// PullMessageProcessor
this.remotingServer.registerProcessor(RequestCode.PULL_MESSAGE,
this.pullMessageProcessor, this.pullMessageExecutor);
// 省略其他许许多多的Processor注册
...
}
...
复制代码
需要指明的是,sendProcessor
用来处理producer
请求过来的消息,pullMessageProcessor
用来处理consumer
拉取消息的请求。
3. 接收producer
消息
了解完remotingServer
的启动与Processor
的注册内容后,接下来我们就可以分析接收producer
消息的流程了。
producer
发送消息到broker
时,发送的请求code
为SEND_MESSAGE
(RocketMQ源码5-producer 同步发送和单向发送 第1.4小节),根据上面的分析,当消息过来时,会使用NettyServerHandler
这个ChannelHandler
来处理,之后会调用到NettyRemotingAbstract#processRequestCommand
方法。
在NettyRemotingAbstract#processRequestCommand
方法中,会根据消息的code
获取对应的Processor
来处理,从Processor
的注册流程来看,处理该SEND_MESSAGE
的Processor
为SendMessageProcessor
,我们进入SendMessageProcessor#processRequest
看看它的流程:
public RemotingCommand processRequest(ChannelHandlerContext ctx,
RemotingCommand request) throws RemotingCommandException {
RemotingCommand response = null;
try {