RocketMQ源码12-broker 消息投递流程(处理PULL_MESSAGE请求)

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

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

以上就是rocketMq处理消息的流程了,接下来我们就从源码来分析消息投递的实现。

1. 处理PULL_MESSAGE请求

producer不同,consumerbroker拉取消息时,发送的请求codePULL_MESSAGEprocessorPullMessageProcessor,我们直接进入它的processRequest方法:

@Override
public RemotingCommand processRequest(final ChannelHandlerContext ctx, RemotingCommand request)
        throws RemotingCommandException {
    // 调用方法
    return this.processRequest(ctx.channel(), request, true);
}
复制代码

这个方法就只是调用了一个重载方法,多出来的参数true表示允许broker挂起请求,我们继续,

/**
 * 继续处理
 */
private RemotingCommand processRequest(final Channel channel, RemotingCommand request, 
        boolean brokerAllowSuspend)throws RemotingCommandException {

    RemotingCommand response = RemotingCommand
        .createResponseCommand(PullMessageResponseHeader.class);
    final PullMessageResponseHeader responseHeader 
        = (PullMessageResponseHeader) response.readCustomHeader();
    final PullMessageRequestHeader requestHeader = (PullMessageRequestHeader) 
        request.decodeCommandCustomHeader(PullMessageRequestHeader.class);

    response.setOpaque(request.getOpaque());

    // 省略权限校验流程
    // 1. rocketMq 可以设置校验信息,以阻挡非法客户端的连接
    // 2. 同时,对topic可以设置DENY(拒绝)、ANY(PUB 或者 SUB 权限)、PUB(发送权限)、SUB(订阅权限)等权限,
    //    可以细粒度控制客户端对topic的操作内容
    ...

    // 获取订阅组
    SubscriptionGroupConfig subscriptionGroupConfig =
        this.brokerController.getSubscriptionGroupManager()
        .findSubscriptionGroupConfig(requestHeader.getConsumerGroup());
    ...

    // 获取订阅主题
    TopicConfig topicConfig = this.brokerController.getTopicConfigManager()
        .selectTopicConfig(requestHeader.getTopic());
    ...

    // 处理filter
    // consumer在订阅消息时,可以对订阅的消息进行过滤,过滤方法有两种:tag与sql92
    // 这里我们重点关注拉取消息的流程,具体的过滤细节后面再分析
    ...

    // 获取消息
    // 1. 根据 topic 与 queueId 获取 ConsumerQueue 文件
    // 2. 根据 ConsumerQueue 文件的信息,从 CommitLog 中获取消息内容
    final GetMessageResult getMessageResult = this.brokerController.getMessageStore().getMessage(
        requestHeader.getConsumerGroup(), requestHeader.getTopic(), requestHeader.getQueueId(), 
        requestHeader.getQueueOffset(), requestHeader.getMaxMsgNums(), messageFilter);
    if (getMessageResult != null) {
        // 省略一大堆的校验过程
        ...

        switch (response.getCode()) {
            // 表示消息可以处理,这里会把消息内容写入到 response 中
            case ResponseCode.SUCCESS:
                ...
                // 处理消息消息内容,就是把消息从 getMessageResult 读出来,放到 response 中
                if (this.brokerController.getBrokerConfig().isTransferMsgByHeap()) {
                    final long beginTimeMills = this.brokerController.getMessageStore().now();
                    // 将消息内容转为byte数组
                    final byte[] r = this.readGetMessageResult(getMessageResult, 
                        requestHeader.getConsumerGroup(), requestHeader.getTopic(), 
                        requestHeader.getQueueId());
                    ...
                    response.setBody(r);
                } else {
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值