All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.rocketmq.client.consumer.store.RemoteBrokerOffsetStore Maven / Gradle / Ivy

There is a newer version: 3.6.2.Final
Show newest version
/**
 * Copyright (C) 2010-2013 Alibaba Group Holding Limited
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.rocketmq.client.consumer.store; import com.alibaba.rocketmq.client.exception.MQBrokerException; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.client.impl.FindBrokerResult; import com.alibaba.rocketmq.client.impl.factory.MQClientInstance; import com.alibaba.rocketmq.client.log.ClientLogger; import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.UtilAll; import com.alibaba.rocketmq.common.message.MessageQueue; import com.alibaba.rocketmq.common.protocol.header.QueryConsumerOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetRequestHeader; import com.alibaba.rocketmq.remoting.exception.RemotingException; import org.slf4j.Logger; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; /** * Remote storage implementation * * @author shijia.wxr * @since 2013-7-24 */ public class RemoteBrokerOffsetStore implements OffsetStore { private final static Logger log = ClientLogger.getLog(); private final MQClientInstance mQClientFactory; private final String groupName; private ConcurrentHashMap offsetTable = new ConcurrentHashMap(); public RemoteBrokerOffsetStore(MQClientInstance mQClientFactory, String groupName) { this.mQClientFactory = mQClientFactory; this.groupName = groupName; } @Override public void load() { } @Override public void updateOffset(MessageQueue mq, long offset, boolean increaseOnly) { if (mq != null) { AtomicLong offsetOld = this.offsetTable.get(mq); if (null == offsetOld) { offsetOld = this.offsetTable.putIfAbsent(mq, new AtomicLong(offset)); } if (null != offsetOld) { if (increaseOnly) { MixAll.compareAndIncreaseOnly(offsetOld, offset); } else { offsetOld.set(offset); } } } } @Override public long readOffset(final MessageQueue mq, final ReadOffsetType type) { if (mq != null) { switch (type) { case MEMORY_FIRST_THEN_STORE: case READ_FROM_MEMORY: { AtomicLong offset = this.offsetTable.get(mq); if (offset != null) { return offset.get(); } else if (ReadOffsetType.READ_FROM_MEMORY == type) { return -1; } } case READ_FROM_STORE: { try { long brokerOffset = this.fetchConsumeOffsetFromBroker(mq); AtomicLong offset = new AtomicLong(brokerOffset); this.updateOffset(mq, offset.get(), false); return brokerOffset; } // No offset in broker catch (MQBrokerException e) { return -1; } //Other exceptions catch (Exception e) { log.warn("fetchConsumeOffsetFromBroker exception, " + mq, e); return -2; } } default: break; } } return -1; } @Override public void persistAll(Set mqs) { if (null == mqs || mqs.isEmpty()) return; final HashSet unusedMQ = new HashSet(); if (mqs != null && !mqs.isEmpty()) { for (MessageQueue mq : this.offsetTable.keySet()) { AtomicLong offset = this.offsetTable.get(mq); if (offset != null) { if (mqs.contains(mq)) { try { this.updateConsumeOffsetToBroker(mq, offset.get()); log.info("[persistAll] Group: {} ClientId: {} updateConsumeOffsetToBroker {} {}", // this.groupName,// this.mQClientFactory.getClientId(),// mq, // offset.get()); } catch (Exception e) { log.error("updateConsumeOffsetToBroker exception, " + mq.toString(), e); } } else { unusedMQ.add(mq); } } } } if (!unusedMQ.isEmpty()) { for (MessageQueue mq : unusedMQ) { this.offsetTable.remove(mq); log.info("remove unused mq, {}, {}", mq, this.groupName); } } } @Override public void persist(MessageQueue mq) { AtomicLong offset = this.offsetTable.get(mq); if (offset != null) { try { this.updateConsumeOffsetToBroker(mq, offset.get()); log.info("[persist] Group: {} ClientId: {} updateConsumeOffsetToBroker {} {}", // this.groupName,// this.mQClientFactory.getClientId(),// mq, // offset.get()); } catch (Exception e) { log.error("updateConsumeOffsetToBroker exception, " + mq.toString(), e); } } } public void removeOffset(MessageQueue mq) { if (mq != null) { this.offsetTable.remove(mq); log.info("remove unnecessary messageQueue offset. mq={}, offsetTableSize={}", mq, offsetTable.size()); } } @Override public Map cloneOffsetTable(String topic) { Map cloneOffsetTable = new HashMap(); Iterator iterator = this.offsetTable.keySet().iterator(); while (iterator.hasNext()) { MessageQueue mq = iterator.next(); if (!UtilAll.isBlank(topic) && !topic.equals(mq.getTopic())) { continue; } cloneOffsetTable.put(mq, this.offsetTable.get(mq).get()); } return cloneOffsetTable; } /** * Update the Consumer Offset, once the Master is off, updated to Slave, * here need to be optimized. */ private void updateConsumeOffsetToBroker(MessageQueue mq, long offset) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { FindBrokerResult findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); if (null == findBrokerResult) { // TODO Here may be heavily overhead for Name Server,need tuning this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); } if (findBrokerResult != null) { UpdateConsumerOffsetRequestHeader requestHeader = new UpdateConsumerOffsetRequestHeader(); requestHeader.setTopic(mq.getTopic()); requestHeader.setConsumerGroup(this.groupName); requestHeader.setQueueId(mq.getQueueId()); requestHeader.setCommitOffset(offset); this.mQClientFactory.getMQClientAPIImpl().updateConsumerOffsetOneway( findBrokerResult.getBrokerAddr(), requestHeader, 1000 * 5); } else { throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null); } } private long fetchConsumeOffsetFromBroker(MessageQueue mq) throws RemotingException, MQBrokerException, InterruptedException, MQClientException { FindBrokerResult findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); if (null == findBrokerResult) { // TODO Here may be heavily overhead for Name Server,need tuning this.mQClientFactory.updateTopicRouteInfoFromNameServer(mq.getTopic()); findBrokerResult = this.mQClientFactory.findBrokerAddressInAdmin(mq.getBrokerName()); } if (findBrokerResult != null) { QueryConsumerOffsetRequestHeader requestHeader = new QueryConsumerOffsetRequestHeader(); requestHeader.setTopic(mq.getTopic()); requestHeader.setConsumerGroup(this.groupName); requestHeader.setQueueId(mq.getQueueId()); return this.mQClientFactory.getMQClientAPIImpl().queryConsumerOffset( findBrokerResult.getBrokerAddr(), requestHeader, 1000 * 5); } else { throw new MQClientException("The broker[" + mq.getBrokerName() + "] not exist", null); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy