RocketMQ源码:broker 消息接收流程(写入commitLog)

从本文开始,我们来分析rocketMq消息接收、分发以及投递流程。

RocketMq消息处理整个流程如下:

  1. 消息接收:消息接收是指接收producer的消息,处理类是SendMessageProcessor,将消息写入到commigLog文件后,接收流程处理完毕;
  2. 消息分发:broker处理消息分发的类是ReputMessageService,它会启动一个线程,不断地将commitLong分到到对应的consumerQueue,这一步操作会写两个文件:consumerQueueindexFile,写入后,消息分发流程处理 完毕;
  3. 消息投递:消息投递是指将消息发往consumer的流程,consumer会发起获取消息的请求,broker收到请求后,调用PullMessageProcessor类处理,从consumerQueue文件获取消息,返回给consumer后,投递流程处理完毕。

以上就是rocketMq处理消息的流程了,接下来我们就从源码来看相关流程的实现。

1. remotingServer的启动流程

在正式分析接收与投递流程前,我们来了解下remotingServer的启动。

remotingServer是一个netty服务,他开启了一个端口用来处理producerconsumer的网络请求。

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中,处理读写请求的操作为一个个ChannelHandlerremotingServer中处理读写请求的ChanelHandlerNettyServerHandler,代码如下:

 @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);

    ....
 }

复制代码

如果进入源码去看,会发现这个方法非常长,这里省略了异步处理、异常处理及返回值构造等,仅列出了关键步骤:

  1. 根据codeprocessorTable拿到对应的Pair
  2. Pair里获取Processor

最终处理请求的就是Processor了。

2. Processor的注册

从上面的分析中可知, Processor是处理消息的关键,它是从processorTable中获取的,这个processorTable是啥呢?

processorTableNettyRemotingAbstract成员变量,里面的内容是BrokerController在初始化时(执行BrokerController#initialize方法)注册的。之前在分析BrokerController的初始化流程时,就提到过Processor的提供操作,这里再回顾下:

BrokerController的初始化方法initialize会调用 BrokerController#registerProcessorProcessor的注册操作就在这个方法里:

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时,发送的请求codeSEND_MESSAGERocketMQ源码5-producer 同步发送和单向发送 第1.4小节),根据上面的分析,当消息过来时,会使用NettyServerHandler这个ChannelHandler来处理,之后会调用到NettyRemotingAbstract#processRequestCommand方法。

NettyRemotingAbstract#processRequestCommand方法中,会根据消息的code获取对应的Processor来处理,从Processor的注册流程来看,处理该SEND_MESSAGEProcessorSendMessageProcessor,我们进入SendMessageProcessor#processRequest看看它的流程:

public RemotingCommand processRequest(ChannelHandlerContext ctx,
        RemotingCommand request) throws RemotingCommandException {
    RemotingCommand response = null;
    t
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值