RocketMQ-2.RocketMQのロードバランシング

RocketMQのロードバランシング

プロデューサーMessageQueueのロードバランシング


デバッグコード、いわゆるを通じて知ることができるMessageQueueブローカーのキュー情報、各トピックは、作成時に対応するキューの数を指定することができます。すなわち、主ブローカ複数の格納されたメッセージのトピックであります

プロデューサーのロードバランシング

対応するプライマリブローカーの選択に均衡生産者側の負担。プロデューサーは、ブローカーにルーティングされ、最後に表示されるメッセージのメッセージを送信するときにルーティング。:で言うにメッセージを送信するには、次の2つの主要な方法は系统计算路由MessageQueue自定义路由MessageQueue

システムは、ルートを計算メッセージキュー

 SendResult send = producer.send(message, 60 * 1000);

ルートを計算するためのアルゴリズムをルーティングする他のシステムメッセージキュー

    public MessageQueue selectOneMessageQueue(final TopicPublishInfo tpInfo, final String lastBrokerName) {
        if (this.sendLatencyFaultEnable) {
            try {
                int index = tpInfo.getSendWhichQueue().getAndIncrement();
                for (int i = 0; i < tpInfo.getMessageQueueList().size(); i++) {
                    int pos = Math.abs(index++) % tpInfo.getMessageQueueList().size();
                    if (pos < 0)
                        pos = 0;
                    MessageQueue mq = tpInfo.getMessageQueueList().get(pos);
                    if (latencyFaultTolerance.isAvailable(mq.getBrokerName())) {
                        if (null == lastBrokerName || mq.getBrokerName().equals(lastBrokerName))
                            return mq;
                    }
                }

                final String notBestBroker = latencyFaultTolerance.pickOneAtLeast();
                int writeQueueNums = tpInfo.getQueueIdByBroker(notBestBroker);
                if (writeQueueNums > 0) {
                    final MessageQueue mq = tpInfo.selectOneMessageQueue();
                    if (notBestBroker != null) {
                        mq.setBrokerName(notBestBroker);
                        mq.setQueueId(tpInfo.getSendWhichQueue().getAndIncrement() % writeQueueNums);
                    }
                    return mq;
                } else {
                    latencyFaultTolerance.remove(notBestBroker);
                }
            } catch (Exception e) {
                log.error("Error occurred when selecting message queue", e);
            }

            return tpInfo.selectOneMessageQueue();
        }
        
        // 默认策略(路由到当前的broker主节点列表取模后的broker中)
        return tpInfo.selectOneMessageQueue(lastBrokerName);
    }

カスタムメッセージキューをルーティング

   SendResult send = producer.send(message, new MessageQueueSelector() {
                /**
                 *
                 * @param mqs 通过name server返回的broker主节点列表
                 * @param msg 当前消息
                 * @param arg
                 * @return
                 */
                @Override
                public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
                    int size = mqs.size();
                    long timeMillis = System.currentTimeMillis();

                    return mqs.get((int)timeMillis % size);
                }
            }, 60 * 1000);

消費者の負荷分散

設定し、消費者側が政策のバランスをとるための責任があります

ではconsumer.statrt()では上のメッセージキュー、消費者は、ロードバランシングのトピックをサブスクライブしているDefaultConsumerPushImpl.start()中でthis.rebalanceImpl.setAllocateMessageQueueStrategy(this.defaultMQPushConsumer.getAllocateMessageQueueStrategy());デフォルトに戻りAllocateMessageQueueAveragely

戦略のバランスを取るための責任

  1. AllocateMessageQueueAveragely

バランシング時間のロード

 // RebalanceService
 @Override
    public void run() {
        log.info(this.getServiceName() + " service started");

        while (!this.isStopped()) {
            this.waitForRunning(waitInterval);
            // 开始进行分配
            this.mqClientFactory.doRebalance();
        }

        log.info(this.getServiceName() + " service end");
    }

実現

/**
consumerGroup : 消费组名称
currentCID:当前消费者实例Id(随机数)
mqAll: 该topic对应的queue的信息列表
cidAll: 消费组中所有的消费者列表

*/
@Override
public List<MessageQueue> allocate(String consumerGroup, String currentCID, List<MessageQueue> mqAll,
    List<String> cidAll) {
    if (currentCID == null || currentCID.length() < 1) {
        throw new IllegalArgumentException("currentCID is empty");
    }
    if (mqAll == null || mqAll.isEmpty()) {
        throw new IllegalArgumentException("mqAll is null or mqAll empty");
    }
    if (cidAll == null || cidAll.isEmpty()) {
        throw new IllegalArgumentException("cidAll is null or cidAll empty");
    }

    List<MessageQueue> result = new ArrayList<MessageQueue>();
    if (!cidAll.contains(currentCID)) {
        log.info("[BUG] ConsumerGroup: {} The consumerId: {} not in cidAll: {}",
            consumerGroup,
            currentCID,
            cidAll);
        return result;
    }

    int index = cidAll.indexOf(currentCID);
    int mod = mqAll.size() % cidAll.size();
    int averageSize =
        mqAll.size() <= cidAll.size() ? 1 : (mod > 0 && index < mod ? mqAll.size() / cidAll.size()
            + 1 : mqAll.size() / cidAll.size());
    int startIndex = (mod > 0 && index < mod) ? index * averageSize : index * averageSize + mod;
    int range = Math.min(averageSize, mqAll.size() - startIndex);
    for (int i = 0; i < range; i++) {
        result.add(mqAll.get((startIndex + i) % mqAll.size()));
    }
    return result;
}

おすすめ

転載: www.cnblogs.com/KevinStark/p/12497214.html