public RegisterFilterServerResponseHeader registerFilterServerToBroker( //
      final String brokerAddr, // 1
      final String filterServerAddr // 2
      )
      throws RemotingCommandException, RemotingConnectException, RemotingSendRequestException,
          RemotingTimeoutException, InterruptedException, MQBrokerException {
    RegisterFilterServerRequestHeader requestHeader = new RegisterFilterServerRequestHeader();
    requestHeader.setFilterServerAddr(filterServerAddr);
    RemotingCommand request =
        RemotingCommand.createRequestCommand(RequestCode.REGISTER_FILTER_SERVER, requestHeader);

    RemotingCommand response = this.remotingClient.invokeSync(brokerAddr, request, 3000);
    assert response != null;
    switch (response.getCode()) {
      case ResponseCode.SUCCESS:
        {
          RegisterFilterServerResponseHeader responseHeader =
              (RegisterFilterServerResponseHeader)
                  response.decodeCommandCustomHeader(RegisterFilterServerResponseHeader.class);

          return responseHeader;
        }
      default:
        break;
    }

    throw new MQBrokerException(response.getCode(), response.getRemark());
  }
  private RemotingCommand updateAndCreateTopic(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final CreateTopicRequestHeader requestHeader =
        (CreateTopicRequestHeader)
            request.decodeCommandCustomHeader(CreateTopicRequestHeader.class);
    log.info(
        "updateAndCreateTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));

    // Topic名字是否与保留字段冲突
    if (requestHeader
        .getTopic()
        .equals(this.brokerController.getBrokerConfig().getBrokerClusterName())) {
      String errorMsg =
          "the topic[" + requestHeader.getTopic() + "] is conflict with system reserved words.";
      log.warn(errorMsg);
      response.setCode(ResponseCode.SYSTEM_ERROR_VALUE);
      response.setRemark(errorMsg);
      return response;
    }

    TopicConfig topicConfig = new TopicConfig(requestHeader.getTopic());
    topicConfig.setReadQueueNums(requestHeader.getReadQueueNums());
    topicConfig.setWriteQueueNums(requestHeader.getWriteQueueNums());
    topicConfig.setTopicFilterType(requestHeader.getTopicFilterTypeEnum());
    topicConfig.setPerm(requestHeader.getPerm());

    this.brokerController.getTopicConfigManager().updateTopicConfig(topicConfig);

    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
  private RemotingCommand registerMessageFilterClass(
      ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final RegisterMessageFilterClassRequestHeader requestHeader =
        (RegisterMessageFilterClassRequestHeader)
            request.decodeCommandCustomHeader(RegisterMessageFilterClassRequestHeader.class);

    try {
      boolean ok =
          this.filtersrvController
              .getFilterClassManager()
              .registerFilterClass(
                  requestHeader.getConsumerGroup(), //
                  requestHeader.getTopic(), //
                  requestHeader.getClassName(), //
                  requestHeader.getClassCRC(), //
                  request.getBody()); // Body传输的是Java Source,必须UTF-8编码
      if (!ok) {
        throw new Exception("registerFilterClass error");
      }
    } catch (Exception e) {
      response.setCode(ResponseCode.SYSTEM_ERROR);
      response.setRemark(RemotingHelper.exceptionSimpleDesc(e));
      return response;
    }

    response.setCode(ResponseCode.SUCCESS);
    response.setRemark(null);
    return response;
  }
  private RemotingCommand getTopicStatsInfo(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final GetTopicStatsInfoRequestHeader requestHeader =
        (GetTopicStatsInfoRequestHeader)
            request.decodeCommandCustomHeader(GetTopicStatsInfoRequestHeader.class);

    final String topic = requestHeader.getTopic();
    TopicConfig topicConfig =
        this.brokerController.getTopicConfigManager().selectTopicConfig(topic);
    if (null == topicConfig) {
      response.setCode(MQResponseCode.TOPIC_NOT_EXIST_VALUE);
      response.setRemark("topic[" + topic + "] not exist");
      return response;
    }

    TopicStatsTable topicStatsTable = new TopicStatsTable();
    for (int i = 0; i < topicConfig.getWriteQueueNums(); i++) {
      MessageQueue mq = new MessageQueue();
      mq.setTopic(topic);
      mq.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName());
      mq.setQueueId(i);

      TopicOffset topicOffset = new TopicOffset();
      long min = this.brokerController.getMessageStore().getMinOffsetInQuque(topic, i);
      if (min < 0) min = 0;

      long max = this.brokerController.getMessageStore().getMaxOffsetInQuque(topic, i);
      if (max < 0) max = 0;

      long timestamp = 0;
      if (max > 0) {
        timestamp =
            this.brokerController.getMessageStore().getMessageStoreTimeStamp(topic, i, (max - 1));
      }

      topicOffset.setMinOffset(min);
      topicOffset.setMaxOffset(max);
      topicOffset.setLastUpdateTimestamp(timestamp);

      topicStatsTable.getOffsetTable().put(mq, topicOffset);
    }

    byte[] body = topicStatsTable.encode();
    response.setBody(body);
    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
  private RemotingCommand deleteTopic(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    DeleteTopicRequestHeader requestHeader =
        (DeleteTopicRequestHeader)
            request.decodeCommandCustomHeader(DeleteTopicRequestHeader.class);

    log.info("deleteTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));

    this.brokerController.getTopicConfigManager().deleteTopicConfig(requestHeader.getTopic());

    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
  private RemotingCommand getConsumerConnectionList(
      ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final GetConsumerConnectionListRequestHeader requestHeader =
        (GetConsumerConnectionListRequestHeader)
            request.decodeCommandCustomHeader(GetConsumerConnectionListRequestHeader.class);

    ConsumerGroupInfo consumerGroupInfo =
        this.brokerController
            .getConsumerManager()
            .getConsumerGroupInfo(requestHeader.getConsumerGroup());
    if (consumerGroupInfo != null) {
      ConsumerConnection bodydata = new ConsumerConnection();
      bodydata.setConsumeFromWhere(consumerGroupInfo.getConsumeFromWhere());
      bodydata.setConsumeType(consumerGroupInfo.getConsumeType());
      bodydata.setMessageModel(consumerGroupInfo.getMessageModel());
      bodydata.getSubscriptionTable().putAll(consumerGroupInfo.getSubscriptionTable());

      Iterator<Map.Entry<Channel, ClientChannelInfo>> it =
          consumerGroupInfo.getChannelInfoTable().entrySet().iterator();
      while (it.hasNext()) {
        ClientChannelInfo info = it.next().getValue();
        Connection connection = new Connection();
        connection.setClientId(info.getClientId());
        connection.setLanguage(info.getLanguage());
        connection.setVersion(info.getVersion());
        connection.setClientAddr(RemotingHelper.parseChannelRemoteAddr(info.getChannel()));

        bodydata.getConnectionSet().add(connection);
      }

      byte[] body = bodydata.encode();
      response.setBody(body);
      response.setCode(ResponseCode.SUCCESS_VALUE);
      response.setRemark(null);

      return response;
    }

    response.setCode(MQResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST_VALUE);
    response.setRemark("the consumer group[" + requestHeader.getConsumerGroup() + "] not online");
    return response;
  }
  private RemotingCommand getEarliestMsgStoretime(
      ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response =
        RemotingCommand.createResponseCommand(GetEarliestMsgStoretimeResponseHeader.class);
    final GetEarliestMsgStoretimeResponseHeader responseHeader =
        (GetEarliestMsgStoretimeResponseHeader) response.getCustomHeader();
    final GetEarliestMsgStoretimeRequestHeader requestHeader =
        (GetEarliestMsgStoretimeRequestHeader)
            request.decodeCommandCustomHeader(GetEarliestMsgStoretimeRequestHeader.class);

    long timestamp =
        this.brokerController
            .getMessageStore()
            .getEarliestMessageTime(requestHeader.getTopic(), requestHeader.getQueueId());

    responseHeader.setTimestamp(timestamp);
    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
Example #8
0
  private RegisterBrokerResult registerBroker( //
      final String namesrvAddr, //
      final String clusterName, // 1
      final String brokerAddr, // 2
      final String brokerName, // 3
      final long brokerId, // 4
      final String haServerAddr, // 5
      final TopicConfigSerializeWrapper topicConfigWrapper // 6
      )
      throws RemotingCommandException, MQBrokerException, RemotingConnectException,
          RemotingSendRequestException, RemotingTimeoutException, InterruptedException {
    RegisterBrokerRequestHeader requestHeader = new RegisterBrokerRequestHeader();
    requestHeader.setBrokerAddr(brokerAddr);
    requestHeader.setBrokerId(brokerId);
    requestHeader.setBrokerName(brokerName);
    requestHeader.setClusterName(clusterName);
    requestHeader.setHaServerAddr(haServerAddr);
    RemotingCommand request =
        RemotingCommand.createRequestCommand(MQRequestCode.REGISTER_BROKER_VALUE, requestHeader);
    request.setBody(topicConfigWrapper.encode());

    RemotingCommand response = this.remotingClient.invokeSync(namesrvAddr, request, 3000);
    assert response != null;
    switch (response.getCode()) {
      case ResponseCode.SUCCESS_VALUE:
        {
          RegisterBrokerResponseHeader responseHeader =
              (RegisterBrokerResponseHeader)
                  response.decodeCommandCustomHeader(RegisterBrokerResponseHeader.class);
          RegisterBrokerResult result = new RegisterBrokerResult();
          result.setMasterAddr(responseHeader.getMasterAddr());
          result.setHaServerAddr(responseHeader.getHaServerAddr());
          return result;
        }
      default:
        break;
    }

    throw new MQBrokerException(response.getCode(), response.getRemark());
  }
  private RemotingCommand updateConsumerOffset(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response =
        RemotingCommand.createResponseCommand(UpdateConsumerOffsetResponseHeader.class);
    final UpdateConsumerOffsetResponseHeader responseHeader =
        (UpdateConsumerOffsetResponseHeader) response.getCustomHeader();
    final UpdateConsumerOffsetRequestHeader requestHeader =
        (UpdateConsumerOffsetRequestHeader)
            request.decodeCommandCustomHeader(UpdateConsumerOffsetRequestHeader.class);

    this.brokerController
        .getConsumerOffsetManager()
        .commitOffset(
            requestHeader.getConsumerGroup(),
            requestHeader.getTopic(),
            requestHeader.getQueueId(),
            requestHeader.getCommitOffset());
    UpdateCommitOffsetMoniter.printUpdatecommit(ctx.channel(), requestHeader);
    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
Example #10
0
  private RemotingCommand searchOffsetByTimestamp(
      ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response =
        RemotingCommand.createResponseCommand(SearchOffsetResponseHeader.class);
    final SearchOffsetResponseHeader responseHeader =
        (SearchOffsetResponseHeader) response.getCustomHeader();
    final SearchOffsetRequestHeader requestHeader =
        (SearchOffsetRequestHeader)
            request.decodeCommandCustomHeader(SearchOffsetRequestHeader.class);

    long offset =
        this.brokerController
            .getMessageStore()
            .getOffsetInQueueByTime(
                requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getTimestamp());

    responseHeader.setOffset(offset);

    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
  public RemotingCommand getConsumerListByGroup(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response =
        RemotingCommand.createResponseCommand(GetConsumerListByGroupResponseHeader.class);
    final GetConsumerListByGroupRequestHeader requestHeader =
        (GetConsumerListByGroupRequestHeader)
            request.decodeCommandCustomHeader(GetConsumerListByGroupRequestHeader.class);

    ConsumerGroupInfo consumerGroupInfo =
        this.brokerController
            .getConsumerManager()
            .getConsumerGroupInfo(requestHeader.getConsumerGroup());
    if (consumerGroupInfo != null) {
      List<String> clientIds = consumerGroupInfo.getAllClientId();
      if (!clientIds.isEmpty()) {
        GetConsumerListByGroupResponseBody body = new GetConsumerListByGroupResponseBody();
        body.setConsumerIdList(clientIds);
        response.setBody(body.encode());
        response.setCode(ResponseCode.SUCCESS);
        response.setRemark(null);
        return response;
      } else {
        log.warn(
            "getAllClientId failed, {} {}",
            requestHeader.getConsumerGroup(),
            RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
      }
    } else {
      log.warn(
          "getConsumerGroupInfo failed, {} {}",
          requestHeader.getConsumerGroup(),
          RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
    }

    response.setCode(ResponseCode.SYSTEM_ERROR);
    response.setRemark("no consumer for this group, " + requestHeader.getConsumerGroup());
    return response;
  }
Example #12
0
  private RemotingCommand getProducerConnectionList(
      ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final GetProducerConnectionListRequestHeader requestHeader =
        (GetProducerConnectionListRequestHeader)
            request.decodeCommandCustomHeader(GetProducerConnectionListRequestHeader.class);

    ConsumerConnection bodydata = new ConsumerConnection();
    HashMap<Channel, ClientChannelInfo> channelInfoHashMap =
        this.brokerController
            .getProducerManager()
            .getGroupChannelTable()
            .get(requestHeader.getProducerGroup());
    if (channelInfoHashMap != null) {
      Iterator<Map.Entry<Channel, ClientChannelInfo>> it = channelInfoHashMap.entrySet().iterator();
      while (it.hasNext()) {
        ClientChannelInfo info = it.next().getValue();
        Connection connection = new Connection();
        connection.setClientId(info.getClientId());
        connection.setLanguage(info.getLanguage());
        connection.setVersion(info.getVersion());
        connection.setClientAddr(RemotingHelper.parseChannelRemoteAddr(info.getChannel()));

        bodydata.getConnectionSet().add(connection);
      }

      byte[] body = bodydata.encode();
      response.setBody(body);
      response.setCode(ResponseCode.SUCCESS_VALUE);
      response.setRemark(null);
      return response;
    }

    response.setCode(ResponseCode.SYSTEM_ERROR_VALUE);
    response.setRemark("the producer group[" + requestHeader.getProducerGroup() + "] not exist");
    return response;
  }
  public RemotingCommand unregisterClient(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response =
        RemotingCommand.createResponseCommand(UnregisterClientResponseHeader.class);
    final UnregisterClientRequestHeader requestHeader =
        (UnregisterClientRequestHeader)
            request.decodeCommandCustomHeader(UnregisterClientRequestHeader.class);

    ClientChannelInfo clientChannelInfo =
        new ClientChannelInfo( //
            ctx.channel(), //
            requestHeader.getClientID(), //
            request.getLanguage(), //
            request.getVersion() //
            );

    // 注销Producer
    {
      final String group = requestHeader.getProducerGroup();
      if (group != null) {
        this.brokerController.getProducerManager().unregisterProducer(group, clientChannelInfo);
      }
    }

    // 注销Consumer
    {
      final String group = requestHeader.getConsumerGroup();
      if (group != null) {
        this.brokerController.getConsumerManager().unregisterConsumer(group, clientChannelInfo);
      }
    }

    response.setCode(ResponseCode.SUCCESS);
    response.setRemark(null);
    return response;
  }
Example #14
0
  private RemotingCommand queryConsumerOffset(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response =
        RemotingCommand.createResponseCommand(QueryConsumerOffsetResponseHeader.class);
    final QueryConsumerOffsetResponseHeader responseHeader =
        (QueryConsumerOffsetResponseHeader) response.getCustomHeader();
    final QueryConsumerOffsetRequestHeader requestHeader =
        (QueryConsumerOffsetRequestHeader)
            request.decodeCommandCustomHeader(QueryConsumerOffsetRequestHeader.class);

    long offset =
        this.brokerController
            .getConsumerOffsetManager()
            .queryOffset(
                requestHeader.getConsumerGroup(),
                requestHeader.getTopic(),
                requestHeader.getQueueId());

    // 订阅组存在
    if (offset >= 0) {
      responseHeader.setOffset(offset);
      response.setCode(ResponseCode.SUCCESS_VALUE);
      response.setRemark(null);
    }
    // 订阅组不存在
    else {
      // 新版本服务器不做消费进度纠正
      if (request.getVersion() >= MQVersion.Version.V3_0_6_SNAPSHOT.ordinal()) {
        response.setCode(MQResponseCode.QUERY_NOT_FOUND_VALUE);
        response.setRemark("Not found, V3_0_6_SNAPSHOT maybe this group consumer boot first");
      }

      // TODO:以下流程待所有客户端都升级后,可以删除此段代码
      else {
        long minOffset =
            this.brokerController
                .getMessageStore()
                .getMinOffsetInQuque(requestHeader.getTopic(), requestHeader.getQueueId());
        long maxOffset =
            this.brokerController
                .getMessageStore()
                .getMaxOffsetInQuque(requestHeader.getTopic(), requestHeader.getQueueId());

        boolean consumeFromMinEnable = false;
        if (0 == minOffset && maxOffset > 0) {
          long minCommitLogOffset =
              this.brokerController
                  .getMessageStore()
                  .getCommitLogOffsetInQueue(
                      requestHeader.getTopic(), requestHeader.getQueueId(), minOffset);
          long maxCommitLogOffset =
              this.brokerController
                  .getMessageStore()
                  .getCommitLogOffsetInQueue(
                      requestHeader.getTopic(), requestHeader.getQueueId(), maxOffset - 1);

          long memorySpan =
              (long)
                  (StoreUtil.TotalPhysicalMemorySize
                      * (this.brokerController
                              .getMessageStoreConfig()
                              .getAccessMessageInMemoryMaxRatio()
                          / 100.0));

          long diff = maxCommitLogOffset - minCommitLogOffset;
          if (diff < memorySpan) {
            consumeFromMinEnable = true;
            log.info(
                "the consumer group[{}] first subscribed, minOffset: {} maxOffset: {}, from min.", //
                requestHeader.getConsumerGroup(), //
                minOffset, //
                maxOffset);
          }
        } else if (minOffset > 0 && maxOffset > 0) {
          consumeFromMinEnable = false;
        } else {
          consumeFromMinEnable = true;
          log.info(
              "the consumer group[{}] first subscribed, minOffset: {} maxOffset: {}, from min, and unknow offset.", //
              requestHeader.getConsumerGroup(), //
              minOffset, //
              maxOffset);
        }

        // 说明这个队列在服务器存储的消息比较少或者没有消息
        // 订阅组消费进度不存在情况下,从0开始消费
        if (consumeFromMinEnable) {
          responseHeader.setOffset(0L);
          response.setCode(ResponseCode.SUCCESS_VALUE);
          response.setRemark(null);
        } else {
          response.setCode(MQResponseCode.QUERY_NOT_FOUND_VALUE);
          response.setRemark("Not found, maybe this group consumer boot first");
        }
      }
    }

    return response;
  }
Example #15
0
  private RemotingCommand getConsumeStats(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final GetConsumeStatsRequestHeader requestHeader =
        (GetConsumeStatsRequestHeader)
            request.decodeCommandCustomHeader(GetConsumeStatsRequestHeader.class);

    ConsumeStats consumeStats = new ConsumeStats();

    Set<String> topics =
        this.brokerController
            .getConsumerOffsetManager()
            .whichTopicByConsumer(requestHeader.getConsumerGroup());

    for (String topic : topics) {
      TopicConfig topicConfig =
          this.brokerController.getTopicConfigManager().selectTopicConfig(topic);
      if (null == topicConfig) {
        response.setCode(MQResponseCode.TOPIC_NOT_EXIST_VALUE);
        response.setRemark("topic[" + topic + "] not exist");
        return response;
      }

      for (int i = 0; i < topicConfig.getWriteQueueNums(); i++) {
        MessageQueue mq = new MessageQueue();
        mq.setTopic(topic);
        mq.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName());
        mq.setQueueId(i);

        OffsetWrapper offsetWrapper = new OffsetWrapper();

        long brokerOffset = this.brokerController.getMessageStore().getMaxOffsetInQuque(topic, i);
        if (brokerOffset < 0) brokerOffset = 0;

        long consumerOffset =
            this.brokerController
                .getConsumerOffsetManager()
                .queryOffset( //
                    requestHeader.getConsumerGroup(), //
                    topic, //
                    i);
        if (consumerOffset < 0) consumerOffset = 0;

        offsetWrapper.setBrokerOffset(brokerOffset);
        offsetWrapper.setConsumerOffset(consumerOffset);

        // 查询消费者最后一条消息对应的时间戳
        long timeOffset = consumerOffset - 1;
        if (timeOffset >= 0) {
          long lastTimestamp =
              this.brokerController
                  .getMessageStore()
                  .getMessageStoreTimeStamp(topic, i, timeOffset);
          if (lastTimestamp > 0) {
            offsetWrapper.setLastTimestamp(lastTimestamp);
          }
        }

        consumeStats.getOffsetTable().put(mq, offsetWrapper);
      }

      long consumeTps =
          this.brokerController
              .getConsumerOffsetManager()
              .computePullTPS(topic, requestHeader.getConsumerGroup());

      consumeTps += consumeStats.getConsumeTps();
      consumeStats.setConsumeTps(consumeTps);
    }

    byte[] body = consumeStats.encode();
    response.setBody(body);
    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
  private RemotingCommand pullMessageForward(
      final ChannelHandlerContext ctx, final RemotingCommand request) throws Exception {
    final RemotingCommand response =
        RemotingCommand.createResponseCommand(PullMessageResponseHeader.class);
    final PullMessageResponseHeader responseHeader =
        (PullMessageResponseHeader) response.readCustomHeader();
    final PullMessageRequestHeader requestHeader =
        (PullMessageRequestHeader)
            request.decodeCommandCustomHeader(PullMessageRequestHeader.class);

    // 由于异步返回,所以必须要设置
    response.setOpaque(request.getOpaque());

    DefaultMQPullConsumer pullConsumer = this.filtersrvController.getDefaultMQPullConsumer();
    final FilterClassInfo findFilterClass =
        this.filtersrvController
            .getFilterClassManager()
            .findFilterClass(requestHeader.getConsumerGroup(), requestHeader.getTopic());
    if (null == findFilterClass) {
      response.setCode(ResponseCode.SYSTEM_ERROR);
      response.setRemark("Find Filter class failed, not registered");
      return response;
    }

    if (null == findFilterClass.getMessageFilter()) {
      response.setCode(ResponseCode.SYSTEM_ERROR);
      response.setRemark("Find Filter class failed, registered but no class");
      return response;
    }

    responseHeader.setSuggestWhichBrokerId(MixAll.MASTER_ID);

    // 构造从Broker拉消息的参数
    MessageQueue mq = new MessageQueue();
    mq.setTopic(requestHeader.getTopic());
    mq.setQueueId(requestHeader.getQueueId());
    mq.setBrokerName(this.filtersrvController.getBrokerName());
    long offset = requestHeader.getQueueOffset();
    int maxNums = requestHeader.getMaxMsgNums();

    final PullCallback pullCallback =
        new PullCallback() {

          @Override
          public void onSuccess(PullResult pullResult) {
            responseHeader.setMaxOffset(pullResult.getMaxOffset());
            responseHeader.setMinOffset(pullResult.getMinOffset());
            responseHeader.setNextBeginOffset(pullResult.getNextBeginOffset());
            response.setRemark(null);

            switch (pullResult.getPullStatus()) {
              case FOUND:
                response.setCode(ResponseCode.SUCCESS);

                List<MessageExt> msgListOK = new ArrayList<MessageExt>();
                try {
                  for (MessageExt msg : pullResult.getMsgFoundList()) {
                    boolean match = findFilterClass.getMessageFilter().match(msg);
                    if (match) {
                      msgListOK.add(msg);
                    }
                  }

                  // 有消息返回
                  if (!msgListOK.isEmpty()) {
                    returnResponse(
                        requestHeader.getConsumerGroup(),
                        requestHeader.getTopic(),
                        ctx,
                        response,
                        msgListOK);
                    return;
                  }
                  // 全部都被过滤掉了
                  else {
                    response.setCode(ResponseCode.PULL_RETRY_IMMEDIATELY);
                  }
                }
                // 只要抛异常,就终止过滤,并返回客户端异常
                catch (Throwable e) {
                  final String error =
                      String.format(
                          "do Message Filter Exception, ConsumerGroup: %s Topic: %s ",
                          requestHeader.getConsumerGroup(), requestHeader.getTopic());
                  log.error(error, e);

                  response.setCode(ResponseCode.SYSTEM_ERROR);
                  response.setRemark(error + RemotingHelper.exceptionSimpleDesc(e));
                  returnResponse(
                      requestHeader.getConsumerGroup(),
                      requestHeader.getTopic(),
                      ctx,
                      response,
                      null);
                  return;
                }

                break;
              case NO_MATCHED_MSG:
                response.setCode(ResponseCode.PULL_RETRY_IMMEDIATELY);
                break;
              case NO_NEW_MSG:
                response.setCode(ResponseCode.PULL_NOT_FOUND);
                break;
              case OFFSET_ILLEGAL:
                response.setCode(ResponseCode.PULL_OFFSET_MOVED);
                break;
              default:
                break;
            }

            returnResponse(
                requestHeader.getConsumerGroup(), requestHeader.getTopic(), ctx, response, null);
          }

          @Override
          public void onException(Throwable e) {
            response.setCode(ResponseCode.SYSTEM_ERROR);
            response.setRemark("Pull Callback Exception, " + RemotingHelper.exceptionSimpleDesc(e));
            returnResponse(
                requestHeader.getConsumerGroup(), requestHeader.getTopic(), ctx, response, null);
            return;
          }
        };

    pullConsumer.pullBlockIfNotFound(mq, null, offset, maxNums, pullCallback);

    return null;
  }