You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by ji...@apache.org on 2022/03/14 06:52:25 UTC
[rocketmq] 04/07: feature(broker & acl & client):[RIP-32]Support Slave Acting Master mode (#3978)
This is an automated email from the ASF dual-hosted git repository.
jinrongtong pushed a commit to branch 5.0.0-beta-tmp
in repository https://gitbox.apache.org/repos/asf/rocketmq.git
commit cad0cfcecef88958b103059aea7b98395850226a
Author: rongtong <ji...@163.com>
AuthorDate: Mon Mar 14 14:06:45 2022 +0800
feature(broker & acl & client):[RIP-32]Support Slave Acting Master mode (#3978)
---
.../rocketmq/acl/common/AclClientRPCHook.java | 4 +
acl/src/test/resources/conf/plain_acl.yml | 17 -
broker/pom.xml | 12 +-
.../apache/rocketmq/broker/BrokerController.java | 1407 +++++++++++++-------
.../org/apache/rocketmq/broker/BrokerStartup.java | 58 +-
...merIdsChangeListener.java => ShutdownHook.java} | 12 +-
.../broker/client/ClientHousekeepingService.java | 12 +-
.../rocketmq/broker/client/ConsumerGroupInfo.java | 25 +-
.../broker/client/ConsumerIdsChangeListener.java | 2 +
.../rocketmq/broker/client/ConsumerManager.java | 42 +-
.../client/DefaultConsumerIdsChangeListener.java | 68 +-
.../rocketmq/broker/client/ProducerManager.java | 23 +-
.../rocketmq/broker/client/net/Broker2Client.java | 8 +-
.../client/rebalance/RebalanceLockManager.java | 90 +-
.../broker/dledger/DLedgerRoleChangeHandler.java | 86 +-
.../rocketmq/broker/failover/EscapeBridge.java | 268 ++++
.../broker/filtersrv/FilterServerManager.java | 6 +-
.../rocketmq/broker/latency/BrokerFastFailure.java | 44 +-
.../broker/loadbalance/AssignmentManager.java | 27 +-
.../broker/longpolling/ManyPullRequest.java | 4 +
.../{PopRequest.java => NotificationRequest.java} | 42 +-
.../longpolling/NotifyMessageArrivingListener.java | 11 +-
.../rocketmq/broker/longpolling/PopRequest.java | 4 +-
.../broker/longpolling/PullRequestHoldService.java | 36 +-
.../broker/mqtrace/AbortProcessException.java | 69 +
.../broker/mqtrace/ConsumeMessageContext.java | 77 +-
.../broker/mqtrace/SendMessageContext.java | 102 +-
.../broker/offset/ConsumerOffsetManager.java | 85 +-
.../apache/rocketmq/broker/out/BrokerOuterAPI.java | 566 +++++++-
.../broker/pagecache/OneMessageTransfer.java | 1 +
.../broker/plugin/AbstractPluginMessageStore.java | 286 +++-
.../broker/plugin/BrokerAttachedPlugin.java | 74 +
.../broker/plugin/MessageStoreFactory.java | 15 +-
.../broker/plugin/MessageStorePluginContext.java | 16 +-
.../broker/plugin/PullMessageResultHandler.java | 53 +
.../processor/AbstractSendMessageProcessor.java | 378 +++++-
.../broker/processor/AckMessageProcessor.java | 74 +-
.../broker/processor/AdminBrokerProcessor.java | 635 +++++++--
.../processor/ChangeInvisibleTimeProcessor.java | 31 +-
.../broker/processor/ClientManageProcessor.java | 51 +-
.../broker/processor/ConsumerManageProcessor.java | 26 +-
.../processor/DefaultPullMessageResultHandler.java | 244 ++++
.../broker/processor/EndTransactionProcessor.java | 9 +-
.../broker/processor/ForwardRequestProcessor.java | 3 +-
.../broker/processor/NotificationProcessor.java | 318 +++++
.../broker/processor/PeekMessageProcessor.java | 271 ++++
.../broker/processor/PollingInfoProcessor.java | 119 ++
.../broker/processor/PopBufferMergeService.java | 111 +-
.../broker/processor/PopMessageProcessor.java | 227 ++--
.../broker/processor/PopReviveService.java | 136 +-
.../broker/processor/PullMessageProcessor.java | 400 +++---
.../broker/processor/QueryMessageProcessor.java | 14 +-
.../broker/processor/ReplyMessageProcessor.java | 13 +-
.../SendMessageCallback.java} | 15 +-
.../broker/processor/SendMessageProcessor.java | 593 +++------
.../schedule/DelayOffsetSerializeWrapper.java | 45 +
.../broker/schedule/ScheduleMessageService.java | 851 ++++++++++++
.../rocketmq/broker/slave/SlaveSynchronize.java | 28 +-
.../subscription/SubscriptionGroupManager.java | 112 +-
.../rocketmq/broker/topic/TopicConfigManager.java | 150 ++-
.../topic/TopicQueueMappingCleanService.java | 3 +
.../broker/topic/TopicQueueMappingManager.java | 4 +-
.../AbstractTransactionalMessageCheckListener.java | 45 +-
.../broker/transaction/OperationResult.java | 8 +-
.../TransactionalMessageCheckService.java | 3 +
.../transaction/TransactionalMessageService.java | 2 +-
.../DefaultTransactionalMessageCheckListener.java | 2 +-
.../queue/TransactionalMessageBridge.java | 2 +-
.../queue/TransactionalMessageServiceImpl.java | 2 +-
.../org/apache/rocketmq/broker/util/HookUtils.java | 164 +++
.../org/apache/rocketmq/broker/util/MsgUtil.java | 4 +-
.../rocketmq/broker/BrokerControllerTest.java | 3 +-
.../apache/rocketmq/broker/BrokerOuterAPITest.java | 33 +-
.../broker/filter/MessageStoreWithFilterTest.java | 56 +-
.../broker/offset/ConsumerOffsetManagerTest.java | 38 +
.../AbstractSendMessageProcessorTest.java | 2 -
.../broker/processor/AckMessageProcessorTest.java | 15 +-
.../broker/processor/AdminBrokerProcessorTest.java | 43 +-
.../ChangeInvisibleTimeProcessorTest.java | 11 +-
.../processor/ClientManageProcessorTest.java | 1 -
.../processor/ConsumerManageProcessorTest.java | 91 ++
.../processor/EndTransactionProcessorTest.java | 2 +-
.../processor/PopBufferMergeServiceTest.java | 8 +-
.../broker/processor/PopMessageProcessorTest.java | 9 +-
.../broker/processor/PullMessageProcessorTest.java | 18 +-
.../processor/QueryAssignmentProcessorTest.java | 1 -
.../processor/ReplyMessageProcessorTest.java | 2 +-
.../broker/processor/SendMessageProcessorTest.java | 206 ++-
.../schedule/ScheduleMessageServiceTest.java | 287 ++++
.../broker/substription/ForbiddenTest.java | 64 +
.../broker/topic/TopicConfigManagerTest.java | 7 +-
...faultTransactionalMessageCheckListenerTest.java | 2 +-
.../queue/TransactionalMessageBridgeTest.java | 2 +-
.../queue/TransactionalMessageServiceImplTest.java | 2 +-
.../rocketmq/broker/util/ServiceProviderTest.java | 7 +-
.../util/TransactionalMessageServiceImpl.java | 2 +-
.../rocketmq/client/impl/BaseInvokeCallback.java | 1 +
.../client/impl/ClientRemotingProcessor.java | 3 +-
.../apache/rocketmq/client/impl/MQAdminImpl.java | 44 +-
.../rocketmq/client/impl/MQClientAPIImpl.java | 289 +++-
.../client/impl/factory/MQClientInstance.java | 16 +-
.../impl/producer/DefaultMQProducerImpl.java | 1 -
.../client/producer/DefaultMQProducer.java | 6 +-
.../consumer/DefaultLitePullConsumerTest.java | 2 +-
.../rocketmq/client/impl/MQClientAPIImplTest.java | 1 -
.../consumer/DefaultMQPushConsumerImplTest.java | 6 -
.../client/producer/DefaultMQProducerTest.java | 2 +-
.../selector/SelectMessageQueueRetryTest.java | 1 -
.../trace/TransactionMQProducerWithTraceTest.java | 11 +-
109 files changed, 7872 insertions(+), 2168 deletions(-)
diff --git a/acl/src/main/java/org/apache/rocketmq/acl/common/AclClientRPCHook.java b/acl/src/main/java/org/apache/rocketmq/acl/common/AclClientRPCHook.java
index 9e5bf1f..50c73ca 100644
--- a/acl/src/main/java/org/apache/rocketmq/acl/common/AclClientRPCHook.java
+++ b/acl/src/main/java/org/apache/rocketmq/acl/common/AclClientRPCHook.java
@@ -56,6 +56,10 @@ public class AclClientRPCHook implements RPCHook {
}
+ @Override public void doAfterRpcFailure(String remoteAddr, RemotingCommand request, Boolean remoteTimeout) {
+
+ }
+
protected SortedMap<String, String> parseRequestContent(RemotingCommand request, String ak, String securityToken) {
CommandCustomHeader header = request.readCustomHeader();
// Sort property
diff --git a/acl/src/test/resources/conf/plain_acl.yml b/acl/src/test/resources/conf/plain_acl.yml
index 59bd6d4..40d66d9 100644
--- a/acl/src/test/resources/conf/plain_acl.yml
+++ b/acl/src/test/resources/conf/plain_acl.yml
@@ -1,20 +1,3 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You 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.
-
-## suggested format
-
globalWhiteRemoteAddresses:
- 10.10.103.*
- 192.168.0.*
diff --git a/broker/pom.xml b/broker/pom.xml
index 31a10cc..8e52c19 100644
--- a/broker/pom.xml
+++ b/broker/pom.xml
@@ -47,14 +47,18 @@
<artifactId>rocketmq-filter</artifactId>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>rocketmq-acl</artifactId>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
@@ -74,6 +78,10 @@
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.rocketmq</groupId>
+ <artifactId>rocketmq-acl</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java b/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
index 210e180..2d06f19 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
@@ -16,7 +16,29 @@
*/
package org.apache.rocketmq.broker;
-import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.commons.io.FilenameUtils;
import org.apache.rocketmq.acl.AccessValidator;
import org.apache.rocketmq.broker.client.ClientHousekeepingService;
import org.apache.rocketmq.broker.client.ConsumerIdsChangeListener;
@@ -26,6 +48,7 @@ import org.apache.rocketmq.broker.client.ProducerManager;
import org.apache.rocketmq.broker.client.net.Broker2Client;
import org.apache.rocketmq.broker.client.rebalance.RebalanceLockManager;
import org.apache.rocketmq.broker.dledger.DLedgerRoleChangeHandler;
+import org.apache.rocketmq.broker.failover.EscapeBridge;
import org.apache.rocketmq.broker.filter.CommitLogDispatcherCalcBitMap;
import org.apache.rocketmq.broker.filter.ConsumerFilterManager;
import org.apache.rocketmq.broker.filtersrv.FilterServerManager;
@@ -41,6 +64,7 @@ import org.apache.rocketmq.broker.offset.ConsumerOffsetManager;
import org.apache.rocketmq.broker.offset.ConsumerOrderInfoManager;
import org.apache.rocketmq.broker.offset.LmqConsumerOffsetManager;
import org.apache.rocketmq.broker.out.BrokerOuterAPI;
+import org.apache.rocketmq.broker.plugin.BrokerAttachedPlugin;
import org.apache.rocketmq.broker.plugin.MessageStoreFactory;
import org.apache.rocketmq.broker.plugin.MessageStorePluginContext;
import org.apache.rocketmq.broker.processor.AckMessageProcessor;
@@ -49,12 +73,16 @@ import org.apache.rocketmq.broker.processor.ChangeInvisibleTimeProcessor;
import org.apache.rocketmq.broker.processor.ClientManageProcessor;
import org.apache.rocketmq.broker.processor.ConsumerManageProcessor;
import org.apache.rocketmq.broker.processor.EndTransactionProcessor;
+import org.apache.rocketmq.broker.processor.NotificationProcessor;
+import org.apache.rocketmq.broker.processor.PeekMessageProcessor;
+import org.apache.rocketmq.broker.processor.PollingInfoProcessor;
import org.apache.rocketmq.broker.processor.PopMessageProcessor;
import org.apache.rocketmq.broker.processor.PullMessageProcessor;
import org.apache.rocketmq.broker.processor.QueryAssignmentProcessor;
import org.apache.rocketmq.broker.processor.QueryMessageProcessor;
import org.apache.rocketmq.broker.processor.ReplyMessageProcessor;
import org.apache.rocketmq.broker.processor.SendMessageProcessor;
+import org.apache.rocketmq.broker.schedule.ScheduleMessageService;
import org.apache.rocketmq.broker.slave.SlaveSynchronize;
import org.apache.rocketmq.broker.subscription.LmqSubscriptionGroupManager;
import org.apache.rocketmq.broker.subscription.SubscriptionGroupManager;
@@ -68,22 +96,27 @@ import org.apache.rocketmq.broker.transaction.TransactionalMessageService;
import org.apache.rocketmq.broker.transaction.queue.DefaultTransactionalMessageCheckListener;
import org.apache.rocketmq.broker.transaction.queue.TransactionalMessageBridge;
import org.apache.rocketmq.broker.transaction.queue.TransactionalMessageServiceImpl;
-import org.apache.rocketmq.broker.util.ServiceProvider;
+import org.apache.rocketmq.broker.util.HookUtils;
import org.apache.rocketmq.common.BrokerConfig;
import org.apache.rocketmq.common.Configuration;
import org.apache.rocketmq.common.DataVersion;
+import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.ThreadFactoryImpl;
import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.common.constant.PermName;
+import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.namesrv.RegisterBrokerResult;
+import org.apache.rocketmq.common.protocol.NamespaceUtil;
import org.apache.rocketmq.common.protocol.RequestCode;
+import org.apache.rocketmq.common.protocol.body.BrokerMemberGroup;
import org.apache.rocketmq.common.protocol.body.TopicConfigAndMappingSerializeWrapper;
import org.apache.rocketmq.common.protocol.body.TopicConfigSerializeWrapper;
import org.apache.rocketmq.common.statictopic.TopicQueueMappingDetail;
import org.apache.rocketmq.common.statictopic.TopicQueueMappingInfo;
import org.apache.rocketmq.common.stats.MomentStatsItem;
+import org.apache.rocketmq.common.utils.ServiceProvider;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.RPCHook;
@@ -99,116 +132,129 @@ import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.srvutil.FileWatchService;
import org.apache.rocketmq.store.DefaultMessageStore;
import org.apache.rocketmq.store.MessageArrivingListener;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
import org.apache.rocketmq.store.MessageStore;
+import org.apache.rocketmq.store.PutMessageResult;
import org.apache.rocketmq.store.config.BrokerRole;
import org.apache.rocketmq.store.config.MessageStoreConfig;
import org.apache.rocketmq.store.dledger.DLedgerCommitLog;
+import org.apache.rocketmq.store.hook.PutMessageHook;
+import org.apache.rocketmq.store.hook.SendMessageBackHook;
import org.apache.rocketmq.store.stats.BrokerStats;
import org.apache.rocketmq.store.stats.BrokerStatsManager;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Function;
-import java.util.stream.Collectors;
import org.apache.rocketmq.store.stats.LmqBrokerStatsManager;
public class BrokerController {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ protected static final InternalLogger LOG = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private static final InternalLogger LOG_PROTECTION = InternalLoggerFactory.getLogger(LoggerName.PROTECTION_LOGGER_NAME);
private static final InternalLogger LOG_WATER_MARK = InternalLoggerFactory.getLogger(LoggerName.WATER_MARK_LOGGER_NAME);
- private final BrokerConfig brokerConfig;
+ protected static final int HA_ADDRESS_MIN_LENGTH = 6;
+
+ protected final BrokerConfig brokerConfig;
private final NettyServerConfig nettyServerConfig;
private final NettyClientConfig nettyClientConfig;
- private final MessageStoreConfig messageStoreConfig;
- private final ConsumerOffsetManager consumerOffsetManager;
- private final ConsumerManager consumerManager;
- private final ConsumerFilterManager consumerFilterManager;
- private final ConsumerOrderInfoManager consumerOrderInfoManager;
- private final ProducerManager producerManager;
- private final AssignmentManager assignmentManager;
- private final ClientHousekeepingService clientHousekeepingService;
-
- private final PullMessageProcessor pullMessageProcessor;
- private final PopMessageProcessor popMessageProcessor;
- private final AckMessageProcessor ackMessageProcessor;
- private final ChangeInvisibleTimeProcessor changeInvisibleTimeProcessor;
- private final QueryAssignmentProcessor queryAssignmentProcessor;
- private final ClientManageProcessor clientManageProcessor;
- private final SendMessageProcessor sendMessageProcessor;
- private final PullRequestHoldService pullRequestHoldService;
- private final MessageArrivingListener messageArrivingListener;
- private final Broker2Client broker2Client;
- private final SubscriptionGroupManager subscriptionGroupManager;
- private final ConsumerIdsChangeListener consumerIdsChangeListener;
+ protected final MessageStoreConfig messageStoreConfig;
+ protected final ConsumerOffsetManager consumerOffsetManager;
+ protected final ConsumerManager consumerManager;
+ protected final ConsumerFilterManager consumerFilterManager;
+ protected final ConsumerOrderInfoManager consumerOrderInfoManager;
+ protected final ProducerManager producerManager;
+ protected final ScheduleMessageService scheduleMessageService;
+ protected final AssignmentManager assignmentManager;
+ protected final ClientHousekeepingService clientHousekeepingService;
+ protected final PullMessageProcessor pullMessageProcessor;
+ protected final PeekMessageProcessor peekMessageProcessor;
+ protected final PopMessageProcessor popMessageProcessor;
+ protected final AckMessageProcessor ackMessageProcessor;
+ protected final ChangeInvisibleTimeProcessor changeInvisibleTimeProcessor;
+ protected final NotificationProcessor notificationProcessor;
+ protected final PollingInfoProcessor pollingInfoProcessor;
+ protected final QueryAssignmentProcessor queryAssignmentProcessor;
+ protected final ClientManageProcessor clientManageProcessor;
+ protected final SendMessageProcessor sendMessageProcessor;
+ protected final ReplyMessageProcessor replyMessageProcessor;
+ protected final PullRequestHoldService pullRequestHoldService;
+ protected final MessageArrivingListener messageArrivingListener;
+ protected final Broker2Client broker2Client;
+ protected final SubscriptionGroupManager subscriptionGroupManager;
+ protected final ConsumerIdsChangeListener consumerIdsChangeListener;
private final RebalanceLockManager rebalanceLockManager = new RebalanceLockManager();
- private final BrokerOuterAPI brokerOuterAPI;
- private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl(
- "BrokerControllerScheduledThread"));
- private final SlaveSynchronize slaveSynchronize;
- private final BlockingQueue<Runnable> sendThreadPoolQueue;
- private final BlockingQueue<Runnable> putThreadPoolQueue;
- private final BlockingQueue<Runnable> ackThreadPoolQueue;
- private final BlockingQueue<Runnable> pullThreadPoolQueue;
- private final BlockingQueue<Runnable> replyThreadPoolQueue;
- private final BlockingQueue<Runnable> queryThreadPoolQueue;
- private final BlockingQueue<Runnable> clientManagerThreadPoolQueue;
- private final BlockingQueue<Runnable> heartbeatThreadPoolQueue;
- private final BlockingQueue<Runnable> consumerManagerThreadPoolQueue;
- private final BlockingQueue<Runnable> endTransactionThreadPoolQueue;
- private final FilterServerManager filterServerManager;
- private final BrokerStatsManager brokerStatsManager;
- private final List<SendMessageHook> sendMessageHookList = new ArrayList<SendMessageHook>();
- private final List<ConsumeMessageHook> consumeMessageHookList = new ArrayList<ConsumeMessageHook>();
- private final ConcurrentMap<String, String> brokerName2AddrMap = Maps.newConcurrentMap();
- private MessageStore messageStore;
- private RemotingServer remotingServer;
- private RemotingServer fastRemotingServer;
- private TopicConfigManager topicConfigManager;
- private TopicQueueMappingManager topicQueueMappingManager;
- private ExecutorService sendMessageExecutor;
- private ExecutorService putMessageFutureExecutor;
- private ExecutorService pullMessageExecutor;
- private ExecutorService ackMessageExecutor;
- private ExecutorService replyMessageExecutor;
- private ExecutorService queryMessageExecutor;
- private ExecutorService adminBrokerExecutor;
- private ExecutorService clientManageExecutor;
- private ExecutorService heartbeatExecutor;
- private ExecutorService consumerManageExecutor;
- private ExecutorService loadBalanceExecutor;
- private ExecutorService endTransactionExecutor;
- private boolean updateMasterHAServerAddrPeriodically = false;
+ protected BrokerOuterAPI brokerOuterAPI;
+ protected ScheduledExecutorService scheduledExecutorService;
+ protected final SlaveSynchronize slaveSynchronize;
+ protected final BlockingQueue<Runnable> sendThreadPoolQueue;
+ protected final BlockingQueue<Runnable> putThreadPoolQueue;
+ protected final BlockingQueue<Runnable> ackThreadPoolQueue;
+ protected final BlockingQueue<Runnable> pullThreadPoolQueue;
+ protected final BlockingQueue<Runnable> litePullThreadPoolQueue;
+ protected final BlockingQueue<Runnable> replyThreadPoolQueue;
+ protected final BlockingQueue<Runnable> queryThreadPoolQueue;
+ protected final BlockingQueue<Runnable> clientManagerThreadPoolQueue;
+ protected final BlockingQueue<Runnable> heartbeatThreadPoolQueue;
+ protected final BlockingQueue<Runnable> consumerManagerThreadPoolQueue;
+ protected final BlockingQueue<Runnable> endTransactionThreadPoolQueue;
+ protected final BlockingQueue<Runnable> adminBrokerThreadPoolQueue;
+ protected final BlockingQueue<Runnable> loadBalanceThreadPoolQueue;
+ protected final FilterServerManager filterServerManager;
+ protected final BrokerStatsManager brokerStatsManager;
+ protected final List<SendMessageHook> sendMessageHookList = new ArrayList<SendMessageHook>();
+ protected final List<ConsumeMessageHook> consumeMessageHookList = new ArrayList<ConsumeMessageHook>();
+ protected MessageStore messageStore;
+ protected RemotingServer remotingServer;
+ protected CountDownLatch remotingServerStartLatch;
+ protected RemotingServer fastRemotingServer;
+ protected TopicConfigManager topicConfigManager;
+ protected TopicQueueMappingManager topicQueueMappingManager;
+ protected ExecutorService sendMessageExecutor;
+ protected ExecutorService pullMessageExecutor;
+ protected ExecutorService litePullMessageExecutor;
+ protected ExecutorService putMessageFutureExecutor;
+ protected ExecutorService ackMessageExecutor;
+ protected ExecutorService replyMessageExecutor;
+ protected ExecutorService queryMessageExecutor;
+ protected ExecutorService adminBrokerExecutor;
+ protected ExecutorService clientManageExecutor;
+ protected ExecutorService heartbeatExecutor;
+ protected ExecutorService consumerManageExecutor;
+ protected ExecutorService loadBalanceExecutor;
+ protected ExecutorService endTransactionExecutor;
+ protected boolean updateMasterHAServerAddrPeriodically = false;
private BrokerStats brokerStats;
private InetSocketAddress storeHost;
- private BrokerFastFailure brokerFastFailure;
+ protected BrokerFastFailure brokerFastFailure;
private Configuration configuration;
- private TopicQueueMappingCleanService topicQueueMappingCleanService;
- private FileWatchService fileWatchService;
- private TransactionalMessageCheckService transactionalMessageCheckService;
- private TransactionalMessageService transactionalMessageService;
- private AbstractTransactionalMessageCheckListener transactionalMessageCheckListener;
- private Future<?> slaveSyncFuture;
- private Map<Class, AccessValidator> accessValidatorMap = new HashMap<Class, AccessValidator>();
- private long shouldStartTime;
+ protected TopicQueueMappingCleanService topicQueueMappingCleanService;
+ protected FileWatchService fileWatchService;
+ protected TransactionalMessageCheckService transactionalMessageCheckService;
+ protected TransactionalMessageService transactionalMessageService;
+ protected AbstractTransactionalMessageCheckListener transactionalMessageCheckListener;
+ protected Map<Class, AccessValidator> accessValidatorMap = new HashMap<Class, AccessValidator>();
+ protected volatile boolean shutdown = false;
+ protected ShutdownHook shutdownHook;
+ private volatile boolean isScheduleServiceStart = false;
+ private volatile boolean isTransactionCheckServiceStart = false;
+ protected volatile BrokerMemberGroup brokerMemberGroup;
+ protected EscapeBridge escapeBridge;
+ protected List<BrokerAttachedPlugin> brokerAttachedPlugins = new ArrayList<>();
+ protected volatile long shouldStartTime;
+
+ public BrokerController(
+ final BrokerConfig brokerConfig,
+ final NettyServerConfig nettyServerConfig,
+ final NettyClientConfig nettyClientConfig,
+ final MessageStoreConfig messageStoreConfig,
+ final ShutdownHook shutdownHook
+ ) {
+ this(brokerConfig, nettyServerConfig, nettyClientConfig, messageStoreConfig);
+ this.shutdownHook = shutdownHook;
+ }
+
+ public BrokerController(
+ final BrokerConfig brokerConfig,
+ final MessageStoreConfig messageStoreConfig
+ ) {
+ this(brokerConfig, null, null, messageStoreConfig);
+ }
public BrokerController(
final BrokerConfig brokerConfig,
@@ -220,26 +266,36 @@ public class BrokerController {
this.nettyServerConfig = nettyServerConfig;
this.nettyClientConfig = nettyClientConfig;
this.messageStoreConfig = messageStoreConfig;
+ this.setStoreHost(new InetSocketAddress(this.getBrokerConfig().getBrokerIP1(), getListenPort()));
+ this.brokerStatsManager = messageStoreConfig.isEnableLmq() ? new LmqBrokerStatsManager(this.brokerConfig.getBrokerClusterName(), this.brokerConfig.isEnableDetailStat()) : new BrokerStatsManager(this.brokerConfig.getBrokerClusterName(), this.brokerConfig.isEnableDetailStat());
this.consumerOffsetManager = messageStoreConfig.isEnableLmq() ? new LmqConsumerOffsetManager(this) : new ConsumerOffsetManager(this);
this.topicConfigManager = messageStoreConfig.isEnableLmq() ? new LmqTopicConfigManager(this) : new TopicConfigManager(this);
this.topicQueueMappingManager = new TopicQueueMappingManager(this);
this.pullMessageProcessor = new PullMessageProcessor(this);
+ this.peekMessageProcessor = new PeekMessageProcessor(this);
this.pullRequestHoldService = messageStoreConfig.isEnableLmq() ? new LmqPullRequestHoldService(this) : new PullRequestHoldService(this);
this.popMessageProcessor = new PopMessageProcessor(this);
+ this.notificationProcessor = new NotificationProcessor(this);
+ this.pollingInfoProcessor = new PollingInfoProcessor(this);
this.ackMessageProcessor = new AckMessageProcessor(this);
this.changeInvisibleTimeProcessor = new ChangeInvisibleTimeProcessor(this);
this.sendMessageProcessor = new SendMessageProcessor(this);
- this.messageArrivingListener = new NotifyMessageArrivingListener(this.pullRequestHoldService,
- this.popMessageProcessor);
+ this.replyMessageProcessor = new ReplyMessageProcessor(this);
+ this.messageArrivingListener = new NotifyMessageArrivingListener(this.pullRequestHoldService, this.popMessageProcessor, this.notificationProcessor);
this.consumerIdsChangeListener = new DefaultConsumerIdsChangeListener(this);
- this.consumerManager = new ConsumerManager(this.consumerIdsChangeListener);
+ this.consumerManager = new ConsumerManager(this.consumerIdsChangeListener, this.brokerStatsManager);
+ this.producerManager = new ProducerManager(this.brokerStatsManager);
this.consumerFilterManager = new ConsumerFilterManager(this);
this.consumerOrderInfoManager = new ConsumerOrderInfoManager(this);
- this.producerManager = new ProducerManager();
this.clientHousekeepingService = new ClientHousekeepingService(this);
this.broker2Client = new Broker2Client(this);
this.subscriptionGroupManager = messageStoreConfig.isEnableLmq() ? new LmqSubscriptionGroupManager(this) : new SubscriptionGroupManager(this);
- this.brokerOuterAPI = new BrokerOuterAPI(nettyClientConfig, this);
+ this.scheduleMessageService = new ScheduleMessageService(this);
+
+ if (nettyClientConfig != null) {
+ this.brokerOuterAPI = new BrokerOuterAPI(nettyClientConfig);
+ }
+
this.filterServerManager = new FilterServerManager(this);
this.assignmentManager = new AssignmentManager(this);
@@ -250,6 +306,8 @@ public class BrokerController {
this.sendThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getSendThreadPoolQueueCapacity());
this.putThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getPutThreadPoolQueueCapacity());
this.pullThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getPullThreadPoolQueueCapacity());
+ this.litePullThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getLitePullThreadPoolQueueCapacity());
+
this.ackThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getAckThreadPoolQueueCapacity());
this.replyThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getReplyThreadPoolQueueCapacity());
this.queryThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getQueryThreadPoolQueueCapacity());
@@ -257,25 +315,51 @@ public class BrokerController {
this.consumerManagerThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getConsumerManagerThreadPoolQueueCapacity());
this.heartbeatThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getHeartbeatThreadPoolQueueCapacity());
this.endTransactionThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getEndTransactionPoolQueueCapacity());
-
- this.brokerStatsManager = messageStoreConfig.isEnableLmq() ? new LmqBrokerStatsManager(this.brokerConfig.getBrokerClusterName(), this.brokerConfig.isEnableDetailStat()) : new BrokerStatsManager(this.brokerConfig.getBrokerClusterName(), this.brokerConfig.isEnableDetailStat());
-
- this.setStoreHost(new InetSocketAddress(this.getBrokerConfig().getBrokerIP1(), this.getNettyServerConfig().getListenPort()));
+ this.adminBrokerThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getAdminBrokerThreadPoolQueueCapacity());
+ this.loadBalanceThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getLoadBalanceThreadPoolQueueCapacity());
this.brokerFastFailure = new BrokerFastFailure(this);
+
+ String brokerConfigPath;
+ if (brokerConfig.getBrokerConfigPath() != null && !brokerConfig.getBrokerConfigPath().isEmpty()) {
+ brokerConfigPath = brokerConfig.getBrokerConfigPath();
+ } else {
+ brokerConfigPath = FilenameUtils.concat(
+ FilenameUtils.getFullPathNoEndSeparator(BrokerPathConfigHelper.getBrokerConfigPath()),
+ this.brokerConfig.getCanonicalName() + ".properties");
+ }
this.configuration = new Configuration(
- log,
- BrokerPathConfigHelper.getBrokerConfigPath(),
+ LOG,
+ brokerConfigPath,
this.brokerConfig, this.nettyServerConfig, this.nettyClientConfig, this.messageStoreConfig
);
- }
- public ConsumerIdsChangeListener getConsumerIdsChangeListener() {
- return consumerIdsChangeListener;
- }
+ this.brokerStatsManager.setProduerStateGetter(new BrokerStatsManager.StateGetter() {
+ @Override
+ public boolean online(String instanceId, String group, String topic) {
+ if (getTopicConfigManager().getTopicConfigTable().containsKey(NamespaceUtil.wrapNamespace(instanceId, topic))) {
+ return getProducerManager().groupOnline(NamespaceUtil.wrapNamespace(instanceId, group));
+ } else {
+ return getProducerManager().groupOnline(group);
+ }
+ }
+ });
+ this.brokerStatsManager.setConsumerStateGetter(new BrokerStatsManager.StateGetter() {
+ @Override
+ public boolean online(String instanceId, String group, String topic) {
+ String topicFullName = NamespaceUtil.wrapNamespace(instanceId, topic);
+ if (getTopicConfigManager().getTopicConfigTable().containsKey(topicFullName)) {
+ return getConsumerManager().findSubscriptionData(NamespaceUtil.wrapNamespace(instanceId, group), topicFullName) != null;
+ } else {
+ return getConsumerManager().findSubscriptionData(group, topic) != null;
+ }
+ }
+ });
+
+ this.brokerMemberGroup = new BrokerMemberGroup(this.brokerConfig.getBrokerClusterName(), this.brokerConfig.getBrokerName());
+ this.brokerMemberGroup.getBrokerAddrs().put(this.brokerConfig.getBrokerId(), this.getBrokerAddr());
- public ClientManageProcessor getClientManageProcessor() {
- return clientManageProcessor;
+ this.escapeBridge = new EscapeBridge(this);
}
public BrokerConfig getBrokerConfig() {
@@ -286,6 +370,10 @@ public class BrokerController {
return nettyServerConfig;
}
+ public NettyClientConfig getNettyClientConfig() {
+ return nettyClientConfig;
+ }
+
public BlockingQueue<Runnable> getPullThreadPoolQueue() {
return pullThreadPoolQueue;
}
@@ -294,245 +382,342 @@ public class BrokerController {
return queryThreadPoolQueue;
}
- public boolean initialize() throws CloneNotSupportedException {
- boolean result = this.topicConfigManager.load();
+ protected void initializeRemotingServer() throws CloneNotSupportedException {
+ this.remotingServer = new NettyRemotingServer(this.nettyServerConfig, this.clientHousekeepingService);
+ NettyServerConfig fastConfig = (NettyServerConfig) this.nettyServerConfig.clone();
+ fastConfig.setListenPort(nettyServerConfig.getListenPort() - 2);
+ this.fastRemotingServer = new NettyRemotingServer(fastConfig, this.clientHousekeepingService);
+ }
+
+ /**
+ * Initialize resources including remoting server and thread executors.
+ */
+ protected void initializeResources() {
+ this.scheduledExecutorService = new ScheduledThreadPoolExecutor(1,
+ new ThreadFactoryImpl("BrokerControllerScheduledThread", true, brokerConfig));
+
+ this.sendMessageExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getSendMessageThreadPoolNums(),
+ this.brokerConfig.getSendMessageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.sendThreadPoolQueue,
+ new ThreadFactoryImpl("SendMessageThread_", brokerConfig));
+
+ this.pullMessageExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getPullMessageThreadPoolNums(),
+ this.brokerConfig.getPullMessageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.pullThreadPoolQueue,
+ new ThreadFactoryImpl("PullMessageThread_", brokerConfig));
+
+ this.litePullMessageExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getLitePullMessageThreadPoolNums(),
+ this.brokerConfig.getLitePullMessageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.litePullThreadPoolQueue,
+ new ThreadFactoryImpl("LitePullMessageThread_", brokerConfig));
+
+ this.putMessageFutureExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getPutMessageFutureThreadPoolNums(),
+ this.brokerConfig.getPutMessageFutureThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.putThreadPoolQueue,
+ new ThreadFactoryImpl("SendMessageThread_", brokerConfig));
+
+ this.ackMessageExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getAckMessageThreadPoolNums(),
+ this.brokerConfig.getAckMessageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.ackThreadPoolQueue,
+ new ThreadFactoryImpl("AckMessageThread_", brokerConfig));
+
+ this.queryMessageExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getQueryMessageThreadPoolNums(),
+ this.brokerConfig.getQueryMessageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.queryThreadPoolQueue,
+ new ThreadFactoryImpl("QueryMessageThread_", brokerConfig));
+
+ this.adminBrokerExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getAdminBrokerThreadPoolNums(),
+ this.brokerConfig.getAdminBrokerThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.adminBrokerThreadPoolQueue,
+ new ThreadFactoryImpl("AdminBrokerThread_", brokerConfig));
+
+ this.clientManageExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getClientManageThreadPoolNums(),
+ this.brokerConfig.getClientManageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.clientManagerThreadPoolQueue,
+ new ThreadFactoryImpl("ClientManageThread_", brokerConfig));
+
+ this.heartbeatExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getHeartbeatThreadPoolNums(),
+ this.brokerConfig.getHeartbeatThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.heartbeatThreadPoolQueue,
+ new ThreadFactoryImpl("HeartbeatThread_", true, brokerConfig));
+
+ this.consumerManageExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getConsumerManageThreadPoolNums(),
+ this.brokerConfig.getConsumerManageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.consumerManagerThreadPoolQueue,
+ new ThreadFactoryImpl("ConsumerManageThread_", true, brokerConfig));
+
+ this.replyMessageExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
+ this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.replyThreadPoolQueue,
+ new ThreadFactoryImpl("ProcessReplyMessageThread_", brokerConfig));
+
+ this.endTransactionExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getEndTransactionThreadPoolNums(),
+ this.brokerConfig.getEndTransactionThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.endTransactionThreadPoolQueue,
+ new ThreadFactoryImpl("EndTransactionThread_", brokerConfig));
+
+ this.loadBalanceExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getLoadBalanceProcessorThreadPoolNums(),
+ this.brokerConfig.getLoadBalanceProcessorThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.loadBalanceThreadPoolQueue,
+ new ThreadFactoryImpl("LoadBalanceProcessorThread_", brokerConfig));
+
+ this.topicQueueMappingCleanService = new TopicQueueMappingCleanService(this);
+ }
+
+ protected void initializeBrokerScheduledTasks() {
+ final long initialDelay = UtilAll.computeNextMorningTimeMillis() - System.currentTimeMillis();
+ final long period = 1000 * 60 * 60 * 24;
+ this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ BrokerController.this.getBrokerStats().record();
+ } catch (Throwable e) {
+ LOG.error("BrokerController: failed to record broker stats", e);
+ }
+ }
+ }, initialDelay, period, TimeUnit.MILLISECONDS);
- result = result && this.topicQueueMappingManager.load();
+ this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ BrokerController.this.consumerOffsetManager.persist();
+ } catch (Throwable e) {
+ LOG.error(
+ "BrokerController: failed to persist config file of consumerOffset", e);
+ }
+ }
+ }, 1000 * 10, this.brokerConfig.getFlushConsumerOffsetInterval(), TimeUnit.MILLISECONDS);
- result = result && this.consumerOffsetManager.load();
- result = result && this.subscriptionGroupManager.load();
- result = result && this.consumerFilterManager.load();
+ this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ BrokerController.this.consumerFilterManager.persist();
+ BrokerController.this.consumerOrderInfoManager.persist();
+ } catch (Throwable e) {
+ LOG.error(
+ "BrokerController: failed to persist config file of consumerFilter or consumerOrderInfo",
+ e);
+ }
+ }
+ }, 1000 * 10, 1000 * 10, TimeUnit.MILLISECONDS);
- if (result) {
- try {
- this.messageStore = new DefaultMessageStore(this.messageStoreConfig, this.brokerStatsManager, this.messageArrivingListener, this.brokerConfig);
- ((DefaultMessageStore) this.messageStore).setTopicConfigTable(topicConfigManager.getTopicConfigTable());
+ this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ BrokerController.this.protectBroker();
+ } catch (Throwable e) {
+ LOG.error("BrokerController: failed to protectBroker", e);
+ }
+ }
+ }, 3, 3, TimeUnit.MINUTES);
- if (messageStoreConfig.isEnableDLegerCommitLog()) {
- DLedgerRoleChangeHandler roleChangeHandler = new DLedgerRoleChangeHandler(this, (DefaultMessageStore) messageStore);
- ((DLedgerCommitLog) messageStore.getCommitLog()).getdLedgerServer().getdLedgerLeaderElector().addRoleChangeHandler(roleChangeHandler);
+ this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ BrokerController.this.printWaterMark();
+ } catch (Throwable e) {
+ LOG.error("BrokerController: failed to print broker watermark", e);
}
- this.brokerStats = new BrokerStats(this.messageStore);
- //load plugin
- MessageStorePluginContext context = new MessageStorePluginContext(messageStoreConfig, brokerStatsManager, messageArrivingListener, brokerConfig);
- this.messageStore = MessageStoreFactory.build(context, this.messageStore);
- this.messageStore.getDispatcherList().addFirst(new CommitLogDispatcherCalcBitMap(this.brokerConfig, this.consumerFilterManager));
- } catch (IOException e) {
- result = false;
- log.error("Failed to initialize", e);
}
- }
+ }, 10, 1, TimeUnit.SECONDS);
- result = result && this.messageStore.load();
+ this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- if (result) {
- this.remotingServer = new NettyRemotingServer(this.nettyServerConfig, this.clientHousekeepingService);
- NettyServerConfig fastConfig = (NettyServerConfig) this.nettyServerConfig.clone();
- fastConfig.setListenPort(nettyServerConfig.getListenPort() - 2);
- this.fastRemotingServer = new NettyRemotingServer(fastConfig, this.clientHousekeepingService);
- this.sendMessageExecutor = new BrokerFixedThreadPoolExecutor(
- this.brokerConfig.getSendMessageThreadPoolNums(),
- this.brokerConfig.getSendMessageThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.sendThreadPoolQueue,
- new ThreadFactoryImpl("SendMessageThread_"));
-
- this.putMessageFutureExecutor = new BrokerFixedThreadPoolExecutor(
- this.brokerConfig.getPutMessageFutureThreadPoolNums(),
- this.brokerConfig.getPutMessageFutureThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.putThreadPoolQueue,
- new ThreadFactoryImpl("PutMessageThread_"));
-
- this.pullMessageExecutor = new BrokerFixedThreadPoolExecutor(
- this.brokerConfig.getPullMessageThreadPoolNums(),
- this.brokerConfig.getPullMessageThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.pullThreadPoolQueue,
- new ThreadFactoryImpl("PullMessageThread_"));
-
- this.ackMessageExecutor = new BrokerFixedThreadPoolExecutor(
- this.brokerConfig.getAckMessageThreadPoolNums(),
- this.brokerConfig.getAckMessageThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.ackThreadPoolQueue,
- new ThreadFactoryImpl("AckMessageThread_"));
-
- this.replyMessageExecutor = new BrokerFixedThreadPoolExecutor(
- this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
- this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.replyThreadPoolQueue,
- new ThreadFactoryImpl("ProcessReplyMessageThread_"));
-
- this.queryMessageExecutor = new BrokerFixedThreadPoolExecutor(
- this.brokerConfig.getQueryMessageThreadPoolNums(),
- this.brokerConfig.getQueryMessageThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.queryThreadPoolQueue,
- new ThreadFactoryImpl("QueryMessageThread_"));
-
- this.adminBrokerExecutor =
- Executors.newFixedThreadPool(this.brokerConfig.getAdminBrokerThreadPoolNums(), new ThreadFactoryImpl(
- "AdminBrokerThread_"));
-
- this.clientManageExecutor = new ThreadPoolExecutor(
- this.brokerConfig.getClientManageThreadPoolNums(),
- this.brokerConfig.getClientManageThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.clientManagerThreadPoolQueue,
- new ThreadFactoryImpl("ClientManageThread_"));
-
- this.heartbeatExecutor = new BrokerFixedThreadPoolExecutor(
- this.brokerConfig.getHeartbeatThreadPoolNums(),
- this.brokerConfig.getHeartbeatThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.heartbeatThreadPoolQueue,
- new ThreadFactoryImpl("HeartbeatThread_", true));
-
- this.endTransactionExecutor = new BrokerFixedThreadPoolExecutor(
- this.brokerConfig.getEndTransactionThreadPoolNums(),
- this.brokerConfig.getEndTransactionThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.endTransactionThreadPoolQueue,
- new ThreadFactoryImpl("EndTransactionThread_"));
-
- this.consumerManageExecutor =
- Executors.newFixedThreadPool(this.brokerConfig.getConsumerManageThreadPoolNums(), new ThreadFactoryImpl(
- "ConsumerManageThread_"));
-
- this.registerProcessor();
-
- final long initialDelay = UtilAll.computeNextMorningTimeMillis() - System.currentTimeMillis();
- final long period = 1000 * 60 * 60 * 24;
- this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try {
- BrokerController.this.getBrokerStats().record();
- } catch (Throwable e) {
- log.error("schedule record error.", e);
- }
+ @Override
+ public void run() {
+ try {
+ LOG.info("Dispatch task fall behind commit log {}bytes",
+ BrokerController.this.getMessageStore().dispatchBehindBytes());
+ } catch (Throwable e) {
+ LOG.error("Failed to print dispatchBehindBytes", e);
}
- }, initialDelay, period, TimeUnit.MILLISECONDS);
+ }
+ }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);
- this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try {
- BrokerController.this.consumerOffsetManager.persist();
- } catch (Throwable e) {
- log.error("schedule persist consumerOffset error.", e);
- }
+ if (!messageStoreConfig.isEnableDLegerCommitLog() && !messageStoreConfig.isDuplicationEnable()) {
+ if (BrokerRole.SLAVE == this.messageStoreConfig.getBrokerRole()) {
+ if (this.messageStoreConfig.getHaMasterAddress() != null && this.messageStoreConfig.getHaMasterAddress().length() >= HA_ADDRESS_MIN_LENGTH) {
+ this.messageStore.updateHaMasterAddress(this.messageStoreConfig.getHaMasterAddress());
+ this.updateMasterHAServerAddrPeriodically = false;
+ } else {
+ this.updateMasterHAServerAddrPeriodically = true;
}
- }, 1000 * 10, this.brokerConfig.getFlushConsumerOffsetInterval(), TimeUnit.MILLISECONDS);
- this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try {
- BrokerController.this.consumerFilterManager.persist();
- } catch (Throwable e) {
- log.error("schedule persist consumer filter error.", e);
+ this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ BrokerController.this.slaveSynchronize.syncAll();
+ } catch (Throwable e) {
+ LOG.error("Failed to sync all config for slave.", e);
+ }
}
- }
- }, 1000 * 10, 1000 * 10, TimeUnit.MILLISECONDS);
+ }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);
- this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try {
- BrokerController.this.protectBroker();
- } catch (Throwable e) {
- log.error("protectBroker error.", e);
+ } else {
+ this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ BrokerController.this.printMasterAndSlaveDiff();
+ } catch (Throwable e) {
+ LOG.error("Failed to print diff of master and slave.", e);
+ }
}
+ }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+
+ protected void initializeScheduledTasks() {
+
+ initializeBrokerScheduledTasks();
+
+ this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ BrokerController.this.brokerOuterAPI.refreshMetadata();
+ } catch (Exception e) {
+ LOG.error("ScheduledTask refresh metadata exception", e);
}
- }, 3, 3, TimeUnit.MINUTES);
+ }
+ }, 1, 5, TimeUnit.SECONDS);
+ if (this.brokerConfig.getNamesrvAddr() != null) {
+ this.brokerOuterAPI.updateNameServerAddressList(this.brokerConfig.getNamesrvAddr());
+ LOG.info("Set user specified name server address: {}", this.brokerConfig.getNamesrvAddr());
+ // also auto update namesrv if specify
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
- BrokerController.this.printWaterMark();
+ BrokerController.this.brokerOuterAPI.updateNameServerAddressList(BrokerController.this.brokerConfig.getNamesrvAddr());
} catch (Throwable e) {
- log.error("printWaterMark error.", e);
+ LOG.error("Failed to update nameServer address list", e);
}
}
- }, 10, 1, TimeUnit.SECONDS);
-
+ }, 1000 * 10, 1000 * 60 * 2, TimeUnit.MILLISECONDS);
+ } else if (this.brokerConfig.isFetchNamesrvAddrByAddressServer()) {
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
- log.info("dispatch behind commit log {} bytes", BrokerController.this.getMessageStore().dispatchBehindBytes());
+ BrokerController.this.brokerOuterAPI.fetchNameServerAddr();
} catch (Throwable e) {
- log.error("schedule dispatchBehindBytes error.", e);
+ LOG.error("Failed to fetch nameServer address", e);
}
}
- }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);
+ }, 1000 * 10, 1000 * 60 * 2, TimeUnit.MILLISECONDS);
+ }
+ }
- this.loadBalanceExecutor =
- Executors.newFixedThreadPool(this.brokerConfig.getLoadBalanceProcessorThreadPoolNums(), new ThreadFactoryImpl(
- "LoadBalanceProcessorThread_"));
+ public boolean initialize() throws CloneNotSupportedException {
- if (this.brokerConfig.getNamesrvAddr() != null) {
- this.brokerOuterAPI.updateNameServerAddressList(this.brokerConfig.getNamesrvAddr());
- log.info("Set user specified name server address: {}", this.brokerConfig.getNamesrvAddr());
- } else if (this.brokerConfig.isFetchNamesrvAddrByAddressServer()) {
- this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
+ boolean result = this.topicConfigManager.load();
+ result = result && this.topicQueueMappingManager.load();
+ result = result && this.consumerOffsetManager.load();
+ result = result && this.subscriptionGroupManager.load();
+ result = result && this.consumerFilterManager.load();
+ result = result && this.consumerOrderInfoManager.load();
- @Override
- public void run() {
- try {
- BrokerController.this.brokerOuterAPI.fetchNameServerAddr();
- } catch (Throwable e) {
- log.error("ScheduledTask fetchNameServerAddr exception", e);
- }
- }
- }, 1000 * 10, 1000 * 60 * 2, TimeUnit.MILLISECONDS);
- }
+ if (result) {
+ try {
+ DefaultMessageStore defaultMessageStore = new DefaultMessageStore(this.messageStoreConfig, this.brokerStatsManager, this.messageArrivingListener, this.brokerConfig);
+ defaultMessageStore.setTopicConfigTable(topicConfigManager.getTopicConfigTable());
- this.scheduledExecutorService.scheduleAtFixedRate(() -> {
- try {
- BrokerController.this.brokerOuterAPI.refreshMetadata();
- } catch (Exception e) {
- log.error("ScheduledTask refresh metadata exception", e);
- }
- }, 1, 5, TimeUnit.SECONDS);
-
- if (!messageStoreConfig.isEnableDLegerCommitLog()) {
- if (BrokerRole.SLAVE == this.messageStoreConfig.getBrokerRole()) {
- if (this.messageStoreConfig.getHaMasterAddress() != null && this.messageStoreConfig.getHaMasterAddress().length() >= 6) {
- this.messageStore.updateHaMasterAddress(this.messageStoreConfig.getHaMasterAddress());
- this.updateMasterHAServerAddrPeriodically = false;
- } else {
- this.updateMasterHAServerAddrPeriodically = true;
- }
- } else {
- this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try {
- BrokerController.this.printMasterAndSlaveDiff();
- } catch (Throwable e) {
- log.error("schedule printMasterAndSlaveDiff error.", e);
- }
- }
- }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);
+ if (messageStoreConfig.isEnableDLegerCommitLog()) {
+ DLedgerRoleChangeHandler roleChangeHandler = new DLedgerRoleChangeHandler(this, defaultMessageStore);
+ ((DLedgerCommitLog) defaultMessageStore.getCommitLog()).getdLedgerServer().getdLedgerLeaderElector().addRoleChangeHandler(roleChangeHandler);
}
+ this.brokerStats = new BrokerStats(defaultMessageStore);
+ //load plugin
+ MessageStorePluginContext context = new MessageStorePluginContext(this, messageStoreConfig, brokerStatsManager, messageArrivingListener);
+ this.messageStore = MessageStoreFactory.build(context, defaultMessageStore);
+ this.messageStore.getDispatcherList().addFirst(new CommitLogDispatcherCalcBitMap(this.brokerConfig, this.consumerFilterManager));
+
+ } catch (IOException e) {
+ result = false;
+ LOG.error("BrokerController#initialize: unexpected error occurs", e);
+ }
+ }
+ if (messageStore != null) {
+ registerMessageStoreHook();
+ }
+
+ result = result && this.messageStore.load();
+
+ //scheduleMessageService load after messageStore load success
+ result = result && this.scheduleMessageService.load();
+
+ for (BrokerAttachedPlugin brokerAttachedPlugin : brokerAttachedPlugins) {
+ if (brokerAttachedPlugin != null) {
+ result = result && brokerAttachedPlugin.load();
}
+ }
+
+ if (result) {
+
+ initializeRemotingServer();
+
+ initializeResources();
+
+ registerProcessor();
+
+ initializeScheduledTasks();
+
+ initialTransaction();
+
+ initialAcl();
- this.topicQueueMappingCleanService = new TopicQueueMappingCleanService(this);
+ initialRpcHooks();
if (TlsSystemConfig.tlsMode != TlsMode.DISABLED) {
// Register a listener to reload SslContext
@@ -549,7 +734,7 @@ public class BrokerController {
@Override
public void onChanged(String path) {
if (path.equals(TlsSystemConfig.tlsServerTrustCertPath)) {
- log.info("The trust certificate changed, reload the ssl context");
+ LOG.info("The trust certificate changed, reload the ssl context");
reloadServerSslContext();
}
if (path.equals(TlsSystemConfig.tlsServerCertPath)) {
@@ -559,7 +744,7 @@ public class BrokerController {
keyChanged = true;
}
if (certChanged && keyChanged) {
- log.info("The certificate and private key changed, reload the ssl context");
+ LOG.info("The certificate and private key changed, reload the ssl context");
certChanged = keyChanged = false;
reloadServerSslContext();
}
@@ -571,26 +756,76 @@ public class BrokerController {
}
});
} catch (Exception e) {
- log.warn("FileWatchService created error, can't load the certificate dynamically");
+ result = false;
+ LOG.warn("FileWatchService created error, can't load the certificate dynamically");
}
}
- initialTransaction();
- initialAcl();
- initialRpcHooks();
}
+
return result;
}
+ public void registerMessageStoreHook() {
+ List<PutMessageHook> putMessageHookList = messageStore.getPutMessageHookList();
+
+ putMessageHookList.add(new PutMessageHook() {
+ @Override public String hookName() {
+ return "checkBeforePutMessage";
+ }
+
+ @Override public PutMessageResult executeBeforePutMessage(MessageExt msg) {
+ return HookUtils.checkBeforePutMessage(BrokerController.this, msg);
+ }
+ });
+
+ putMessageHookList.add(new PutMessageHook() {
+ @Override public String hookName() {
+ return "innerBatchChecker";
+ }
+
+ @Override public PutMessageResult executeBeforePutMessage(MessageExt msg) {
+ if (msg instanceof MessageExtBrokerInner) {
+ return HookUtils.checkInnerBatch(BrokerController.this, msg);
+ }
+ return null;
+ }
+ });
+
+ putMessageHookList.add(new PutMessageHook() {
+ @Override public String hookName() {
+ return "handleScheduleMessage";
+ }
+
+ @Override public PutMessageResult executeBeforePutMessage(MessageExt msg) {
+ if (msg instanceof MessageExtBrokerInner) {
+ return HookUtils.handleScheduleMessage(BrokerController.this, (MessageExtBrokerInner) msg);
+ }
+ return null;
+ }
+ });
+
+ SendMessageBackHook sendMessageBackHook = new SendMessageBackHook() {
+ @Override
+ public boolean executeSendMessageBack(List<MessageExt> msgList, String brokerName, String brokerAddr) {
+ return HookUtils.sendMessageBack(BrokerController.this, msgList, brokerName, brokerAddr);
+ }
+ };
+
+ if (messageStore != null) {
+ messageStore.setSendMessageBackHook(sendMessageBackHook);
+ }
+ }
+
private void initialTransaction() {
this.transactionalMessageService = ServiceProvider.loadClass(ServiceProvider.TRANSACTION_SERVICE_ID, TransactionalMessageService.class);
if (null == this.transactionalMessageService) {
this.transactionalMessageService = new TransactionalMessageServiceImpl(new TransactionalMessageBridge(this, this.getMessageStore()));
- log.warn("Load default transaction message hook service: {}", TransactionalMessageServiceImpl.class.getSimpleName());
+ LOG.warn("Load default transaction message hook service: {}", TransactionalMessageServiceImpl.class.getSimpleName());
}
this.transactionalMessageCheckListener = ServiceProvider.loadClass(ServiceProvider.TRANSACTION_LISTENER_ID, AbstractTransactionalMessageCheckListener.class);
if (null == this.transactionalMessageCheckListener) {
this.transactionalMessageCheckListener = new DefaultTransactionalMessageCheckListener();
- log.warn("Load default discard message hook service: {}", DefaultTransactionalMessageCheckListener.class.getSimpleName());
+ LOG.warn("Load default discard message hook service: {}", DefaultTransactionalMessageCheckListener.class.getSimpleName());
}
this.transactionalMessageCheckListener.setBrokerController(this);
this.transactionalMessageCheckService = new TransactionalMessageCheckService(this);
@@ -598,13 +833,13 @@ public class BrokerController {
private void initialAcl() {
if (!this.brokerConfig.isAclEnable()) {
- log.info("The broker dose not enable acl");
+ LOG.info("The broker dose not enable acl");
return;
}
List<AccessValidator> accessValidators = ServiceProvider.load(ServiceProvider.ACL_VALIDATOR_ID, AccessValidator.class);
- if (accessValidators == null || accessValidators.isEmpty()) {
- log.info("The broker dose not load the AccessValidator");
+ if (accessValidators.isEmpty()) {
+ LOG.info("The broker dose not load the AccessValidator");
return;
}
@@ -622,6 +857,11 @@ public class BrokerController {
@Override
public void doAfterResponse(String remoteAddr, RemotingCommand request, RemotingCommand response) {
}
+
+ @Override
+ public void doAfterRpcFailure(String remoteAddr, RemotingCommand request, Boolean remoteTimeout) {
+
+ }
});
}
}
@@ -637,15 +877,10 @@ public class BrokerController {
}
}
- public String getBrokerAddrByName(String brokerName) {
- return this.brokerName2AddrMap.get(brokerName);
- }
-
public void registerProcessor() {
- /**
+ /*
* SendMessageProcessor
*/
-
sendMessageProcessor.registerSendMessageHook(sendMessageHookList);
sendMessageProcessor.registerConsumeMessageHook(consumeMessageHookList);
@@ -661,8 +896,13 @@ public class BrokerController {
* PullMessageProcessor
*/
this.remotingServer.registerProcessor(RequestCode.PULL_MESSAGE, this.pullMessageProcessor, this.pullMessageExecutor);
+ this.remotingServer.registerProcessor(RequestCode.LITE_PULL_MESSAGE, this.pullMessageProcessor, this.litePullMessageExecutor);
this.pullMessageProcessor.registerConsumeMessageHook(consumeMessageHookList);
/**
+ * PeekMessageProcessor
+ */
+ this.remotingServer.registerProcessor(RequestCode.PEEK_MESSAGE, this.peekMessageProcessor, this.pullMessageExecutor);
+ /**
* PopMessageProcessor
*/
this.remotingServer.registerProcessor(RequestCode.POP_MESSAGE, this.popMessageProcessor, this.pullMessageExecutor);
@@ -677,11 +917,20 @@ public class BrokerController {
*/
this.remotingServer.registerProcessor(RequestCode.CHANGE_MESSAGE_INVISIBLETIME, this.changeInvisibleTimeProcessor, this.ackMessageExecutor);
this.fastRemotingServer.registerProcessor(RequestCode.CHANGE_MESSAGE_INVISIBLETIME, this.changeInvisibleTimeProcessor, this.ackMessageExecutor);
+ /**
+ * notificationProcessor
+ */
+ this.remotingServer.registerProcessor(RequestCode.NOTIFICATION, this.notificationProcessor, this.pullMessageExecutor);
+
+ /**
+ * pollingInfoProcessor
+ */
+ this.remotingServer.registerProcessor(RequestCode.POLLING_INFO, this.pollingInfoProcessor, this.pullMessageExecutor);
/**
* ReplyMessageProcessor
*/
- ReplyMessageProcessor replyMessageProcessor = new ReplyMessageProcessor(this);
+
replyMessageProcessor.registerSendMessageHook(sendMessageHookList);
this.remotingServer.registerProcessor(RequestCode.SEND_REPLY_MESSAGE, replyMessageProcessor, replyMessageExecutor);
@@ -733,10 +982,10 @@ public class BrokerController {
/**
* EndTransactionProcessor
*/
- this.remotingServer.registerProcessor(RequestCode.END_TRANSACTION, new EndTransactionProcessor(this), this.endTransactionExecutor);
- this.fastRemotingServer.registerProcessor(RequestCode.END_TRANSACTION, new EndTransactionProcessor(this), this.endTransactionExecutor);
+ this.remotingServer.registerProcessor(RequestCode.END_TRANSACTION, new EndTransactionProcessor(this), this.sendMessageExecutor);
+ this.fastRemotingServer.registerProcessor(RequestCode.END_TRANSACTION, new EndTransactionProcessor(this), this.sendMessageExecutor);
- /**
+ /*
* Default
*/
AdminBrokerProcessor adminProcessor = new AdminBrokerProcessor(this);
@@ -754,9 +1003,7 @@ public class BrokerController {
public void protectBroker() {
if (this.brokerConfig.isDisableConsumeIfConsumerReadSlowly()) {
- final Iterator<Map.Entry<String, MomentStatsItem>> it = this.brokerStatsManager.getMomentStatsItemSetFallSize().getStatsItemTable().entrySet().iterator();
- while (it.hasNext()) {
- final Map.Entry<String, MomentStatsItem> next = it.next();
+ for (Map.Entry<String, MomentStatsItem> next : this.brokerStatsManager.getMomentStatsItemSetFallSize().getStatsItemTable().entrySet()) {
final long fallBehindBytes = next.getValue().getValue().get();
if (fallBehindBytes > this.brokerConfig.getConsumerFallbehindThreshold()) {
final String[] split = next.getValue().getStatsKey().split("@");
@@ -791,19 +1038,23 @@ public class BrokerController {
return this.headSlowTimeMills(this.pullThreadPoolQueue);
}
- public long headSlowTimeMills4QueryThreadPoolQueue() {
- return this.headSlowTimeMills(this.queryThreadPoolQueue);
+ public long headSlowTimeMills4LitePullThreadPoolQueue() {
+ return this.headSlowTimeMills(this.litePullThreadPoolQueue);
}
- public long headSlowTimeMills4EndTransactionThreadPoolQueue() {
- return this.headSlowTimeMills(this.endTransactionThreadPoolQueue);
+ public long headSlowTimeMills4QueryThreadPoolQueue() {
+ return this.headSlowTimeMills(this.queryThreadPoolQueue);
}
public void printWaterMark() {
LOG_WATER_MARK.info("[WATERMARK] Send Queue Size: {} SlowTimeMills: {}", this.sendThreadPoolQueue.size(), headSlowTimeMills4SendThreadPoolQueue());
LOG_WATER_MARK.info("[WATERMARK] Pull Queue Size: {} SlowTimeMills: {}", this.pullThreadPoolQueue.size(), headSlowTimeMills4PullThreadPoolQueue());
LOG_WATER_MARK.info("[WATERMARK] Query Queue Size: {} SlowTimeMills: {}", this.queryThreadPoolQueue.size(), headSlowTimeMills4QueryThreadPoolQueue());
- LOG_WATER_MARK.info("[WATERMARK] Transaction Queue Size: {} SlowTimeMills: {}", this.endTransactionThreadPoolQueue.size(), headSlowTimeMills4EndTransactionThreadPoolQueue());
+ LOG_WATER_MARK.info("[WATERMARK] Lite Pull Queue Size: {} SlowTimeMills: {}", this.litePullThreadPoolQueue.size(), headSlowTimeMills4LitePullThreadPoolQueue());
+ LOG_WATER_MARK.info("[WATERMARK] Transaction Queue Size: {} SlowTimeMills: {}", this.endTransactionThreadPoolQueue.size(), headSlowTimeMills(this.endTransactionThreadPoolQueue));
+ LOG_WATER_MARK.info("[WATERMARK] ClientManager Queue Size: {} SlowTimeMills: {}", this.clientManagerThreadPoolQueue.size(), this.headSlowTimeMills(this.clientManagerThreadPoolQueue));
+ LOG_WATER_MARK.info("[WATERMARK] Heartbeat Queue Size: {} SlowTimeMills: {}", this.heartbeatThreadPoolQueue.size(), this.headSlowTimeMills(this.heartbeatThreadPoolQueue));
+ LOG_WATER_MARK.info("[WATERMARK] Ack Queue Size: {} SlowTimeMills: {}", this.ackThreadPoolQueue.size(), headSlowTimeMills(this.ackThreadPoolQueue));
}
public MessageStore getMessageStore() {
@@ -814,11 +1065,11 @@ public class BrokerController {
this.messageStore = messageStore;
}
- private void printMasterAndSlaveDiff() {
- long diff = this.messageStore.slaveFallBehindMuch();
-
- // XXX: warn and notify me
- log.info("Slave fall behind master: {} bytes", diff);
+ protected void printMasterAndSlaveDiff() {
+ if (messageStore.getHaService() != null && messageStore.getHaService().getConnectionCount().get() > 0) {
+ long diff = this.messageStore.slaveFallBehindMuch();
+ LOG.info("CommitLog: slave fall behind master {}bytes", diff);
+ }
}
public Broker2Client getBroker2Client() {
@@ -853,6 +1104,10 @@ public class BrokerController {
this.fastRemotingServer = fastRemotingServer;
}
+ public RemotingServer getFastRemotingServer() {
+ return fastRemotingServer;
+ }
+
public PullMessageProcessor getPullMessageProcessor() {
return pullMessageProcessor;
}
@@ -869,7 +1124,24 @@ public class BrokerController {
return popMessageProcessor;
}
- public void shutdown() {
+ protected void shutdownBasicService() {
+
+ shutdown = true;
+
+ this.unregisterBrokerAll();
+
+ if (this.shutdownHook != null) {
+ this.shutdownHook.beforeShutdown(this);
+ }
+
+ if (this.remotingServer != null) {
+ this.remotingServer.shutdown();
+ }
+
+ if (this.fastRemotingServer != null) {
+ this.fastRemotingServer.shutdown();
+ }
+
if (this.brokerStatsManager != null) {
this.brokerStatsManager.shutdown();
}
@@ -882,12 +1154,26 @@ public class BrokerController {
this.pullRequestHoldService.shutdown();
}
- if (this.remotingServer != null) {
- this.remotingServer.shutdown();
+ {
+ this.popMessageProcessor.getPopLongPollingService().shutdown();
+ this.popMessageProcessor.getQueueLockManager().shutdown();
}
- if (this.fastRemotingServer != null) {
- this.fastRemotingServer.shutdown();
+ {
+ this.popMessageProcessor.getPopBufferMergeService().shutdown();
+ this.ackMessageProcessor.shutdownPopReviveService();
+ }
+
+ if (this.assignmentManager != null) {
+ this.assignmentManager.shutdown();
+ }
+
+ if (this.notificationProcessor != null) {
+ this.notificationProcessor.shutdown();
+ }
+
+ if (this.consumerIdsChangeListener != null) {
+ this.consumerIdsChangeListener.shutdown();
}
if (this.topicQueueMappingCleanService != null) {
@@ -902,20 +1188,14 @@ public class BrokerController {
this.messageStore.shutdown();
}
- this.scheduledExecutorService.shutdown();
- try {
- this.scheduledExecutorService.awaitTermination(5000, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- }
-
- this.unregisterBrokerAll();
+ shutdownScheduledExecutorService(this.scheduledExecutorService);
if (this.sendMessageExecutor != null) {
this.sendMessageExecutor.shutdown();
}
- if (this.putMessageFutureExecutor != null) {
- this.putMessageFutureExecutor.shutdown();
+ if (this.litePullMessageExecutor != null) {
+ this.litePullMessageExecutor.shutdown();
}
if (this.pullMessageExecutor != null) {
@@ -926,12 +1206,16 @@ public class BrokerController {
this.replyMessageExecutor.shutdown();
}
- if (this.adminBrokerExecutor != null) {
- this.adminBrokerExecutor.shutdown();
+ if (this.putMessageFutureExecutor != null) {
+ this.putMessageFutureExecutor.shutdown();
}
- if (this.brokerOuterAPI != null) {
- this.brokerOuterAPI.shutdown();
+ if (this.ackMessageExecutor != null) {
+ this.ackMessageExecutor.shutdown();
+ }
+
+ if (this.adminBrokerExecutor != null) {
+ this.adminBrokerExecutor.shutdown();
}
this.consumerOffsetManager.persist();
@@ -948,6 +1232,15 @@ public class BrokerController {
this.consumerFilterManager.persist();
}
+ if (this.consumerOrderInfoManager != null) {
+ this.consumerOrderInfoManager.persist();
+ }
+
+ if (this.scheduleMessageService != null) {
+ this.scheduleMessageService.persist();
+ this.scheduleMessageService.shutdown();
+ }
+
if (this.clientManageExecutor != null) {
this.clientManageExecutor.shutdown();
}
@@ -956,13 +1249,12 @@ public class BrokerController {
this.queryMessageExecutor.shutdown();
}
- if (this.consumerManageExecutor != null) {
- this.consumerManageExecutor.shutdown();
+ if (this.heartbeatExecutor != null) {
+ this.heartbeatExecutor.shutdown();
}
- {
- this.popMessageProcessor.getPopBufferMergeService().shutdown();
- this.ackMessageProcessor.shutdownPopReviveService();
+ if (this.consumerManageExecutor != null) {
+ this.consumerManageExecutor.shutdown();
}
if (this.fileWatchService != null) {
@@ -975,9 +1267,42 @@ public class BrokerController {
if (this.endTransactionExecutor != null) {
this.endTransactionExecutor.shutdown();
}
+
+ if (this.escapeBridge != null) {
+ escapeBridge.shutdown();
+ }
+
+ this.topicConfigManager.persist();
+ this.subscriptionGroupManager.persist();
+
+ for (BrokerAttachedPlugin brokerAttachedPlugin : brokerAttachedPlugins) {
+ if (brokerAttachedPlugin != null) {
+ brokerAttachedPlugin.shutdown();
+ }
+ }
+ }
+
+ public void shutdown() {
+
+ shutdownBasicService();
+
+ if (this.brokerOuterAPI != null) {
+ this.brokerOuterAPI.shutdown();
+ }
+ }
+
+ protected void shutdownScheduledExecutorService(ScheduledExecutorService scheduledExecutorService) {
+ if (scheduledExecutorService == null) {
+ return;
+ }
+ scheduledExecutorService.shutdown();
+ try {
+ scheduledExecutorService.awaitTermination(5000, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException ignore) {
+ }
}
- private void unregisterBrokerAll() {
+ protected void unregisterBrokerAll() {
this.brokerOuterAPI.unregisterBrokerAll(
this.brokerConfig.getBrokerClusterName(),
this.getBrokerAddr(),
@@ -989,30 +1314,42 @@ public class BrokerController {
return this.brokerConfig.getBrokerIP1() + ":" + this.nettyServerConfig.getListenPort();
}
- public void start() throws Exception {
- this.shouldStartTime = System.currentTimeMillis();
+ protected void startBasicService() throws Exception {
if (this.messageStore != null) {
this.messageStore.start();
}
+ if (remotingServerStartLatch != null) {
+ remotingServerStartLatch.await();
+ }
+
if (this.remotingServer != null) {
this.remotingServer.start();
}
- {
+ if (this.fastRemotingServer != null) {
+ this.fastRemotingServer.start();
+ }
+
+ for (BrokerAttachedPlugin brokerAttachedPlugin : brokerAttachedPlugins) {
+ if (brokerAttachedPlugin != null) {
+ brokerAttachedPlugin.start();
+ }
+ }
+
+ if (this.popMessageProcessor != null) {
this.popMessageProcessor.getPopLongPollingService().start();
this.popMessageProcessor.getPopBufferMergeService().start();
this.popMessageProcessor.getQueueLockManager().start();
- this.ackMessageProcessor.startPopReviveService();
}
- {
- assignmentManager.start();
+ if (this.ackMessageProcessor != null) {
+ this.ackMessageProcessor.startPopReviveService();
}
- if (this.fastRemotingServer != null) {
- this.fastRemotingServer.start();
+ if (this.assignmentManager != null) {
+ this.assignmentManager.start();
}
if (this.topicQueueMappingCleanService != null) {
@@ -1023,10 +1360,6 @@ public class BrokerController {
this.fileWatchService.start();
}
- if (this.brokerOuterAPI != null) {
- this.brokerOuterAPI.start();
- }
-
if (this.pullRequestHoldService != null) {
this.pullRequestHoldService.start();
}
@@ -1039,9 +1372,34 @@ public class BrokerController {
this.filterServerManager.start();
}
- if (!messageStoreConfig.isEnableDLegerCommitLog()) {
- startProcessorByHa(messageStoreConfig.getBrokerRole());
- handleSlaveSynchronize(messageStoreConfig.getBrokerRole());
+ if (this.brokerStatsManager != null) {
+ this.brokerStatsManager.start();
+ }
+
+ if (this.brokerFastFailure != null) {
+ this.brokerFastFailure.start();
+ }
+
+ if (this.escapeBridge != null) {
+ this.escapeBridge.start();
+ }
+
+ //Init state version after messageStore initialized.
+ this.topicConfigManager.initStateVersion();
+ }
+
+ public void start() throws Exception {
+
+ this.shouldStartTime = System.currentTimeMillis() + messageStoreConfig.getDisappearTimeAfterStart();
+
+ if (this.brokerOuterAPI != null) {
+ this.brokerOuterAPI.start();
+ }
+
+ startBasicService();
+
+ if (!this.messageStoreConfig.isEnableDLegerCommitLog() && !this.messageStoreConfig.isDuplicationEnable()) {
+ changeSpecialServiceStatus(this.brokerConfig.getBrokerId() == MixAll.MASTER_ID);
this.registerBrokerAll(true, false, true);
}
@@ -1050,21 +1408,17 @@ public class BrokerController {
@Override
public void run() {
try {
+ if (System.currentTimeMillis() < shouldStartTime) {
+ LOG.info("Register to namesrv after {}", shouldStartTime);
+ return;
+ }
BrokerController.this.registerBrokerAll(true, false, brokerConfig.isForceRegister());
} catch (Throwable e) {
- log.error("registerBrokerAll Exception", e);
+ LOG.error("BrokerController#registerBrokerAll: unexpected error occurs.", e);
}
}
}, 1000 * 10, Math.max(10000, Math.min(brokerConfig.getRegisterNameServerPeriod(), 60000)), TimeUnit.MILLISECONDS);
- if (this.brokerStatsManager != null) {
- this.brokerStatsManager.start();
- }
-
- if (this.brokerFastFailure != null) {
- this.brokerFastFailure.start();
- }
-
}
public synchronized void registerIncrementBrokerData(TopicConfig topicConfig, DataVersion dataVersion) {
@@ -1088,7 +1442,7 @@ public class BrokerController {
new TopicConfig(topicConfig.getTopicName(),
topicConfig.getReadQueueNums(),
topicConfig.getWriteQueueNums(),
- this.brokerConfig.getBrokerPermission());
+ this.brokerConfig.getBrokerPermission(), topicConfig.getTopicSysFlag());
} else {
registerTopicConfig = new TopicConfig(topicConfig);
}
@@ -1128,7 +1482,7 @@ public class BrokerController {
for (TopicConfig topicConfig : topicConfigWrapper.getTopicConfigTable().values()) {
TopicConfig tmp =
new TopicConfig(topicConfig.getTopicName(), topicConfig.getReadQueueNums(), topicConfig.getWriteQueueNums(),
- this.brokerConfig.getBrokerPermission());
+ topicConfig.getPerm() & this.brokerConfig.getBrokerPermission(), topicConfig.getTopicSysFlag());
topicConfigTable.put(topicConfig.getTopicName(), tmp);
}
topicConfigWrapper.setTopicConfigTable(topicConfigTable);
@@ -1138,14 +1492,20 @@ public class BrokerController {
this.getBrokerAddr(),
this.brokerConfig.getBrokerName(),
this.brokerConfig.getBrokerId(),
- this.brokerConfig.getRegisterBrokerTimeoutMills())) {
+ this.brokerConfig.getRegisterBrokerTimeoutMills(),
+ this.brokerConfig.isInBrokerContainer())) {
doRegisterBrokerAll(checkOrderConfig, oneway, topicConfigWrapper);
}
}
- private void doRegisterBrokerAll(boolean checkOrderConfig, boolean oneway,
- TopicConfigAndMappingSerializeWrapper topicConfigWrapper) {
- List<RegisterBrokerResult> registerBrokerResultList = this.brokerOuterAPI.registerBrokerAll(
+ protected void doRegisterBrokerAll(boolean checkOrderConfig, boolean oneway,
+ TopicConfigSerializeWrapper topicConfigWrapper) {
+
+ if (shutdown) {
+ LOG.info("BrokerController#doResterBrokerAll: broker has shutdown, no need to register any more.");
+ return;
+ }
+ List<RegisterBrokerResult> registerBrokerResultList = this.getBrokerOuterAPI().registerBrokerAll(
this.brokerConfig.getBrokerClusterName(),
this.getBrokerAddr(),
this.brokerConfig.getBrokerName(),
@@ -1155,10 +1515,16 @@ public class BrokerController {
this.filterServerManager.buildNewFilterServerList(),
oneway,
this.brokerConfig.getRegisterBrokerTimeoutMills(),
- this.brokerConfig.isCompressedRegister());
+ this.brokerConfig.isEnableSlaveActingMaster(),
+ this.brokerConfig.isCompressedRegister(),
+ this.brokerConfig.isInBrokerContainer());
+
+ handleRegisterBrokerResult(registerBrokerResultList, checkOrderConfig);
+ }
- if (registerBrokerResultList.size() > 0) {
- RegisterBrokerResult registerBrokerResult = registerBrokerResultList.get(0);
+ protected void handleRegisterBrokerResult(List<RegisterBrokerResult> registerBrokerResultList,
+ boolean checkOrderConfig) {
+ for (RegisterBrokerResult registerBrokerResult : registerBrokerResultList) {
if (registerBrokerResult != null) {
if (this.updateMasterHAServerAddrPeriodically && registerBrokerResult.getHaServerAddr() != null) {
this.messageStore.updateHaMasterAddress(registerBrokerResult.getHaServerAddr());
@@ -1169,6 +1535,7 @@ public class BrokerController {
if (checkOrderConfig) {
this.getTopicConfigManager().updateOrderTopicConfig(registerBrokerResult.getKvTable());
}
+ break;
}
}
}
@@ -1177,10 +1544,11 @@ public class BrokerController {
final String brokerAddr,
final String brokerName,
final long brokerId,
- final int timeoutMills) {
+ final int timeoutMills,
+ final boolean isInBrokerContainer) {
TopicConfigSerializeWrapper topicConfigWrapper = this.getTopicConfigManager().buildTopicConfigSerializeWrapper();
- List<Boolean> changeList = brokerOuterAPI.needRegister(clusterName, brokerAddr, brokerName, brokerId, topicConfigWrapper, timeoutMills);
+ List<Boolean> changeList = brokerOuterAPI.needRegister(clusterName, brokerAddr, brokerName, brokerId, topicConfigWrapper, timeoutMills, isInBrokerContainer);
boolean needRegister = false;
for (Boolean changed : changeList) {
if (changed) {
@@ -1191,6 +1559,16 @@ public class BrokerController {
return needRegister;
}
+ public String getNameServerList() {
+ if (this.brokerConfig.getNamesrvAddr() != null) {
+ this.brokerOuterAPI.updateNameServerAddressList(this.brokerConfig.getNamesrvAddr());
+ return this.brokerConfig.getNamesrvAddr();
+ } else if (this.brokerConfig.isFetchNamesrvAddrByAddressServer()) {
+ return this.brokerOuterAPI.fetchNameServerAddr();
+ }
+ return null;
+ }
+
public TopicConfigManager getTopicConfigManager() {
return topicConfigManager;
}
@@ -1215,10 +1593,18 @@ public class BrokerController {
return slaveSynchronize;
}
+ public ScheduledExecutorService getScheduledExecutorService() {
+ return scheduledExecutorService;
+ }
+
public ExecutorService getPullMessageExecutor() {
return pullMessageExecutor;
}
+ public ExecutorService getPutMessageFutureExecutor() {
+ return putMessageFutureExecutor;
+ }
+
public void setPullMessageExecutor(ExecutorService pullMessageExecutor) {
this.pullMessageExecutor = pullMessageExecutor;
}
@@ -1227,6 +1613,10 @@ public class BrokerController {
return sendThreadPoolQueue;
}
+ public BlockingQueue<Runnable> getAckThreadPoolQueue() {
+ return ackThreadPoolQueue;
+ }
+
public FilterServerManager getFilterServerManager() {
return filterServerManager;
}
@@ -1241,7 +1631,7 @@ public class BrokerController {
public void registerSendMessageHook(final SendMessageHook hook) {
this.sendMessageHookList.add(hook);
- log.info("register SendMessageHook Hook, {}", hook.hookName());
+ LOG.info("register SendMessageHook Hook, {}", hook.hookName());
}
public List<ConsumeMessageHook> getConsumeMessageHookList() {
@@ -1250,7 +1640,7 @@ public class BrokerController {
public void registerConsumeMessageHook(final ConsumeMessageHook hook) {
this.consumeMessageHookList.add(hook);
- log.info("register ConsumeMessageHook Hook, {}", hook.hookName());
+ LOG.info("register ConsumeMessageHook Hook, {}", hook.hookName());
}
public void registerServerRPCHook(RPCHook rpcHook) {
@@ -1266,6 +1656,14 @@ public class BrokerController {
this.remotingServer = remotingServer;
}
+ public CountDownLatch getRemotingServerStartLatch() {
+ return remotingServerStartLatch;
+ }
+
+ public void setRemotingServerStartLatch(CountDownLatch remotingServerStartLatch) {
+ this.remotingServerStartLatch = remotingServerStartLatch;
+ }
+
public void registerClientRPCHook(RPCHook rpcHook) {
this.getBrokerOuterAPI().registerRPCHook(rpcHook);
}
@@ -1325,133 +1723,140 @@ public class BrokerController {
return accessValidatorMap;
}
- private void handleSlaveSynchronize(BrokerRole role) {
- if (role == BrokerRole.SLAVE) {
- if (null != slaveSyncFuture) {
- slaveSyncFuture.cancel(false);
- }
- this.slaveSynchronize.setMasterAddr(null);
- slaveSyncFuture = this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try {
- BrokerController.this.slaveSynchronize.syncAll();
- } catch (Throwable e) {
- log.error("ScheduledTask SlaveSynchronize syncAll error.", e);
- }
- }
- }, 1000 * 3, 1000 * 10, TimeUnit.MILLISECONDS);
- } else {
- //handle the slave synchronise
- if (null != slaveSyncFuture) {
- slaveSyncFuture.cancel(false);
- }
- this.slaveSynchronize.setMasterAddr(null);
- }
+ public ExecutorService getSendMessageExecutor() {
+ return sendMessageExecutor;
}
- public void changeToSlave(int brokerId) {
- log.info("Begin to change to slave brokerName={} brokerId={}", brokerConfig.getBrokerName(), brokerId);
+ public AssignmentManager getAssignmentManager() {
+ return assignmentManager;
+ }
- //change the role
- brokerConfig.setBrokerId(brokerId == 0 ? 1 : brokerId); //TO DO check
- messageStoreConfig.setBrokerRole(BrokerRole.SLAVE);
+ public SendMessageProcessor getSendMessageProcessor() {
+ return sendMessageProcessor;
+ }
- //handle the scheduled service
- try {
- this.messageStore.handleScheduleMessageService(BrokerRole.SLAVE);
- } catch (Throwable t) {
- log.error("[MONITOR] handleScheduleMessageService failed when changing to slave", t);
- }
+ public QueryAssignmentProcessor getQueryAssignmentProcessor() {
+ return queryAssignmentProcessor;
+ }
- //handle the transactional service
- try {
- this.shutdownProcessorByHa();
- } catch (Throwable t) {
- log.error("[MONITOR] shutdownProcessorByHa failed when changing to slave", t);
- }
+ public TopicQueueMappingCleanService getTopicQueueMappingCleanService() {
+ return topicQueueMappingCleanService;
+ }
- //handle the slave synchronise
- handleSlaveSynchronize(BrokerRole.SLAVE);
+ public ExecutorService getAdminBrokerExecutor() {
+ return adminBrokerExecutor;
+ }
- try {
- this.registerBrokerAll(true, true, true);
- } catch (Throwable ignored) {
+ public BlockingQueue<Runnable> getLitePullThreadPoolQueue() {
+ return litePullThreadPoolQueue;
+ }
- }
- log.info("Finish to change to slave brokerName={} brokerId={}", brokerConfig.getBrokerName(), brokerId);
+ public ShutdownHook getShutdownHook() {
+ return shutdownHook;
}
- public void changeToMaster(BrokerRole role) {
- if (role == BrokerRole.SLAVE) {
- return;
- }
- log.info("Begin to change to master brokerName={}", brokerConfig.getBrokerName());
+ public void setShutdownHook(ShutdownHook shutdownHook) {
+ this.shutdownHook = shutdownHook;
+ }
- //handle the slave synchronise
- handleSlaveSynchronize(role);
+ public long getMinBrokerIdInGroup() {
+ return this.brokerConfig.getBrokerId();
+ }
- //handle the scheduled service
- try {
- this.messageStore.handleScheduleMessageService(role);
- } catch (Throwable t) {
- log.error("[MONITOR] handleScheduleMessageService failed when changing to master", t);
- }
+ public BrokerController peekMasterBroker() {
+ return brokerConfig.getBrokerId() == MixAll.MASTER_ID ? this : null;
+ }
- //handle the transactional service
- try {
- this.startProcessorByHa(BrokerRole.SYNC_MASTER);
- } catch (Throwable t) {
- log.error("[MONITOR] startProcessorByHa failed when changing to master", t);
- }
+ public BrokerMemberGroup getBrokerMemberGroup() {
+ return this.brokerMemberGroup;
+ }
- //if the operations above are totally successful, we change to master
- brokerConfig.setBrokerId(0); //TO DO check
- messageStoreConfig.setBrokerRole(role);
+ public boolean isSpecialServiceRunning() {
+ return this.brokerConfig.getBrokerId() == MixAll.MASTER_ID;
+ }
- try {
- this.registerBrokerAll(true, true, true);
- } catch (Throwable ignored) {
+ public void updateMinBroker(long minBrokerId, String minBrokerAddr) {
+ //do nothing
+ }
- }
- log.info("Finish to change to master brokerName={}", brokerConfig.getBrokerName());
+ public void updateMinBroker(long minBrokerId, String minBrokerAddr, String offlineBrokerAddr, String masterHaAddr) {
+ //do nothing
}
- private void startProcessorByHa(BrokerRole role) {
- if (BrokerRole.SLAVE != role) {
- if (this.transactionalMessageCheckService != null) {
- this.transactionalMessageCheckService.start();
- }
- }
+ public int getListenPort() {
+ return this.nettyServerConfig.getListenPort();
}
- private void shutdownProcessorByHa() {
- if (this.transactionalMessageCheckService != null) {
- this.transactionalMessageCheckService.shutdown(true);
- }
+ public List<BrokerAttachedPlugin> getBrokerAttachedPlugins() {
+ return brokerAttachedPlugins;
}
- public ExecutorService getPutMessageFutureExecutor() {
- return putMessageFutureExecutor;
+ public EscapeBridge getEscapeBridge() {
+ return escapeBridge;
}
public long getShouldStartTime() {
return shouldStartTime;
}
- public AssignmentManager getAssignmentManager() {
- return assignmentManager;
+ public void changeSpecialServiceStatus(boolean shouldStart) {
+
+ for (BrokerAttachedPlugin brokerAttachedPlugin : brokerAttachedPlugins) {
+ if (brokerAttachedPlugin != null) {
+ brokerAttachedPlugin.statusChanged(shouldStart);
+ }
+ }
+
+ changeScheduleServiceStatus(shouldStart);
+
+ changeTransactionCheckServiceStatus(shouldStart);
+
+ if (this.ackMessageProcessor != null) {
+ LOG.info("Set PopReviveService Status to {}", shouldStart);
+ this.ackMessageProcessor.setPopReviveServiceStatus(shouldStart);
+ }
}
- public SendMessageProcessor getSendMessageProcessor() {
- return sendMessageProcessor;
+ private synchronized void changeTransactionCheckServiceStatus(boolean shouldStart) {
+ if (isTransactionCheckServiceStart != shouldStart) {
+ LOG.info("TransactionCheckService status changed to {}", shouldStart);
+ if (shouldStart) {
+ this.transactionalMessageCheckService.start();
+ } else {
+ this.transactionalMessageCheckService.shutdown(true);
+ }
+ isTransactionCheckServiceStart = shouldStart;
+ }
}
- public QueryAssignmentProcessor getQueryAssignmentProcessor() {
- return queryAssignmentProcessor;
+ public synchronized void changeScheduleServiceStatus(boolean shouldStart) {
+ if (isScheduleServiceStart != shouldStart) {
+ LOG.info("ScheduleServiceStatus changed to {}", shouldStart);
+ if (shouldStart) {
+ this.scheduleMessageService.start();
+ } else {
+ this.scheduleMessageService.stop();
+ }
+ isScheduleServiceStart = shouldStart;
+ }
}
- public TopicQueueMappingCleanService getTopicQueueMappingCleanService() {
- return topicQueueMappingCleanService;
+ public boolean isScheduleServiceStart() {
+ return isScheduleServiceStart;
+ }
+
+ public boolean isTransactionCheckServiceStart() {
+ return isTransactionCheckServiceStart;
+ }
+
+ public ScheduleMessageService getScheduleMessageService() {
+ return scheduleMessageService;
+ }
+
+ public MessageStore getMessageStoreByBrokerName(String brokerName) {
+ if (this.brokerConfig.getBrokerName().equals(brokerName)) {
+ return this.getMessageStore();
+ }
+ return null;
}
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java b/broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java
index 19e618b..ca388b6 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java
@@ -19,9 +19,9 @@ package org.apache.rocketmq.broker;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
-import org.apache.commons.cli.PosixParser;
import org.apache.rocketmq.common.BrokerConfig;
import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.common.MixAll;
@@ -37,6 +37,7 @@ import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.srvutil.ServerUtil;
import org.apache.rocketmq.store.config.BrokerRole;
import org.apache.rocketmq.store.config.MessageStoreConfig;
+import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
@@ -52,6 +53,7 @@ public class BrokerStartup {
public static CommandLine commandLine = null;
public static String configFile = null;
public static InternalLogger log;
+ public static SystemConfigFileHelper configFileHelper = new SystemConfigFileHelper();
public static void main(String[] args) {
start(createBrokerController(args));
@@ -93,7 +95,7 @@ public class BrokerStartup {
//PackageConflictDetect.detectFastjson();
Options options = ServerUtil.buildCommandlineOptions(new Options());
commandLine = ServerUtil.parseCmdLine("mqbroker", args, buildCommandlineOptions(options),
- new PosixParser());
+ new DefaultParser());
if (null == commandLine) {
System.exit(-1);
}
@@ -115,22 +117,21 @@ public class BrokerStartup {
if (commandLine.hasOption('c')) {
String file = commandLine.getOptionValue('c');
if (file != null) {
+ configFileHelper.setFile(file);
configFile = file;
- InputStream in = new BufferedInputStream(new FileInputStream(file));
- properties = new Properties();
- properties.load(in);
-
- properties2SystemEnv(properties);
- MixAll.properties2Object(properties, brokerConfig);
- MixAll.properties2Object(properties, nettyServerConfig);
- MixAll.properties2Object(properties, nettyClientConfig);
- MixAll.properties2Object(properties, messageStoreConfig);
-
BrokerPathConfigHelper.setBrokerConfigPath(file);
- in.close();
}
}
+ properties = configFileHelper.loadConfig();
+ if (properties != null) {
+ properties2SystemEnv(properties);
+ MixAll.properties2Object(properties, brokerConfig);
+ MixAll.properties2Object(properties, nettyServerConfig);
+ MixAll.properties2Object(properties, nettyClientConfig);
+ MixAll.properties2Object(properties, messageStoreConfig);
+ }
+
MixAll.properties2Object(ServerUtil.commandLine2Properties(commandLine), brokerConfig);
if (null == brokerConfig.getRocketmqHome()) {
@@ -209,6 +210,8 @@ public class BrokerStartup {
MixAll.printObjectProperties(log, nettyClientConfig);
MixAll.printObjectProperties(log, messageStoreConfig);
+ brokerConfig.setInBrokerContainer(false);
+
final BrokerController controller = new BrokerController(
brokerConfig,
nettyServerConfig,
@@ -276,4 +279,33 @@ public class BrokerStartup {
return options;
}
+
+ public static class SystemConfigFileHelper {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SystemConfigFileHelper.class);
+
+ private String file;
+
+ public SystemConfigFileHelper() {
+ }
+
+ public Properties loadConfig() throws Exception {
+ InputStream in = new BufferedInputStream(new FileInputStream(file));
+ Properties properties = new Properties();
+ properties.load(in);
+ in.close();
+ return properties;
+ }
+
+ public void update(Properties properties) throws Exception {
+ LOGGER.error("[SystemConfigFileHelper] update no thing.");
+ }
+
+ public void setFile(String file) {
+ this.file = file;
+ }
+
+ public String getFile() {
+ return file;
+ }
+ }
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerIdsChangeListener.java b/broker/src/main/java/org/apache/rocketmq/broker/ShutdownHook.java
similarity index 77%
copy from broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerIdsChangeListener.java
copy to broker/src/main/java/org/apache/rocketmq/broker/ShutdownHook.java
index 831e293..63567f8 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerIdsChangeListener.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/ShutdownHook.java
@@ -14,9 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.rocketmq.broker.client;
+package org.apache.rocketmq.broker;
-public interface ConsumerIdsChangeListener {
-
- void handle(ConsumerGroupEvent event, String group, Object... args);
+public interface ShutdownHook {
+ /**
+ * Code to execute before broker shutdown.
+ *
+ * @param controller broker to shutdown
+ */
+ void beforeShutdown(BrokerController controller);
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/ClientHousekeepingService.java b/broker/src/main/java/org/apache/rocketmq/broker/client/ClientHousekeepingService.java
index d536db5..e7890a4 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/ClientHousekeepingService.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/ClientHousekeepingService.java
@@ -17,8 +17,8 @@
package org.apache.rocketmq.broker.client;
import io.netty.channel.Channel;
-import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.common.ThreadFactoryImpl;
@@ -31,11 +31,12 @@ public class ClientHousekeepingService implements ChannelEventListener {
private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private final BrokerController brokerController;
- private ScheduledExecutorService scheduledExecutorService = Executors
- .newSingleThreadScheduledExecutor(new ThreadFactoryImpl("ClientHousekeepingScheduledThread"));
+ private ScheduledExecutorService scheduledExecutorService;
public ClientHousekeepingService(final BrokerController brokerController) {
this.brokerController = brokerController;
+ scheduledExecutorService = new ScheduledThreadPoolExecutor(1,
+ new ThreadFactoryImpl("ClientHousekeepingScheduledThread", brokerController.getBrokerConfig()));
}
public void start() {
@@ -64,7 +65,7 @@ public class ClientHousekeepingService implements ChannelEventListener {
@Override
public void onChannelConnect(String remoteAddr, Channel channel) {
-
+ this.brokerController.getBrokerStatsManager().incChannelConnectNum();
}
@Override
@@ -72,6 +73,7 @@ public class ClientHousekeepingService implements ChannelEventListener {
this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getFilterServerManager().doChannelCloseEvent(remoteAddr, channel);
+ this.brokerController.getBrokerStatsManager().incChannelCloseNum();
}
@Override
@@ -79,6 +81,7 @@ public class ClientHousekeepingService implements ChannelEventListener {
this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getFilterServerManager().doChannelCloseEvent(remoteAddr, channel);
+ this.brokerController.getBrokerStatsManager().incChannelExceptionNum();
}
@Override
@@ -86,5 +89,6 @@ public class ClientHousekeepingService implements ChannelEventListener {
this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel);
this.brokerController.getFilterServerManager().doChannelCloseEvent(remoteAddr, channel);
+ this.brokerController.getBrokerStatsManager().incChannelIdleNum();
}
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerGroupInfo.java b/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerGroupInfo.java
index c90d494..09e1241 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerGroupInfo.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerGroupInfo.java
@@ -68,6 +68,10 @@ public class ConsumerGroupInfo {
return subscriptionTable;
}
+ public ClientChannelInfo findChannel(final Channel channel) {
+ return this.channelInfoTable.get(channel);
+ }
+
public ConcurrentMap<Channel, ClientChannelInfo> getChannelInfoTable() {
return channelInfoTable;
}
@@ -113,6 +117,15 @@ public class ConsumerGroupInfo {
return false;
}
+ /**
+ * Update {@link #channelInfoTable} in {@link ConsumerGroupInfo}
+ *
+ * @param infoNew Channel info of new client.
+ * @param consumeType consume type of new client.
+ * @param messageModel message consuming model (CLUSTERING/BROADCASTING) of new client.
+ * @param consumeFromWhere indicate the position when the client consume message firstly.
+ * @return the result that if new connector is connected or not.
+ */
public boolean updateChannel(final ClientChannelInfo infoNew, ConsumeType consumeType,
MessageModel messageModel, ConsumeFromWhere consumeFromWhere) {
boolean updated = false;
@@ -132,9 +145,9 @@ public class ConsumerGroupInfo {
infoOld = infoNew;
} else {
if (!infoOld.getClientId().equals(infoNew.getClientId())) {
- log.error("[BUG] consumer channel exist in broker, but clientId not equal. GROUP: {} OLD: {} NEW: {} ",
- this.groupName,
- infoOld.toString(),
+ log.error(
+ "ConsumerGroupInfo: consumer channel exists in broker, but clientId is not the same one, "
+ + "group={}, old clientChannelInfo={}, new clientChannelInfo={}", groupName, infoOld.toString(),
infoNew.toString());
this.channelInfoTable.put(infoNew.getChannel(), infoNew);
}
@@ -146,6 +159,12 @@ public class ConsumerGroupInfo {
return updated;
}
+ /**
+ * Update subscription.
+ *
+ * @param subList set of {@link SubscriptionData}
+ * @return the boolean indicates the subscription has changed or not.
+ */
public boolean updateSubscription(final Set<SubscriptionData> subList) {
boolean updated = false;
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerIdsChangeListener.java b/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerIdsChangeListener.java
index 831e293..144092c 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerIdsChangeListener.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerIdsChangeListener.java
@@ -19,4 +19,6 @@ package org.apache.rocketmq.broker.client;
public interface ConsumerIdsChangeListener {
void handle(ConsumerGroupEvent event, String group, Object... args);
+
+ void shutdown();
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerManager.java b/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerManager.java
index cb60655..b3bee7c 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/ConsumerManager.java
@@ -16,32 +16,41 @@
*/
package org.apache.rocketmq.broker.client;
-import io.netty.channel.Channel;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+
+import io.netty.channel.Channel;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
-import org.apache.rocketmq.logging.InternalLogger;
-import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.common.protocol.heartbeat.ConsumeType;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.common.RemotingUtil;
+import org.apache.rocketmq.store.stats.BrokerStatsManager;
public class ConsumerManager {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ private static final InternalLogger LOGGER = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private static final long CHANNEL_EXPIRED_TIMEOUT = 1000 * 120;
- private final ConcurrentMap<String/* Group */, ConsumerGroupInfo> consumerTable =
+ private final ConcurrentMap<String, ConsumerGroupInfo> consumerTable =
new ConcurrentHashMap<String, ConsumerGroupInfo>(1024);
private final ConsumerIdsChangeListener consumerIdsChangeListener;
+ protected final BrokerStatsManager brokerStatsManager;
public ConsumerManager(final ConsumerIdsChangeListener consumerIdsChangeListener) {
this.consumerIdsChangeListener = consumerIdsChangeListener;
+ this.brokerStatsManager = null;
+ }
+
+ public ConsumerManager(final ConsumerIdsChangeListener consumerIdsChangeListener, final BrokerStatsManager brokerStatsManager) {
+ this.consumerIdsChangeListener = consumerIdsChangeListener;
+ this.brokerStatsManager = brokerStatsManager;
}
public ClientChannelInfo findChannel(final String group, final String clientId) {
@@ -61,6 +70,10 @@ public class ConsumerManager {
return null;
}
+ public ConcurrentMap<String, ConsumerGroupInfo> getConsumerTable() {
+ return this.consumerTable;
+ }
+
public ConsumerGroupInfo getConsumerGroupInfo(final String group) {
return this.consumerTable.get(group);
}
@@ -74,17 +87,18 @@ public class ConsumerManager {
return 0;
}
- public void doChannelCloseEvent(final String remoteAddr, final Channel channel) {
+ public boolean doChannelCloseEvent(final String remoteAddr, final Channel channel) {
+ boolean removed = false;
Iterator<Entry<String, ConsumerGroupInfo>> it = this.consumerTable.entrySet().iterator();
while (it.hasNext()) {
Entry<String, ConsumerGroupInfo> next = it.next();
ConsumerGroupInfo info = next.getValue();
- boolean removed = info.doChannelCloseEvent(remoteAddr, channel);
+ removed = info.doChannelCloseEvent(remoteAddr, channel);
if (removed) {
if (info.getChannelInfoTable().isEmpty()) {
ConsumerGroupInfo remove = this.consumerTable.remove(next.getKey());
if (remove != null) {
- log.info("unregister consumer ok, no any connection, and remove consumer group, {}",
+ LOGGER.info("unregister consumer ok, no any connection, and remove consumer group, {}",
next.getKey());
this.consumerIdsChangeListener.handle(ConsumerGroupEvent.UNREGISTER, next.getKey());
}
@@ -93,12 +107,13 @@ public class ConsumerManager {
this.consumerIdsChangeListener.handle(ConsumerGroupEvent.CHANGE, next.getKey(), info.getAllChannel());
}
}
+ return removed;
}
public boolean registerConsumer(final String group, final ClientChannelInfo clientChannelInfo,
ConsumeType consumeType, MessageModel messageModel, ConsumeFromWhere consumeFromWhere,
final Set<SubscriptionData> subList, boolean isNotifyConsumerIdsChangedEnable) {
-
+ long start = System.currentTimeMillis();
ConsumerGroupInfo consumerGroupInfo = this.consumerTable.get(group);
if (null == consumerGroupInfo) {
ConsumerGroupInfo tmp = new ConsumerGroupInfo(group, consumeType, messageModel, consumeFromWhere);
@@ -116,6 +131,9 @@ public class ConsumerManager {
this.consumerIdsChangeListener.handle(ConsumerGroupEvent.CHANGE, group, consumerGroupInfo.getAllChannel());
}
}
+ if (null != this.brokerStatsManager) {
+ this.brokerStatsManager.incConsumerRegisterTime((int) (System.currentTimeMillis() - start));
+ }
this.consumerIdsChangeListener.handle(ConsumerGroupEvent.REGISTER, group, subList);
@@ -130,7 +148,7 @@ public class ConsumerManager {
if (consumerGroupInfo.getChannelInfoTable().isEmpty()) {
ConsumerGroupInfo remove = this.consumerTable.remove(group);
if (remove != null) {
- log.info("unregister consumer ok, no any connection, and remove consumer group, {}", group);
+ LOGGER.info("unregister consumer ok, no any connection, and remove consumer group, {}", group);
this.consumerIdsChangeListener.handle(ConsumerGroupEvent.UNREGISTER, group);
}
@@ -156,7 +174,7 @@ public class ConsumerManager {
ClientChannelInfo clientChannelInfo = nextChannel.getValue();
long diff = System.currentTimeMillis() - clientChannelInfo.getLastUpdateTimestamp();
if (diff > CHANNEL_EXPIRED_TIMEOUT) {
- log.warn(
+ LOGGER.warn(
"SCAN: remove expired channel from ConsumerManager consumerTable. channel={}, consumerGroup={}",
RemotingHelper.parseChannelRemoteAddr(clientChannelInfo.getChannel()), group);
RemotingUtil.closeChannel(clientChannelInfo.getChannel());
@@ -165,7 +183,7 @@ public class ConsumerManager {
}
if (channelInfoTable.isEmpty()) {
- log.warn(
+ LOGGER.warn(
"SCAN: remove expired channel from ConsumerManager consumerTable, all clear, consumerGroup={}",
group);
it.remove();
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/DefaultConsumerIdsChangeListener.java b/broker/src/main/java/org/apache/rocketmq/broker/client/DefaultConsumerIdsChangeListener.java
index d716a33..8e6e667 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/DefaultConsumerIdsChangeListener.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/DefaultConsumerIdsChangeListener.java
@@ -17,18 +17,46 @@
package org.apache.rocketmq.broker.client;
import io.netty.channel.Channel;
-
import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.common.AbstractBrokerRunnable;
+import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData;
+import org.apache.rocketmq.common.utils.ThreadUtils;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.logging.InternalLoggerFactory;
public class DefaultConsumerIdsChangeListener implements ConsumerIdsChangeListener {
+ private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private final BrokerController brokerController;
+ private final int cacheSize = 8096;
+
+ private final ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1,
+ ThreadUtils.newGenericThreadFactory("DefaultConsumerIdsChangeListener", true));
+
+ private ConcurrentHashMap<String,List<Channel>> consumerChannelMap = new ConcurrentHashMap<>(cacheSize);
public DefaultConsumerIdsChangeListener(BrokerController brokerController) {
this.brokerController = brokerController;
+
+ scheduledExecutorService.scheduleAtFixedRate(new AbstractBrokerRunnable(brokerController.getBrokerConfig()) {
+ @Override
+ public void run2() {
+ try {
+ notifyConsumerChange();
+ } catch (Exception e) {
+ log.error(
+ "DefaultConsumerIdsChangeListen#notifyConsumerChange: unexpected error occurs", e);
+ }
+ }
+ }, 30, 15, TimeUnit.SECONDS);
}
@Override
@@ -43,8 +71,12 @@ public class DefaultConsumerIdsChangeListener implements ConsumerIdsChangeListen
}
List<Channel> channels = (List<Channel>) args[0];
if (channels != null && brokerController.getBrokerConfig().isNotifyConsumerIdsChangedEnable()) {
- for (Channel chl : channels) {
- this.brokerController.getBroker2Client().notifyConsumerIdsChanged(chl, group);
+ if (this.brokerController.getBrokerConfig().isRealTimeNotifyConsumerChange()) {
+ for (Channel chl : channels) {
+ this.brokerController.getBroker2Client().notifyConsumerIdsChanged(chl, group);
+ }
+ } else {
+ consumerChannelMap.put(group, channels);
}
}
break;
@@ -62,4 +94,34 @@ public class DefaultConsumerIdsChangeListener implements ConsumerIdsChangeListen
throw new RuntimeException("Unknown event " + event);
}
}
+
+ private void notifyConsumerChange() {
+
+ if (consumerChannelMap.isEmpty()) {
+ return;
+ }
+
+ ConcurrentHashMap<String, List<Channel>> processMap = new ConcurrentHashMap<>(consumerChannelMap);
+ consumerChannelMap = new ConcurrentHashMap<>(cacheSize);
+
+ for (Map.Entry<String, List<Channel>> entry : processMap.entrySet()) {
+ String consumerId = entry.getKey();
+ List<Channel> channelList = entry.getValue();
+ try {
+ if (channelList != null && brokerController.getBrokerConfig().isNotifyConsumerIdsChangedEnable()) {
+ for (Channel chl : channelList) {
+ this.brokerController.getBroker2Client().notifyConsumerIdsChanged(chl, consumerId);
+ }
+ }
+ } catch (Exception e) {
+ log.error("Failed to notify consumer when some consumers changed, consumerId to notify: {}",
+ consumerId, e);
+ }
+ }
+ }
+
+ @Override
+ public void shutdown() {
+ this.scheduledExecutorService.shutdown();
+ }
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java b/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
index 4bd00ef..11b9088 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
@@ -29,6 +29,7 @@ import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.common.RemotingUtil;
+import org.apache.rocketmq.store.stats.BrokerStatsManager;
public class ProducerManager {
private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
@@ -37,9 +38,24 @@ public class ProducerManager {
private final ConcurrentHashMap<String /* group name */, ConcurrentHashMap<Channel, ClientChannelInfo>> groupChannelTable =
new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Channel> clientChannelTable = new ConcurrentHashMap<>();
+ protected final BrokerStatsManager brokerStatsManager;
private PositiveAtomicCounter positiveAtomicCounter = new PositiveAtomicCounter();
public ProducerManager() {
+ this.brokerStatsManager = null;
+ }
+
+ public ProducerManager(final BrokerStatsManager brokerStatsManager) {
+ this.brokerStatsManager = brokerStatsManager;
+ }
+
+ public int groupSize() {
+ return this.groupChannelTable.size();
+ }
+
+ public boolean groupOnline(String group) {
+ Map<Channel, ClientChannelInfo> channels = this.groupChannelTable.get(group);
+ return channels != null && !channels.isEmpty();
}
public ConcurrentHashMap<String, ConcurrentHashMap<Channel, ClientChannelInfo>> getGroupChannelTable() {
@@ -63,7 +79,7 @@ public class ProducerManager {
it.remove();
clientChannelTable.remove(info.getClientId());
log.warn(
- "SCAN: remove expired channel[{}] from ProducerManager groupChannelTable, producer group name: {}",
+ "ProducerManager#scanNotActiveChannel: remove expired channel[{}] from ProducerManager groupChannelTable, producer group name: {}",
RemotingHelper.parseChannelRemoteAddr(info.getChannel()), group);
RemotingUtil.closeChannel(info.getChannel());
}
@@ -71,7 +87,8 @@ public class ProducerManager {
}
}
- public synchronized void doChannelCloseEvent(final String remoteAddr, final Channel channel) {
+ public synchronized boolean doChannelCloseEvent(final String remoteAddr, final Channel channel) {
+ boolean removed = false;
if (channel != null) {
for (final Map.Entry<String, ConcurrentHashMap<Channel, ClientChannelInfo>> entry : this.groupChannelTable
.entrySet()) {
@@ -82,6 +99,7 @@ public class ProducerManager {
clientChannelInfoTable.remove(channel);
if (clientChannelInfo != null) {
clientChannelTable.remove(clientChannelInfo.getClientId());
+ removed = true;
log.info(
"NETTY EVENT: remove channel[{}][{}] from ProducerManager groupChannelTable, producer group: {}",
clientChannelInfo.toString(), remoteAddr, group);
@@ -89,6 +107,7 @@ public class ProducerManager {
}
}
+ return removed;
}
public synchronized void registerProducer(final String group, final ClientChannelInfo clientChannelInfo) {
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/net/Broker2Client.java b/broker/src/main/java/org/apache/rocketmq/broker/client/net/Broker2Client.java
index 4d28cd8..b78129c 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/net/Broker2Client.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/net/Broker2Client.java
@@ -76,7 +76,7 @@ public class Broker2Client {
}
public RemotingCommand callClient(final Channel channel,
- final RemotingCommand request
+ final RemotingCommand request
) throws RemotingSendRequestException, RemotingTimeoutException, InterruptedException {
return this.brokerController.getRemotingServer().invokeSync(channel, request, 10000);
}
@@ -101,12 +101,13 @@ public class Broker2Client {
}
}
+
public RemotingCommand resetOffset(String topic, String group, long timeStamp, boolean isForce) {
return resetOffset(topic, group, timeStamp, isForce, false);
}
public RemotingCommand resetOffset(String topic, String group, long timeStamp, boolean isForce,
- boolean isC) {
+ boolean isC) {
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(topic);
@@ -237,8 +238,7 @@ public class Broker2Client {
RemotingCommand.createRequestCommand(RequestCode.GET_CONSUMER_STATUS_FROM_CLIENT,
requestHeader);
- Map<String, Map<MessageQueue, Long>> consumerStatusTable =
- new HashMap<String, Map<MessageQueue, Long>>();
+ Map<String, Map<MessageQueue, Long>> consumerStatusTable = new HashMap<String, Map<MessageQueue, Long>>();
ConcurrentMap<Channel, ClientChannelInfo> channelInfoTable =
this.brokerController.getConsumerManager().getConsumerGroupInfo(group).getChannelInfoTable();
if (null == channelInfoTable || channelInfoTable.isEmpty()) {
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/rebalance/RebalanceLockManager.java b/broker/src/main/java/org/apache/rocketmq/broker/client/rebalance/RebalanceLockManager.java
index 9056998..a0abd70 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/rebalance/RebalanceLockManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/rebalance/RebalanceLockManager.java
@@ -36,6 +36,19 @@ public class RebalanceLockManager {
private final ConcurrentMap<String/* group */, ConcurrentHashMap<MessageQueue, LockEntry>> mqLockTable =
new ConcurrentHashMap<String, ConcurrentHashMap<MessageQueue, LockEntry>>(1024);
+ public boolean isLockAllExpired(final String group) {
+ final ConcurrentHashMap<MessageQueue, LockEntry> lockEntryMap = mqLockTable.get(group);
+ if (null == lockEntryMap) {
+ return true;
+ }
+ for (LockEntry entry : lockEntryMap.values()) {
+ if (!entry.isExpired()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
public boolean tryLock(final String group, final MessageQueue mq, final String clientId) {
if (!this.isLocked(group, mq, clientId)) {
@@ -53,10 +66,9 @@ public class RebalanceLockManager {
lockEntry = new LockEntry();
lockEntry.setClientId(clientId);
groupValue.put(mq, lockEntry);
- log.info("tryLock, message queue not locked, I got it. Group: {} NewClientId: {} {}",
- group,
- clientId,
- mq);
+ log.info(
+ "RebalanceLockManager#tryLock: lock a message queue which has not been locked yet, "
+ + "group={}, clientId={}, mq={}", group, clientId, mq);
}
if (lockEntry.isLocked(clientId)) {
@@ -70,26 +82,21 @@ public class RebalanceLockManager {
lockEntry.setClientId(clientId);
lockEntry.setLastUpdateTimestamp(System.currentTimeMillis());
log.warn(
- "tryLock, message queue lock expired, I got it. Group: {} OldClientId: {} NewClientId: {} {}",
- group,
- oldClientId,
- clientId,
- mq);
+ "RebalanceLockManager#tryLock: try to lock a expired message queue, group={}, mq={}, old "
+ + "client id={}, new client id={}", group, mq, oldClientId, clientId);
return true;
}
log.warn(
- "tryLock, message queue locked by other client. Group: {} OtherClientId: {} NewClientId: {} {}",
- group,
- oldClientId,
- clientId,
- mq);
+ "RebalanceLockManager#tryLock: message queue has been locked by other client, group={}, "
+ + "mq={}, locked client id={}, current client id={}", group, mq, oldClientId, clientId);
return false;
} finally {
this.lock.unlock();
}
} catch (InterruptedException e) {
- log.error("putMessage exception", e);
+ log.error("RebalanceLockManager#tryLock: unexpected error, group={}, mq={}, clientId={}", group, mq,
+ clientId, e);
}
} else {
@@ -145,10 +152,8 @@ public class RebalanceLockManager {
lockEntry.setClientId(clientId);
groupValue.put(mq, lockEntry);
log.info(
- "tryLockBatch, message queue not locked, I got it. Group: {} NewClientId: {} {}",
- group,
- clientId,
- mq);
+ "RebalanceLockManager#tryLockBatch: lock a message which has not been locked yet, "
+ + "group={}, clientId={}, mq={}", group, clientId, mq);
}
if (lockEntry.isLocked(clientId)) {
@@ -163,27 +168,23 @@ public class RebalanceLockManager {
lockEntry.setClientId(clientId);
lockEntry.setLastUpdateTimestamp(System.currentTimeMillis());
log.warn(
- "tryLockBatch, message queue lock expired, I got it. Group: {} OldClientId: {} NewClientId: {} {}",
- group,
- oldClientId,
- clientId,
- mq);
+ "RebalanceLockManager#tryLockBatch: try to lock a expired message queue, group={}, "
+ + "mq={}, old client id={}, new client id={}", group, mq, oldClientId, clientId);
lockedMqs.add(mq);
continue;
}
log.warn(
- "tryLockBatch, message queue locked by other client. Group: {} OtherClientId: {} NewClientId: {} {}",
- group,
- oldClientId,
- clientId,
- mq);
+ "RebalanceLockManager#tryLockBatch: message queue has been locked by other client, "
+ + "group={}, mq={}, locked client id={}, current client id={}", group, mq, oldClientId,
+ clientId);
}
} finally {
this.lock.unlock();
}
} catch (InterruptedException e) {
- log.error("putMessage exception", e);
+ log.error("RebalanceLockManager#tryBatch: unexpected error, group={}, mqs={}, clientId={}", group, mqs,
+ clientId, e);
}
}
@@ -201,34 +202,29 @@ public class RebalanceLockManager {
if (null != lockEntry) {
if (lockEntry.getClientId().equals(clientId)) {
groupValue.remove(mq);
- log.info("unlockBatch, Group: {} {} {}",
- group,
- mq,
- clientId);
+ log.info("RebalanceLockManager#unlockBatch: unlock mq, group={}, clientId={}, mqs={}",
+ group, clientId, mq);
} else {
- log.warn("unlockBatch, but mq locked by other client: {}, Group: {} {} {}",
- lockEntry.getClientId(),
- group,
- mq,
- clientId);
+ log.warn(
+ "RebalanceLockManager#unlockBatch: mq locked by other client, group={}, locked "
+ + "clientId={}, current clientId={}, mqs={}", group, lockEntry.getClientId(),
+ clientId, mq);
}
} else {
- log.warn("unlockBatch, but mq not locked, Group: {} {} {}",
- group,
- mq,
- clientId);
+ log.warn("RebalanceLockManager#unlockBatch: mq not locked, group={}, clientId={}, mq={}",
+ group, clientId, mq);
}
}
} else {
- log.warn("unlockBatch, group not exist, Group: {} {}",
- group,
- clientId);
+ log.warn("RebalanceLockManager#unlockBatch: group not exist, group={}, clientId={}, mqs={}", group,
+ clientId, mqs);
}
} finally {
this.lock.unlock();
}
} catch (InterruptedException e) {
- log.error("putMessage exception", e);
+ log.error("RebalanceLockManager#unlockBatch: unexpected error, group={}, mqs={}, clientId={}", group, mqs,
+ clientId);
}
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/dledger/DLedgerRoleChangeHandler.java b/broker/src/main/java/org/apache/rocketmq/broker/dledger/DLedgerRoleChangeHandler.java
index 09bf10c..3f5f024 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/dledger/DLedgerRoleChangeHandler.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/dledger/DLedgerRoleChangeHandler.java
@@ -22,6 +22,8 @@ import io.openmessaging.storage.dledger.MemberState;
import io.openmessaging.storage.dledger.utils.DLedgerUtils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.common.ThreadFactoryImpl;
import org.apache.rocketmq.common.constant.LoggerName;
@@ -33,12 +35,14 @@ import org.apache.rocketmq.store.dledger.DLedgerCommitLog;
public class DLedgerRoleChangeHandler implements DLedgerLeaderElector.RoleChangeHandler {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ private static final InternalLogger LOGGER = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactoryImpl("DLegerRoleChangeHandler_"));
private BrokerController brokerController;
private DefaultMessageStore messageStore;
private DLedgerCommitLog dLedgerCommitLog;
private DLedgerServer dLegerServer;
+ private Future<?> slaveSyncFuture;
+
public DLedgerRoleChangeHandler(BrokerController brokerController, DefaultMessageStore messageStore) {
this.brokerController = brokerController;
this.messageStore = messageStore;
@@ -52,15 +56,15 @@ public class DLedgerRoleChangeHandler implements DLedgerLeaderElector.RoleChange
long start = System.currentTimeMillis();
try {
boolean succ = true;
- log.info("Begin handling broker role change term={} role={} currStoreRole={}", term, role, messageStore.getMessageStoreConfig().getBrokerRole());
+ LOGGER.info("Begin handling broker role change term={} role={} currStoreRole={}", term, role, messageStore.getMessageStoreConfig().getBrokerRole());
switch (role) {
case CANDIDATE:
if (messageStore.getMessageStoreConfig().getBrokerRole() != BrokerRole.SLAVE) {
- brokerController.changeToSlave(dLedgerCommitLog.getId());
+ changeToSlave(dLedgerCommitLog.getId());
}
break;
case FOLLOWER:
- brokerController.changeToSlave(dLedgerCommitLog.getId());
+ changeToSlave(dLedgerCommitLog.getId());
break;
case LEADER:
while (true) {
@@ -79,21 +83,89 @@ public class DLedgerRoleChangeHandler implements DLedgerLeaderElector.RoleChange
}
if (succ) {
messageStore.recoverTopicQueueTable();
- brokerController.changeToMaster(BrokerRole.SYNC_MASTER);
+ changeToMaster(BrokerRole.SYNC_MASTER);
}
break;
default:
break;
}
- log.info("Finish handling broker role change succ={} term={} role={} currStoreRole={} cost={}", succ, term, role, messageStore.getMessageStoreConfig().getBrokerRole(), DLedgerUtils.elapsed(start));
+ LOGGER.info("Finish handling broker role change succ={} term={} role={} currStoreRole={} cost={}", succ, term, role, messageStore.getMessageStoreConfig().getBrokerRole(), DLedgerUtils.elapsed(start));
} catch (Throwable t) {
- log.info("[MONITOR]Failed handling broker role change term={} role={} currStoreRole={} cost={}", term, role, messageStore.getMessageStoreConfig().getBrokerRole(), DLedgerUtils.elapsed(start), t);
+ LOGGER.info("[MONITOR]Failed handling broker role change term={} role={} currStoreRole={} cost={}", term, role, messageStore.getMessageStoreConfig().getBrokerRole(), DLedgerUtils.elapsed(start), t);
}
}
};
executorService.submit(runnable);
}
+ private void handleSlaveSynchronize(BrokerRole role) {
+ if (role == BrokerRole.SLAVE) {
+ if (null != slaveSyncFuture) {
+ slaveSyncFuture.cancel(false);
+ }
+ this.brokerController.getSlaveSynchronize().setMasterAddr(null);
+ slaveSyncFuture = this.brokerController.getScheduledExecutorService().scheduleAtFixedRate(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ brokerController.getSlaveSynchronize().syncAll();
+ } catch (Throwable e) {
+ LOGGER.error("ScheduledTask SlaveSynchronize syncAll error.", e);
+ }
+ }
+ }, 1000 * 3, 1000 * 10, TimeUnit.MILLISECONDS);
+ } else {
+ //handle the slave synchronise
+ if (null != slaveSyncFuture) {
+ slaveSyncFuture.cancel(false);
+ }
+ this.brokerController.getSlaveSynchronize().setMasterAddr(null);
+ }
+ }
+
+ public void changeToSlave(int brokerId) {
+ LOGGER.info("Begin to change to slave brokerName={} brokerId={}", this.brokerController.getBrokerConfig().getBrokerName(), brokerId);
+
+ //change the role
+ this.brokerController.getBrokerConfig().setBrokerId(brokerId == 0 ? 1 : brokerId); //TO DO check
+ this.brokerController.getMessageStoreConfig().setBrokerRole(BrokerRole.SLAVE);
+
+ this.brokerController.changeSpecialServiceStatus(false);
+
+ //handle the slave synchronise
+ handleSlaveSynchronize(BrokerRole.SLAVE);
+
+ try {
+ this.brokerController.registerBrokerAll(true, true, this.brokerController.getBrokerConfig().isForceRegister());
+ } catch (Throwable ignored) {
+
+ }
+ LOGGER.info("Finish to change to slave brokerName={} brokerId={}", this.brokerController.getBrokerConfig().getBrokerName(), brokerId);
+ }
+
+ public void changeToMaster(BrokerRole role) {
+ if (role == BrokerRole.SLAVE) {
+ return;
+ }
+ LOGGER.info("Begin to change to master brokerName={}", this.brokerController.getBrokerConfig().getBrokerName());
+
+ //handle the slave synchronise
+ handleSlaveSynchronize(role);
+
+ this.brokerController.changeSpecialServiceStatus(true);
+
+ //if the operations above are totally successful, we change to master
+ this.brokerController.getBrokerConfig().setBrokerId(0); //TO DO check
+ this.brokerController.getMessageStoreConfig().setBrokerRole(role);
+
+ try {
+ this.brokerController.registerBrokerAll(true, true, this.brokerController.getBrokerConfig().isForceRegister());
+ } catch (Throwable ignored) {
+
+ }
+ LOGGER.info("Finish to change to master brokerName={}", this.brokerController.getBrokerConfig().getBrokerName());
+ }
+
@Override public void startup() {
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/failover/EscapeBridge.java b/broker/src/main/java/org/apache/rocketmq/broker/failover/EscapeBridge.java
new file mode 100644
index 0000000..c7f10a2
--- /dev/null
+++ b/broker/src/main/java/org/apache/rocketmq/broker/failover/EscapeBridge.java
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.rocketmq.broker.failover;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
+import org.apache.rocketmq.client.consumer.PullResult;
+import org.apache.rocketmq.client.consumer.PullStatus;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.client.producer.MessageQueueSelector;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.common.constant.LoggerName;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageDecoder;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.logging.InternalLoggerFactory;
+import org.apache.rocketmq.store.GetMessageResult;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
+import org.apache.rocketmq.store.MessageStore;
+import org.apache.rocketmq.store.PutMessageResult;
+import org.apache.rocketmq.store.PutMessageStatus;
+
+public class EscapeBridge {
+ protected static final InternalLogger LOG = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ private final String innerProducerGroupName;
+ private final String innerConsumerGroupName;
+
+ private final BrokerController brokerController;
+
+ private DefaultMQProducer innerProducer;
+ private DefaultMQPullConsumer innerConsumer;
+
+ public EscapeBridge(BrokerController brokerController) {
+ this.brokerController = brokerController;
+ this.innerProducerGroupName = "InnerProducerGroup_" + brokerController.getBrokerConfig().getBrokerName() + "_" + brokerController.getBrokerConfig().getBrokerId();
+ this.innerConsumerGroupName = "InnerConsumerGroup_" + brokerController.getBrokerConfig().getBrokerName() + "_" + brokerController.getBrokerConfig().getBrokerId();
+ }
+
+ public void start() throws Exception {
+ if (brokerController.getBrokerConfig().isEnableSlaveActingMaster() && brokerController.getBrokerConfig().isEnableRemoteEscape()) {
+ String nameserver = this.brokerController.getNameServerList();
+ if (nameserver != null && !nameserver.isEmpty()) {
+ startInnerProducer(nameserver);
+ startInnerConsumer(nameserver);
+ LOG.info("start inner producer and consumer success.");
+ } else {
+ throw new RuntimeException("nameserver address is null or empty");
+ }
+ }
+ }
+
+ public void shutdown() {
+ if (this.innerProducer != null) {
+ this.innerProducer.shutdown();
+ }
+
+ if (this.innerConsumer != null) {
+ this.innerConsumer.shutdown();
+ }
+ }
+
+ private void startInnerProducer(String nameServer) throws MQClientException {
+ try {
+ innerProducer = new DefaultMQProducer(innerProducerGroupName);
+ innerProducer.setNamesrvAddr(nameServer);
+ innerProducer.start();
+ } catch (MQClientException e) {
+ LOG.error("start inner producer failed, nameserver address: {}", nameServer, e);
+ throw e;
+ }
+ }
+
+ private void startInnerConsumer(String nameServer) throws MQClientException {
+ try {
+ innerConsumer = new DefaultMQPullConsumer(innerConsumerGroupName);
+ innerConsumer.setNamesrvAddr(nameServer);
+ innerConsumer.start();
+ } catch (MQClientException e) {
+ LOG.error("start inner consumer failed, nameserver address: {}", nameServer, e);
+ throw e;
+ }
+ }
+
+ public PutMessageResult putMessage(MessageExtBrokerInner messageExt) {
+ BrokerController masterBroker = this.brokerController.peekMasterBroker();
+ if (masterBroker != null) {
+ return masterBroker.getMessageStore().putMessage(messageExt);
+ } else if (this.brokerController.getBrokerConfig().isEnableSlaveActingMaster()
+ && this.brokerController.getBrokerConfig().isEnableRemoteEscape()
+ && innerProducer != null) {
+ // Remote Acting lead to born timestamp, msgId changed, it need to polish.
+ try {
+ messageExt.setWaitStoreMsgOK(false);
+ SendResult sendResult = innerProducer.send(messageExt);
+ return transformSendResult2PutResult(sendResult);
+ } catch (Exception e) {
+ LOG.error("sendMessageInFailover to remote failed", e);
+ return new PutMessageResult(PutMessageStatus.PUT_TO_REMOTE_BROKER_FAIL, null, true);
+ }
+ } else {
+ LOG.warn("Put message failed, enableSlaveActingMaster={}, enableRemoteEscape={}.",
+ this.brokerController.getBrokerConfig().isEnableSlaveActingMaster(), this.brokerController.getBrokerConfig().isEnableRemoteEscape());
+ return new PutMessageResult(PutMessageStatus.SERVICE_NOT_AVAILABLE, null);
+ }
+ }
+
+ public CompletableFuture<PutMessageResult> asyncPutMessage(MessageExtBrokerInner messageExt) {
+ BrokerController masterBroker = this.brokerController.peekMasterBroker();
+ CompletableFuture<PutMessageResult> completableFuture = new CompletableFuture<>();
+ if (masterBroker != null) {
+ return masterBroker.getMessageStore().asyncPutMessage(messageExt);
+ } else if (this.brokerController.getBrokerConfig().isEnableSlaveActingMaster()
+ && this.brokerController.getBrokerConfig().isEnableRemoteEscape()
+ && innerProducer != null) {
+ // Remote Acting lead to born timestamp, msgId changed, it need to polish.
+ try {
+ messageExt.setWaitStoreMsgOK(false);
+ innerProducer.send(messageExt, new SendCallback() {
+ @Override public void onSuccess(SendResult sendResult) {
+ completableFuture.complete(transformSendResult2PutResult(sendResult));
+ }
+
+ @Override public void onException(Throwable e) {
+ completableFuture.complete(new PutMessageResult(PutMessageStatus.PUT_TO_REMOTE_BROKER_FAIL, null, true));
+ }
+ });
+ return completableFuture;
+ } catch (Exception e) {
+ LOG.error("sendMessageInFailover to remote failed", e);
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.PUT_TO_REMOTE_BROKER_FAIL, null, true));
+ }
+ } else {
+ LOG.warn("Put message failed, enableSlaveActingMaster={}, enableRemoteEscape={}.",
+ this.brokerController.getBrokerConfig().isEnableSlaveActingMaster(), this.brokerController.getBrokerConfig().isEnableRemoteEscape());
+ return CompletableFuture.completedFuture(new PutMessageResult(PutMessageStatus.SERVICE_NOT_AVAILABLE, null));
+ }
+ }
+
+ public PutMessageResult putMessageToSpecificQueue(MessageExtBrokerInner messageExt) {
+ BrokerController masterBroker = this.brokerController.peekMasterBroker();
+ if (masterBroker != null) {
+ return masterBroker.getMessageStore().putMessage(messageExt);
+ } else if (this.brokerController.getBrokerConfig().isEnableSlaveActingMaster()
+ && this.brokerController.getBrokerConfig().isEnableRemoteEscape()
+ && this.innerProducer != null) {
+ try {
+ messageExt.setWaitStoreMsgOK(false);
+ // Remote Acting lead to born timestamp, msgId changed, it need to polish.
+ SendResult sendResult = innerProducer.send(messageExt, new MessageQueueSelector() {
+ @Override
+ public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
+ String id = (String) arg;
+ int index = Math.abs(id.hashCode()) % mqs.size();
+ return mqs.get(index);
+ }
+ }, messageExt.getTopic() + messageExt.getStoreHost());
+ return transformSendResult2PutResult(sendResult);
+ } catch (Exception e) {
+ LOG.error("sendMessageInFailover to remote failed", e);
+ return new PutMessageResult(PutMessageStatus.PUT_TO_REMOTE_BROKER_FAIL, null, true);
+ }
+ } else {
+ LOG.warn("Put message to specific queue failed, enableSlaveActingMaster={}, enableRemoteEscape={}.",
+ this.brokerController.getBrokerConfig().isEnableSlaveActingMaster(), this.brokerController.getBrokerConfig().isEnableRemoteEscape());
+ return new PutMessageResult(PutMessageStatus.SERVICE_NOT_AVAILABLE, null);
+ }
+ }
+
+ private PutMessageResult transformSendResult2PutResult(SendResult sendResult) {
+ if (sendResult == null) {
+ return new PutMessageResult(PutMessageStatus.PUT_TO_REMOTE_BROKER_FAIL, null, true);
+ }
+ switch (sendResult.getSendStatus()) {
+ case SEND_OK:
+ return new PutMessageResult(PutMessageStatus.PUT_OK, null, true);
+ case SLAVE_NOT_AVAILABLE:
+ return new PutMessageResult(PutMessageStatus.SLAVE_NOT_AVAILABLE, null, true);
+ case FLUSH_DISK_TIMEOUT:
+ return new PutMessageResult(PutMessageStatus.FLUSH_DISK_TIMEOUT, null, true);
+ case FLUSH_SLAVE_TIMEOUT:
+ return new PutMessageResult(PutMessageStatus.FLUSH_SLAVE_TIMEOUT, null, true);
+ default:
+ return new PutMessageResult(PutMessageStatus.PUT_TO_REMOTE_BROKER_FAIL, null, true);
+ }
+ }
+
+ public MessageExt getMessage(String topic, long offset, int queueId, String brokerName) {
+ MessageStore messageStore = brokerController.getMessageStoreByBrokerName(brokerName);
+ if (messageStore != null) {
+ final GetMessageResult getMessageTmpResult = messageStore.getMessage(innerConsumerGroupName, topic, queueId, offset, 1, null);
+ List<MessageExt> list = decodeMsgList(getMessageTmpResult);
+ if (list == null || list.isEmpty()) {
+ LOG.warn("Can not get msg , topic {}, offset {}, queueId {}, result is {}", topic, offset, queueId, getMessageTmpResult);
+ return null;
+ } else {
+ return list.get(0);
+ }
+ } else if (innerConsumer != null) {
+ return getMessageFromRemote(topic, offset, queueId, brokerName);
+ } else {
+ return null;
+ }
+ }
+
+ protected List<MessageExt> decodeMsgList(GetMessageResult getMessageResult) {
+ List<MessageExt> foundList = new ArrayList<>();
+ try {
+ List<ByteBuffer> messageBufferList = getMessageResult.getMessageBufferList();
+ if (messageBufferList != null) {
+ for (int i = 0; i < messageBufferList.size(); i++) {
+ ByteBuffer bb = messageBufferList.get(i);
+ if (bb == null) {
+ LOG.error("bb is null {}", getMessageResult);
+ continue;
+ }
+ MessageExt msgExt = MessageDecoder.decode(bb);
+ if (msgExt == null) {
+ LOG.error("decode msgExt is null {}", getMessageResult);
+ continue;
+ }
+ // use CQ offset, not offset in Message
+ msgExt.setQueueOffset(getMessageResult.getMessageQueueOffset().get(i));
+ foundList.add(msgExt);
+ }
+ }
+ } finally {
+ getMessageResult.release();
+ }
+
+ return foundList;
+ }
+
+ protected MessageExt getMessageFromRemote(String topic, long offset, int queueId, String brokerName) {
+ try {
+ PullResult pullResult = innerConsumer.pull(new MessageQueue(topic, brokerName, queueId), "*", offset, 1);
+ if (pullResult.getPullStatus().equals(PullStatus.FOUND)) {
+ return pullResult.getMsgFoundList().get(0);
+ }
+ } catch (Exception e) {
+ LOG.error("Get message from remote failed.", e);
+ }
+
+ return null;
+ }
+}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/filtersrv/FilterServerManager.java b/broker/src/main/java/org/apache/rocketmq/broker/filtersrv/FilterServerManager.java
index c1a860a..fa01d54 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/filtersrv/FilterServerManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/filtersrv/FilterServerManager.java
@@ -29,6 +29,7 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.broker.BrokerStartup;
+import org.apache.rocketmq.common.AbstractBrokerRunnable;
import org.apache.rocketmq.common.ThreadFactoryImpl;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.logging.InternalLogger;
@@ -52,9 +53,8 @@ public class FilterServerManager {
public void start() {
- this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
+ this.scheduledExecutorService.scheduleAtFixedRate(new AbstractBrokerRunnable(brokerController.getBrokerConfig()) {
+ @Override public void run2() {
try {
FilterServerManager.this.createFilterServer();
} catch (Exception e) {
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/latency/BrokerFastFailure.java b/broker/src/main/java/org/apache/rocketmq/broker/latency/BrokerFastFailure.java
index d176b86..b3184e2 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/latency/BrokerFastFailure.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/latency/BrokerFastFailure.java
@@ -17,25 +17,35 @@
package org.apache.rocketmq.broker.latency;
import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.common.AbstractBrokerRunnable;
import org.apache.rocketmq.common.ThreadFactoryImpl;
+import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.netty.RequestTask;
import org.apache.rocketmq.remoting.protocol.RemotingSysResponseCode;
+/**
+ * BrokerFastFailure will cover {@link BrokerController#getSendThreadPoolQueue()} and {@link
+ * BrokerController#getPullThreadPoolQueue()}
+ */
public class BrokerFastFailure {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
- private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl(
- "BrokerFastFailureScheduledThread"));
+ private static final InternalLogger LOGGER = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ private final ScheduledExecutorService scheduledExecutorService;
private final BrokerController brokerController;
+ private volatile long jstackTime = System.currentTimeMillis();
+
public BrokerFastFailure(final BrokerController brokerController) {
this.brokerController = brokerController;
+ this.scheduledExecutorService = new ScheduledThreadPoolExecutor(1,
+ new ThreadFactoryImpl("BrokerFastFailureScheduledThread", true,
+ brokerController == null ? null : brokerController.getBrokerConfig()));
}
public static RequestTask castRunnable(final Runnable runnable) {
@@ -45,16 +55,15 @@ public class BrokerFastFailure {
return (RequestTask) object.getRunnable();
}
} catch (Throwable e) {
- log.error(String.format("castRunnable exception, %s", runnable.getClass().getName()), e);
+ LOGGER.error(String.format("castRunnable exception, %s", runnable.getClass().getName()), e);
}
return null;
}
public void start() {
- this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
+ this.scheduledExecutorService.scheduleAtFixedRate(new AbstractBrokerRunnable(this.brokerController.getBrokerConfig()) {
+ @Override public void run2() {
if (brokerController.getBrokerConfig().isBrokerFastFailureEnable()) {
cleanExpiredRequest();
}
@@ -63,6 +72,7 @@ public class BrokerFastFailure {
}
private void cleanExpiredRequest() {
+
while (this.brokerController.getMessageStore().isOSPageCacheBusy()) {
try {
if (!this.brokerController.getSendThreadPoolQueue().isEmpty()) {
@@ -72,7 +82,13 @@ public class BrokerFastFailure {
}
final RequestTask rt = castRunnable(runnable);
- rt.returnResponse(RemotingSysResponseCode.SYSTEM_BUSY, String.format("[PCBUSY_CLEAN_QUEUE]broker busy, start flow control for a while, period in queue: %sms, size of queue: %d", System.currentTimeMillis() - rt.getCreateTimestamp(), this.brokerController.getSendThreadPoolQueue().size()));
+ if (rt != null) {
+ rt.returnResponse(RemotingSysResponseCode.SYSTEM_BUSY, String.format(
+ "[PCBUSY_CLEAN_QUEUE]broker busy, start flow control for a while, period in queue: %sms, "
+ + "size of queue: %d",
+ System.currentTimeMillis() - rt.getCreateTimestamp(),
+ this.brokerController.getSendThreadPoolQueue().size()));
+ }
} else {
break;
}
@@ -86,11 +102,17 @@ public class BrokerFastFailure {
cleanExpiredRequestInQueue(this.brokerController.getPullThreadPoolQueue(),
this.brokerController.getBrokerConfig().getWaitTimeMillsInPullQueue());
+ cleanExpiredRequestInQueue(this.brokerController.getLitePullThreadPoolQueue(),
+ this.brokerController.getBrokerConfig().getWaitTimeMillsInLitePullQueue());
+
cleanExpiredRequestInQueue(this.brokerController.getHeartbeatThreadPoolQueue(),
this.brokerController.getBrokerConfig().getWaitTimeMillsInHeartbeatQueue());
cleanExpiredRequestInQueue(this.brokerController.getEndTransactionThreadPoolQueue(), this
.brokerController.getBrokerConfig().getWaitTimeMillsInTransactionQueue());
+
+ cleanExpiredRequestInQueue(this.brokerController.getAckThreadPoolQueue(),
+ brokerController.getBrokerConfig().getWaitTimeMillsInAckQueue());
}
void cleanExpiredRequestInQueue(final BlockingQueue<Runnable> blockingQueue, final long maxWaitTimeMillsInQueue) {
@@ -111,6 +133,10 @@ public class BrokerFastFailure {
if (blockingQueue.remove(runnable)) {
rt.setStopRun(true);
rt.returnResponse(RemotingSysResponseCode.SYSTEM_BUSY, String.format("[TIMEOUT_CLEAN_QUEUE]broker busy, start flow control for a while, period in queue: %sms, size of queue: %d", behind, blockingQueue.size()));
+ if (System.currentTimeMillis() - jstackTime > 15000) {
+ jstackTime = System.currentTimeMillis();
+ LOGGER.warn("broker jstack \n " + UtilAll.jstack());
+ }
}
} else {
break;
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/loadbalance/AssignmentManager.java b/broker/src/main/java/org/apache/rocketmq/broker/loadbalance/AssignmentManager.java
index 877ddd8..fe5d5d0 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/loadbalance/AssignmentManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/loadbalance/AssignmentManager.java
@@ -24,10 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
import org.apache.rocketmq.broker.BrokerController;
-import org.apache.rocketmq.broker.out.BrokerOuterAPI;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.common.MixAll;
@@ -40,25 +37,16 @@ import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
-
public class AssignmentManager {
private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private transient BrokerController brokerController;
- private final static long LOCK_TIMEOUT_MILLIS = 3000;
-
- private final Lock lockNamesrv = new ReentrantLock();
-
- private final BrokerOuterAPI mQClientAPIImpl;
-
private final ConcurrentHashMap<String, Set<MessageQueue>> topicSubscribeInfoTable = new ConcurrentHashMap<String, Set<MessageQueue>>();
- private ScheduledExecutorService scheduledExecutorService = Executors
- .newSingleThreadScheduledExecutor(new ThreadFactoryImpl("LoadBalanceManagerScheduledThread"));
+ private ScheduledExecutorService scheduledExecutorService;
private static final List<String> IGNORE_ROUTE_TOPICS = Lists.newArrayList(
- TopicValidator.SYSTEM_TOPIC_PREFIX,
MixAll.CID_RMQ_SYS_PREFIX,
MixAll.DEFAULT_CONSUMER_GROUP,
MixAll.TOOLS_CONSUMER_GROUP,
@@ -74,9 +62,10 @@ public class AssignmentManager {
public AssignmentManager(BrokerController brokerController) {
this.brokerController = brokerController;
- this.mQClientAPIImpl = brokerController.getBrokerOuterAPI();
ignoreRouteTopics.add(brokerController.getBrokerConfig().getBrokerClusterName());
ignoreRouteTopics.add(brokerController.getBrokerConfig().getBrokerName());
+ scheduledExecutorService = Executors
+ .newSingleThreadScheduledExecutor(new ThreadFactoryImpl("LoadBalanceManagerScheduledThread", brokerController.getBrokerConfig()));
}
public void start() {
@@ -90,9 +79,12 @@ public class AssignmentManager {
log.error("ScheduledTask: failed to pull TopicRouteData from NameServer", e);
}
}
- }, 200, this.brokerController.getBrokerConfig().getLoadBalancePollNameServerInterval(), TimeUnit.MILLISECONDS);
+ }, 1000, this.brokerController.getBrokerConfig().getLoadBalancePollNameServerInterval(), TimeUnit.MILLISECONDS);
}
+ public void shutdown() {
+ this.scheduledExecutorService.shutdown();
+ }
public void updateTopicRouteInfoFromNameServer() {
Set<String> topicList = new HashSet<>(brokerController.getTopicConfigManager().getTopicConfigTable().keySet());
@@ -100,7 +92,7 @@ public class AssignmentManager {
LOOP:
for (String topic : topicList) {
for (String keyword : ignoreRouteTopics) {
- if (topic.contains(keyword)) {
+ if (topic.contains(keyword) || TopicValidator.isSystemTopic(topic)) {
continue LOOP;
}
}
@@ -111,7 +103,7 @@ public class AssignmentManager {
public boolean updateTopicRouteInfoFromNameServer(final String topic) {
try {
- TopicRouteData topicRouteData = this.mQClientAPIImpl.getTopicRouteInfoFromNameServer(topic, 1000 * 3);
+ TopicRouteData topicRouteData = this.brokerController.getBrokerOuterAPI().getTopicRouteInfoFromNameServer(topic, 1000 * 3);
if (topicRouteData != null) {
Set<MessageQueue> newSubscribeInfo = MQClientInstance.topicRouteData2TopicSubscribeInfo(topic, topicRouteData);
Set<MessageQueue> oldSubscribeInfo = topicSubscribeInfoTable.get(topic);
@@ -142,7 +134,6 @@ public class AssignmentManager {
topicSubscribeInfoTable.remove(topic);
}
-
public Set<MessageQueue> getTopicSubscribeInfo(String topic) {
return topicSubscribeInfoTable.get(topic);
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/ManyPullRequest.java b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/ManyPullRequest.java
index 170dae2..08703de 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/ManyPullRequest.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/ManyPullRequest.java
@@ -43,4 +43,8 @@ public class ManyPullRequest {
public ArrayList<PullRequest> getPullRequestList() {
return pullRequestList;
}
+
+ public synchronized boolean isEmpty() {
+ return this.pullRequestList.isEmpty();
+ }
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PopRequest.java b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/NotificationRequest.java
similarity index 56%
copy from broker/src/main/java/org/apache/rocketmq/broker/longpolling/PopRequest.java
copy to broker/src/main/java/org/apache/rocketmq/broker/longpolling/NotificationRequest.java
index e8e4567..fdae881 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PopRequest.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/NotificationRequest.java
@@ -16,22 +16,19 @@
*/
package org.apache.rocketmq.broker.longpolling;
-import io.netty.channel.Channel;
-import java.util.Comparator;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
+
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-public class PopRequest {
- private static final AtomicLong COUNTER = new AtomicLong(Long.MIN_VALUE);
+import io.netty.channel.Channel;
+public class NotificationRequest {
private RemotingCommand remotingCommand;
private Channel channel;
private long expired;
private AtomicBoolean complete = new AtomicBoolean(false);
- private final long op = COUNTER.getAndIncrement();
- public PopRequest(RemotingCommand remotingCommand, Channel channel, long expired) {
+ public NotificationRequest(RemotingCommand remotingCommand, Channel channel, long expired) {
this.channel = channel;
this.remotingCommand = remotingCommand;
this.expired = expired;
@@ -46,42 +43,15 @@ public class PopRequest {
}
public boolean isTimeout() {
- return System.currentTimeMillis() > (expired - 50);
+ return System.currentTimeMillis() > (expired - 3000);
}
public boolean complete() {
return complete.compareAndSet(false, true);
}
- public long getExpired() {
- return expired;
- }
-
@Override
public String toString() {
- final StringBuilder sb = new StringBuilder("PopRequest{");
- sb.append("cmd=").append(remotingCommand);
- sb.append(", channel=").append(channel);
- sb.append(", expired=").append(expired);
- sb.append(", complete=").append(complete);
- sb.append(", op=").append(op);
- sb.append('}');
- return sb.toString();
+ return remotingCommand.toString();
}
-
- public static final Comparator<PopRequest> COMPARATOR = new Comparator<PopRequest>() {
- @Override
- public int compare(PopRequest o1, PopRequest o2) {
- int ret = (int) (o1.getExpired() - o2.getExpired());
-
- if (ret != 0) {
- return ret;
- }
- ret = (int) (o1.op - o2.op);
- if (ret != 0) {
- return ret;
- }
- return -1;
- }
- };
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/NotifyMessageArrivingListener.java b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/NotifyMessageArrivingListener.java
index 7803462..3c099fe 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/NotifyMessageArrivingListener.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/NotifyMessageArrivingListener.java
@@ -17,24 +17,29 @@
package org.apache.rocketmq.broker.longpolling;
-import java.util.Map;
+import org.apache.rocketmq.broker.processor.NotificationProcessor;
import org.apache.rocketmq.broker.processor.PopMessageProcessor;
import org.apache.rocketmq.store.MessageArrivingListener;
+import java.util.Map;
+
public class NotifyMessageArrivingListener implements MessageArrivingListener {
private final PullRequestHoldService pullRequestHoldService;
private final PopMessageProcessor popMessageProcessor;
+ private final NotificationProcessor notificationProcessor;
- public NotifyMessageArrivingListener(final PullRequestHoldService pullRequestHoldService, final PopMessageProcessor popMessageProcessor) {
+ public NotifyMessageArrivingListener(final PullRequestHoldService pullRequestHoldService, final PopMessageProcessor popMessageProcessor, final NotificationProcessor notificationProcessor) {
this.pullRequestHoldService = pullRequestHoldService;
this.popMessageProcessor = popMessageProcessor;
+ this.notificationProcessor = notificationProcessor;
}
@Override
public void arriving(String topic, int queueId, long logicOffset, long tagsCode,
- long msgStoreTime, byte[] filterBitMap, Map<String, String> properties) {
+ long msgStoreTime, byte[] filterBitMap, Map<String, String> properties) {
this.pullRequestHoldService.notifyMessageArriving(topic, queueId, logicOffset, tagsCode,
msgStoreTime, filterBitMap, properties);
this.popMessageProcessor.notifyMessageArriving(topic, queueId);
+ this.notificationProcessor.notifyMessageArriving(topic, queueId);
}
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PopRequest.java b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PopRequest.java
index e8e4567..2eccf77 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PopRequest.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PopRequest.java
@@ -16,12 +16,14 @@
*/
package org.apache.rocketmq.broker.longpolling;
-import io.netty.channel.Channel;
import java.util.Comparator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
+import io.netty.channel.Channel;
+
public class PopRequest {
private static final AtomicLong COUNTER = new AtomicLong(Long.MIN_VALUE);
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PullRequestHoldService.java b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PullRequestHoldService.java
index 85ca9f7..0a05dba 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PullRequestHoldService.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/longpolling/PullRequestHoldService.java
@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.common.ServiceThread;
import org.apache.rocketmq.common.SystemClock;
@@ -78,7 +79,7 @@ public class PullRequestHoldService extends ServiceThread {
this.checkHoldRequest();
long costTime = this.systemClock.now() - beginLockTimestamp;
if (costTime > 5 * 1000) {
- log.info("[NOTIFYME] check hold request cost {} ms.", costTime);
+ log.warn("PullRequestHoldService: check hold pull request cost {}ms", costTime);
}
} catch (Throwable e) {
log.warn(this.getServiceName() + " service has exception. ", e);
@@ -90,6 +91,9 @@ public class PullRequestHoldService extends ServiceThread {
@Override
public String getServiceName() {
+ if (brokerController != null && brokerController.getBrokerConfig().isInBrokerContainer()) {
+ return this.brokerController.getBrokerConfig().getLoggerIdentifier() + PullRequestHoldService.class.getSimpleName();
+ }
return PullRequestHoldService.class.getSimpleName();
}
@@ -103,7 +107,9 @@ public class PullRequestHoldService extends ServiceThread {
try {
this.notifyMessageArriving(topic, queueId, offset);
} catch (Throwable e) {
- log.error("check hold request failed. topic={}, queueId={}", topic, queueId, e);
+ log.error(
+ "PullRequestHoldService: failed to check hold request failed, topic={}, queueId={}", topic,
+ queueId, e);
}
}
}
@@ -141,7 +147,9 @@ public class PullRequestHoldService extends ServiceThread {
this.brokerController.getPullMessageProcessor().executeRequestWhenWakeup(request.getClientChannel(),
request.getRequestCommand());
} catch (Throwable e) {
- log.error("execute request when wakeup failed.", e);
+ log.error(
+ "PullRequestHoldService#notifyMessageArriving: failed to execute request when "
+ + "message matched, topic={}, queueId={}", topic, queueId, e);
}
continue;
}
@@ -152,7 +160,9 @@ public class PullRequestHoldService extends ServiceThread {
this.brokerController.getPullMessageProcessor().executeRequestWhenWakeup(request.getClientChannel(),
request.getRequestCommand());
} catch (Throwable e) {
- log.error("execute request when wakeup failed.", e);
+ log.error(
+ "PullRequestHoldService#notifyMessageArriving: failed to execute request when time's "
+ + "up, topic={}, queueId={}", topic, queueId, e);
}
continue;
}
@@ -166,4 +176,22 @@ public class PullRequestHoldService extends ServiceThread {
}
}
}
+
+ public void notifyMasterOnline() {
+ for (ManyPullRequest mpr : this.pullRequestTable.values()) {
+ if (mpr == null || mpr.isEmpty()) {
+ continue;
+ }
+ for (PullRequest request : mpr.cloneListAndClear()) {
+ try {
+ log.info("notify master online, wakeup {} {}", request.getClientChannel(), request.getRequestCommand());
+ this.brokerController.getPullMessageProcessor().executeRequestWhenWakeup(request.getClientChannel(),
+ request.getRequestCommand());
+ } catch (Throwable e) {
+ log.error("execute request when master online failed.", e);
+ }
+ }
+ }
+
+ }
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/AbortProcessException.java b/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/AbortProcessException.java
new file mode 100644
index 0000000..c81a29a
--- /dev/null
+++ b/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/AbortProcessException.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.rocketmq.broker.mqtrace;
+
+import org.apache.rocketmq.common.UtilAll;
+import org.apache.rocketmq.common.help.FAQUrl;
+
+/**
+ *
+ * This exception is used for broker hooks only : SendMessageHook, ConsumeMessageHook, pullMessageHook
+ * This exception is not ignored while executing hooks and it means that
+ * certain processor should return an immediate error response to the client. The
+ * error response code is included in AbortProcessException. it's naming might
+ * be confusing, so feel free to refactor this class. Also when any class implements
+ * the 3 hook interface mentioned above we should be careful if we want to throw
+ * an AbortProcessException, because it will change the control flow of broker
+ * and cause a RemotingCommand return error immediately. So be aware of the side
+ * effect before throw AbortProcessException in your implementation.
+ *
+ */
+public class AbortProcessException extends RuntimeException {
+ private static final long serialVersionUID = -5728810933841185841L;
+ private int responseCode;
+ private String errorMessage;
+
+ public AbortProcessException(String errorMessage, Throwable cause) {
+ super(FAQUrl.attachDefaultURL(errorMessage), cause);
+ this.responseCode = -1;
+ this.errorMessage = errorMessage;
+ }
+
+ public AbortProcessException(int responseCode, String errorMessage) {
+ super(FAQUrl.attachDefaultURL("CODE: " + UtilAll.responseCode2String(responseCode) + " DESC: "
+ + errorMessage));
+ this.responseCode = responseCode;
+ this.errorMessage = errorMessage;
+ }
+
+ public int getResponseCode() {
+ return responseCode;
+ }
+
+ public AbortProcessException setResponseCode(final int responseCode) {
+ this.responseCode = responseCode;
+ return this;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(final String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+}
\ No newline at end of file
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/ConsumeMessageContext.java b/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/ConsumeMessageContext.java
index ae5d077..ed7bfba 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/ConsumeMessageContext.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/ConsumeMessageContext.java
@@ -17,6 +17,8 @@
package org.apache.rocketmq.broker.mqtrace;
import java.util.Map;
+
+import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.store.stats.BrokerStatsManager;
public class ConsumeMessageContext {
@@ -30,13 +32,22 @@ public class ConsumeMessageContext {
private boolean success;
private String status;
private Object mqTraceContext;
+ private TopicConfig topicConfig;
+
+ private String accountAuthType;
+ private String accountOwnerParent;
+ private String accountOwnerSelf;
+ private int rcvMsgNum;
+ private int rcvMsgSize;
+ private BrokerStatsManager.StatsType rcvStat;
+ private int commercialRcvMsgNum;
private String commercialOwner;
private BrokerStatsManager.StatsType commercialRcvStats;
private int commercialRcvTimes;
private int commercialRcvSize;
- private String namespace;
+ private String namespace;
public String getConsumerGroup() {
return consumerGroup;
}
@@ -109,6 +120,14 @@ public class ConsumeMessageContext {
this.mqTraceContext = mqTraceContext;
}
+ public TopicConfig getTopicConfig() {
+ return topicConfig;
+ }
+
+ public void setTopicConfig(TopicConfig topicConfig) {
+ this.topicConfig = topicConfig;
+ }
+
public int getBodyLength() {
return bodyLength;
}
@@ -117,6 +136,62 @@ public class ConsumeMessageContext {
this.bodyLength = bodyLength;
}
+ public String getAccountAuthType() {
+ return accountAuthType;
+ }
+
+ public void setAccountAuthType(String accountAuthType) {
+ this.accountAuthType = accountAuthType;
+ }
+
+ public String getAccountOwnerParent() {
+ return accountOwnerParent;
+ }
+
+ public void setAccountOwnerParent(String accountOwnerParent) {
+ this.accountOwnerParent = accountOwnerParent;
+ }
+
+ public String getAccountOwnerSelf() {
+ return accountOwnerSelf;
+ }
+
+ public void setAccountOwnerSelf(String accountOwnerSelf) {
+ this.accountOwnerSelf = accountOwnerSelf;
+ }
+
+ public int getRcvMsgNum() {
+ return rcvMsgNum;
+ }
+
+ public void setRcvMsgNum(int rcvMsgNum) {
+ this.rcvMsgNum = rcvMsgNum;
+ }
+
+ public int getRcvMsgSize() {
+ return rcvMsgSize;
+ }
+
+ public void setRcvMsgSize(int rcvMsgSize) {
+ this.rcvMsgSize = rcvMsgSize;
+ }
+
+ public BrokerStatsManager.StatsType getRcvStat() {
+ return rcvStat;
+ }
+
+ public void setRcvStat(BrokerStatsManager.StatsType rcvStat) {
+ this.rcvStat = rcvStat;
+ }
+
+ public int getCommercialRcvMsgNum() {
+ return commercialRcvMsgNum;
+ }
+
+ public void setCommercialRcvMsgNum(int commercialRcvMsgNum) {
+ this.commercialRcvMsgNum = commercialRcvMsgNum;
+ }
+
public String getCommercialOwner() {
return commercialOwner;
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/SendMessageContext.java b/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/SendMessageContext.java
index ab6452e..aaa84b7 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/SendMessageContext.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/mqtrace/SendMessageContext.java
@@ -17,11 +17,16 @@
package org.apache.rocketmq.broker.mqtrace;
import java.util.Properties;
+
import org.apache.rocketmq.common.message.MessageType;
import org.apache.rocketmq.store.stats.BrokerStatsManager;
public class SendMessageContext {
+ /** namespace */
+ private String namespace;
+ /** producer group without namespace. */
private String producerGroup;
+ /** topic without namespace. */
private String topic;
private String msgId;
private String originMsgId;
@@ -38,14 +43,37 @@ public class SendMessageContext {
private String brokerRegionId;
private String msgUniqueKey;
private long bornTimeStamp;
+ private long requestTimeStamp;
private MessageType msgType = MessageType.Trans_msg_Commit;
+
private boolean isSuccess = false;
+ /**
+ * Account Statistics
+ */
+ private String accountAuthType;
+ private String accountOwnerParent;
+ private String accountOwnerSelf;
+ private int sendMsgNum;
+ private int sendMsgSize;
+ private BrokerStatsManager.StatsType sendStat;
+ private int commercialSendMsgNum;
+
+ /**
+ * For Commercial
+ */
private String commercialOwner;
private BrokerStatsManager.StatsType commercialSendStats;
private int commercialSendSize;
private int commercialSendTimes;
- private String namespace;
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
public boolean isSuccess() {
return isSuccess;
@@ -79,6 +107,14 @@ public class SendMessageContext {
this.bornTimeStamp = bornTimeStamp;
}
+ public long getRequestTimeStamp() {
+ return requestTimeStamp;
+ }
+
+ public void setRequestTimeStamp(long requestTimeStamp) {
+ this.requestTimeStamp = requestTimeStamp;
+ }
+
public String getBrokerRegionId() {
return brokerRegionId;
}
@@ -207,10 +243,66 @@ public class SendMessageContext {
this.commercialOwner = commercialOwner;
}
+ public String getAccountAuthType() {
+ return accountAuthType;
+ }
+
+ public void setAccountAuthType(String accountAuthType) {
+ this.accountAuthType = accountAuthType;
+ }
+
+ public String getAccountOwnerParent() {
+ return accountOwnerParent;
+ }
+
+ public void setAccountOwnerParent(String accountOwnerParent) {
+ this.accountOwnerParent = accountOwnerParent;
+ }
+
+ public String getAccountOwnerSelf() {
+ return accountOwnerSelf;
+ }
+
+ public void setAccountOwnerSelf(String accountOwnerSelf) {
+ this.accountOwnerSelf = accountOwnerSelf;
+ }
+
+ public int getSendMsgNum() {
+ return sendMsgNum;
+ }
+
+ public void setSendMsgNum(int sendMsgNum) {
+ this.sendMsgNum = sendMsgNum;
+ }
+
+ public int getSendMsgSize() {
+ return sendMsgSize;
+ }
+
+ public void setSendMsgSize(int sendMsgSize) {
+ this.sendMsgSize = sendMsgSize;
+ }
+
+ public BrokerStatsManager.StatsType getSendStat() {
+ return sendStat;
+ }
+
+ public void setSendStat(BrokerStatsManager.StatsType sendStat) {
+ this.sendStat = sendStat;
+ }
+
public BrokerStatsManager.StatsType getCommercialSendStats() {
return commercialSendStats;
}
+ public int getCommercialSendMsgNum() {
+ return commercialSendMsgNum;
+ }
+
+ public void setCommercialSendMsgNum(int commercialSendMsgNum) {
+ this.commercialSendMsgNum = commercialSendMsgNum;
+ }
+
public void setCommercialSendStats(final BrokerStatsManager.StatsType commercialSendStats) {
this.commercialSendStats = commercialSendStats;
}
@@ -230,12 +322,4 @@ public class SendMessageContext {
public void setCommercialSendTimes(final int commercialSendTimes) {
this.commercialSendTimes = commercialSendTimes;
}
-
- public String getNamespace() {
- return namespace;
- }
-
- public void setNamespace(String namespace) {
- this.namespace = namespace;
- }
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/offset/ConsumerOffsetManager.java b/broker/src/main/java/org/apache/rocketmq/broker/offset/ConsumerOffsetManager.java
index f09522a..4eadaa8 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/offset/ConsumerOffsetManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/offset/ConsumerOffsetManager.java
@@ -24,9 +24,11 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.broker.BrokerPathConfigHelper;
import org.apache.rocketmq.common.ConfigManager;
+import org.apache.rocketmq.common.DataVersion;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.logging.InternalLogger;
@@ -34,14 +36,18 @@ import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.protocol.RemotingSerializable;
public class ConsumerOffsetManager extends ConfigManager {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
- protected static final String TOPIC_GROUP_SEPARATOR = "@";
+ private static final InternalLogger LOG = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ public static final String TOPIC_GROUP_SEPARATOR = "@";
+
+ private DataVersion dataVersion = new DataVersion();
protected ConcurrentMap<String/* topic@group */, ConcurrentMap<Integer, Long>> offsetTable =
new ConcurrentHashMap<String, ConcurrentMap<Integer, Long>>(512);
protected transient BrokerController brokerController;
+ private transient AtomicLong versionChangeCounter = new AtomicLong(0);
+
public ConsumerOffsetManager() {
}
@@ -49,6 +55,36 @@ public class ConsumerOffsetManager extends ConfigManager {
this.brokerController = brokerController;
}
+ public void cleanOffset(String group) {
+ Iterator<Entry<String, ConcurrentMap<Integer, Long>>> it = this.offsetTable.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<String, ConcurrentMap<Integer, Long>> next = it.next();
+ String topicAtGroup = next.getKey();
+ if (topicAtGroup.contains(group)) {
+ String[] arrays = topicAtGroup.split(TOPIC_GROUP_SEPARATOR);
+ if (arrays.length == 2 && group.equals(arrays[1])) {
+ it.remove();
+ LOG.warn("Clean group's offset, {}, {}", topicAtGroup, next.getValue());
+ }
+ }
+ }
+ }
+
+ public void cleanOffsetByTopic(String topic) {
+ Iterator<Entry<String, ConcurrentMap<Integer, Long>>> it = this.offsetTable.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<String, ConcurrentMap<Integer, Long>> next = it.next();
+ String topicAtGroup = next.getKey();
+ if (topicAtGroup.contains(topic)) {
+ String[] arrays = topicAtGroup.split(TOPIC_GROUP_SEPARATOR);
+ if (arrays.length == 2 && topic.equals(arrays[0])) {
+ it.remove();
+ LOG.warn("Clean topic's offset, {}, {}", topicAtGroup, next.getValue());
+ }
+ }
+ }
+ }
+
public void scanUnsubscribedTopic() {
Iterator<Entry<String, ConcurrentMap<Integer, Long>>> it = this.offsetTable.entrySet().iterator();
while (it.hasNext()) {
@@ -62,7 +98,7 @@ public class ConsumerOffsetManager extends ConfigManager {
if (null == brokerController.getConsumerManager().findSubscriptionData(group, topic)
&& this.offsetBehindMuchThanData(topic, next.getValue())) {
it.remove();
- log.warn("remove topic offset, {}", topicAtGroup);
+ LOG.warn("remove topic offset, {}", topicAtGroup);
}
}
}
@@ -118,6 +154,28 @@ public class ConsumerOffsetManager extends ConfigManager {
return groups;
}
+ public Map<String, Set<String>> getGroupTopicMap() {
+ Map<String, Set<String>> retMap = new HashMap<String, Set<String>>(128);
+
+ for (String key : this.offsetTable.keySet()) {
+ String[] arr = key.split(TOPIC_GROUP_SEPARATOR);
+ if (arr.length == 2) {
+ String topic = arr[0];
+ String group = arr[1];
+
+ Set<String> topics = retMap.get(group);
+ if (topics == null) {
+ topics = new HashSet<String>(8);
+ retMap.put(group, topics);
+ }
+
+ topics.add(topic);
+ }
+ }
+
+ return retMap;
+ }
+
public void commitOffset(final String clientHost, final String group, final String topic, final int queueId,
final long offset) {
// topic@group
@@ -134,9 +192,13 @@ public class ConsumerOffsetManager extends ConfigManager {
} else {
Long storeOffset = map.put(queueId, offset);
if (storeOffset != null && offset < storeOffset) {
- log.warn("[NOTIFYME]update consumer offset less than store. clientHost={}, key={}, queueId={}, requestOffset={}, storeOffset={}", clientHost, key, queueId, offset, storeOffset);
+ LOG.warn("[NOTIFYME]update consumer offset less than store. clientHost={}, key={}, queueId={}, requestOffset={}, storeOffset={}", clientHost, key, queueId, offset, storeOffset);
}
}
+ if (versionChangeCounter.incrementAndGet() % brokerController.getBrokerConfig().getConsumerOffsetUpdateVersionStep() == 0) {
+ long stateMachineVersion = brokerController.getMessageStore() != null ? brokerController.getMessageStore().getStateMachineVersion() : 0;
+ dataVersion.nextVersion(stateMachineVersion);
+ }
}
public long queryOffset(final String group, final String topic, final int queueId) {
@@ -145,8 +207,9 @@ public class ConsumerOffsetManager extends ConfigManager {
ConcurrentMap<Integer, Long> map = this.offsetTable.get(key);
if (null != map) {
Long offset = map.get(queueId);
- if (offset != null)
+ if (offset != null) {
return offset;
+ }
}
return -1;
@@ -167,10 +230,12 @@ public class ConsumerOffsetManager extends ConfigManager {
ConsumerOffsetManager obj = RemotingSerializable.fromJson(jsonString, ConsumerOffsetManager.class);
if (obj != null) {
this.offsetTable = obj.offsetTable;
+ this.dataVersion = obj.dataVersion;
}
}
}
+ @Override
public String encode(final boolean prettyFormat) {
return RemotingSerializable.toJson(this, prettyFormat);
}
@@ -232,6 +297,14 @@ public class ConsumerOffsetManager extends ConfigManager {
}
}
+ public DataVersion getDataVersion() {
+ return dataVersion;
+ }
+
+ public void setDataVersion(DataVersion dataVersion) {
+ this.dataVersion = dataVersion;
+ }
+
public void removeOffset(final String group) {
Iterator<Entry<String, ConcurrentMap<Integer, Long>>> it = this.offsetTable.entrySet().iterator();
while (it.hasNext()) {
@@ -241,7 +314,7 @@ public class ConsumerOffsetManager extends ConfigManager {
String[] arrays = topicAtGroup.split(TOPIC_GROUP_SEPARATOR);
if (arrays.length == 2 && group.equals(arrays[1])) {
it.remove();
- log.warn("clean group offset {}", topicAtGroup);
+ LOG.warn("clean group offset {}", topicAtGroup);
}
}
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/out/BrokerOuterAPI.java b/broker/src/main/java/org/apache/rocketmq/broker/out/BrokerOuterAPI.java
index 8a2093a..b637951 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/out/BrokerOuterAPI.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/out/BrokerOuterAPI.java
@@ -16,35 +16,67 @@
*/
package org.apache.rocketmq.broker.out;
-import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.broker.latency.BrokerFixedThreadPoolExecutor;
import org.apache.rocketmq.client.exception.MQBrokerException;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.client.producer.SendStatus;
+import org.apache.rocketmq.common.AbstractBrokerRunnable;
+import org.apache.rocketmq.common.BrokerIdentity;
+import org.apache.rocketmq.common.BrokerSyncInfo;
import org.apache.rocketmq.common.DataVersion;
+import org.apache.rocketmq.common.LockCallback;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.ThreadFactoryImpl;
+import org.apache.rocketmq.common.UnlockCallback;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.constant.LoggerName;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageBatch;
+import org.apache.rocketmq.common.message.MessageClientIDSetter;
+import org.apache.rocketmq.common.message.MessageConst;
+import org.apache.rocketmq.common.message.MessageDecoder;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.common.namesrv.DefaultTopAddressing;
import org.apache.rocketmq.common.namesrv.RegisterBrokerResult;
import org.apache.rocketmq.common.namesrv.TopAddressing;
import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.protocol.body.BrokerMemberGroup;
import org.apache.rocketmq.common.protocol.body.ClusterInfo;
import org.apache.rocketmq.common.protocol.body.ConsumerOffsetSerializeWrapper;
+import org.apache.rocketmq.common.protocol.body.GetBrokerMemberGroupResponseBody;
import org.apache.rocketmq.common.protocol.body.KVTable;
+import org.apache.rocketmq.common.protocol.body.LockBatchRequestBody;
+import org.apache.rocketmq.common.protocol.body.LockBatchResponseBody;
import org.apache.rocketmq.common.protocol.body.RegisterBrokerBody;
import org.apache.rocketmq.common.protocol.body.SubscriptionGroupWrapper;
import org.apache.rocketmq.common.protocol.body.TopicConfigAndMappingSerializeWrapper;
import org.apache.rocketmq.common.protocol.body.TopicConfigSerializeWrapper;
+import org.apache.rocketmq.common.protocol.body.UnlockBatchRequestBody;
+import org.apache.rocketmq.common.protocol.header.ExchangeHAInfoRequestHeader;
+import org.apache.rocketmq.common.protocol.header.ExchangeHAInfoResponseHeader;
+import org.apache.rocketmq.common.protocol.header.GetBrokerMemberGroupRequestHeader;
+import org.apache.rocketmq.common.protocol.header.GetMaxOffsetRequestHeader;
+import org.apache.rocketmq.common.protocol.header.GetMaxOffsetResponseHeader;
+import org.apache.rocketmq.common.protocol.header.GetMinOffsetRequestHeader;
+import org.apache.rocketmq.common.protocol.header.GetMinOffsetResponseHeader;
+import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeaderV2;
+import org.apache.rocketmq.common.protocol.header.SendMessageResponseHeader;
+import org.apache.rocketmq.common.protocol.header.namesrv.BrokerHeartbeatRequestHeader;
import org.apache.rocketmq.common.protocol.header.namesrv.GetRouteInfoRequestHeader;
import org.apache.rocketmq.common.protocol.header.namesrv.QueryDataVersionRequestHeader;
import org.apache.rocketmq.common.protocol.header.namesrv.QueryDataVersionResponseHeader;
import org.apache.rocketmq.common.protocol.header.namesrv.RegisterBrokerRequestHeader;
import org.apache.rocketmq.common.protocol.header.namesrv.RegisterBrokerResponseHeader;
import org.apache.rocketmq.common.protocol.header.namesrv.UnRegisterBrokerRequestHeader;
+import org.apache.rocketmq.common.protocol.route.BrokerData;
import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.common.rpc.ClientMetadata;
import org.apache.rocketmq.common.rpc.RpcClient;
import org.apache.rocketmq.common.rpc.RpcClientImpl;
+import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.InvokeCallback;
@@ -61,37 +93,34 @@ import org.apache.rocketmq.remoting.netty.NettyRemotingClient;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class BrokerOuterAPI {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ private static final InternalLogger LOGGER = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private final RemotingClient remotingClient;
- private final BrokerController brokerController;
- private final TopAddressing topAddressing = new TopAddressing(MixAll.getWSAddr());
+ private final TopAddressing topAddressing = new DefaultTopAddressing(MixAll.getWSAddr());
private String nameSrvAddr = null;
- private final String currBrokerName;
private BrokerFixedThreadPoolExecutor brokerOuterExecutor = new BrokerFixedThreadPoolExecutor(4, 10, 1, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(32), new ThreadFactoryImpl("brokerOutApi_thread_", true));
private ClientMetadata clientMetadata;
private RpcClient rpcClient;
- public BrokerOuterAPI(final NettyClientConfig nettyClientConfig, final BrokerController brokerController) {
-
- this(nettyClientConfig, null, brokerController, new ClientMetadata());
+ public BrokerOuterAPI(final NettyClientConfig nettyClientConfig) {
+ this(nettyClientConfig, null, new ClientMetadata());
}
- private BrokerOuterAPI(final NettyClientConfig nettyClientConfig, RPCHook rpcHook, final BrokerController brokerController, ClientMetadata clientMetadata) {
+ private BrokerOuterAPI(final NettyClientConfig nettyClientConfig, RPCHook rpcHook, ClientMetadata clientMetadata) {
this.remotingClient = new NettyRemotingClient(nettyClientConfig);
this.clientMetadata = clientMetadata;
this.remotingClient.registerRPCHook(rpcHook);
- this.brokerController = brokerController;
- this.currBrokerName = brokerController.getBrokerConfig().getBrokerName();
this.rpcClient = new RpcClientImpl(this.clientMetadata, this.remotingClient);
}
@@ -104,31 +133,224 @@ public class BrokerOuterAPI {
this.brokerOuterExecutor.shutdown();
}
+ public List<String> getNameServerAddressList() {
+ return this.remotingClient.getNameServerAddressList();
+ }
+
public String fetchNameServerAddr() {
try {
String addrs = this.topAddressing.fetchNSAddr();
if (addrs != null) {
if (!addrs.equals(this.nameSrvAddr)) {
- log.info("name server address changed, old: {} new: {}", this.nameSrvAddr, addrs);
+ LOGGER.info("name server address changed, old: {} new: {}", this.nameSrvAddr, addrs);
this.updateNameServerAddressList(addrs);
this.nameSrvAddr = addrs;
return nameSrvAddr;
}
}
} catch (Exception e) {
- log.error("fetchNameServerAddr Exception", e);
+ LOGGER.error("fetchNameServerAddr Exception", e);
}
return nameSrvAddr;
}
public void updateNameServerAddressList(final String addrs) {
- List<String> lst = new ArrayList<String>();
String[] addrArray = addrs.split(";");
- for (String addr : addrArray) {
- lst.add(addr);
+ List<String> lst = new ArrayList<String>(Arrays.asList(addrArray));
+ this.remotingClient.updateNameServerAddressList(lst);
+ }
+
+ public BrokerMemberGroup syncBrokerMemberGroup(String clusterName, String brokerName)
+ throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException {
+ return syncBrokerMemberGroup(clusterName, brokerName, false);
+ }
+
+ public BrokerMemberGroup syncBrokerMemberGroup(String clusterName, String brokerName,
+ boolean isCompatibleWithOldNameSrv)
+ throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException {
+ if (isCompatibleWithOldNameSrv) {
+ return getBrokerMemberGroupCompatible(clusterName, brokerName);
+ } else {
+ return getBrokerMemberGroup(clusterName, brokerName);
}
+ }
- this.remotingClient.updateNameServerAddressList(lst);
+ public BrokerMemberGroup getBrokerMemberGroup(String clusterName, String brokerName)
+ throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException {
+ BrokerMemberGroup brokerMemberGroup = new BrokerMemberGroup(clusterName, brokerName);
+
+ GetBrokerMemberGroupRequestHeader requestHeader = new GetBrokerMemberGroupRequestHeader();
+ requestHeader.setClusterName(clusterName);
+ requestHeader.setBrokerName(brokerName);
+
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_BROKER_MEMBER_GROUP, requestHeader);
+
+ RemotingCommand response = null;
+ response = this.remotingClient.invokeSync(null, request, 3000);
+ assert response != null;
+
+ switch (response.getCode()) {
+ case ResponseCode.SUCCESS: {
+ byte[] body = response.getBody();
+ if (body != null) {
+ GetBrokerMemberGroupResponseBody brokerMemberGroupResponseBody =
+ GetBrokerMemberGroupResponseBody.decode(body, GetBrokerMemberGroupResponseBody.class);
+
+ return brokerMemberGroupResponseBody.getBrokerMemberGroup();
+ }
+ }
+ default:
+ break;
+ }
+
+ return brokerMemberGroup;
+ }
+
+ public BrokerMemberGroup getBrokerMemberGroupCompatible(String clusterName, String brokerName)
+ throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException {
+ BrokerMemberGroup brokerMemberGroup = new BrokerMemberGroup(clusterName, brokerName);
+
+ GetRouteInfoRequestHeader requestHeader = new GetRouteInfoRequestHeader();
+ requestHeader.setTopic(TopicValidator.SYNC_BROKER_MEMBER_GROUP_PREFIX + brokerName);
+
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_ROUTEINFO_BY_TOPIC, requestHeader);
+
+ RemotingCommand response;
+ response = this.remotingClient.invokeSync(null, request, 3000);
+ assert response != null;
+
+ switch (response.getCode()) {
+ case ResponseCode.SUCCESS: {
+ byte[] body = response.getBody();
+ if (body != null) {
+ TopicRouteData topicRouteData = TopicRouteData.decode(body, TopicRouteData.class);
+ for (BrokerData brokerData : topicRouteData.getBrokerDatas()) {
+ if (brokerData != null
+ && brokerData.getBrokerName().equals(brokerName)
+ && brokerData.getCluster().equals(clusterName)) {
+ brokerMemberGroup.getBrokerAddrs().putAll(brokerData.getBrokerAddrs());
+ break;
+ }
+ }
+ return brokerMemberGroup;
+ }
+ }
+ default:
+ break;
+ }
+
+ return brokerMemberGroup;
+ }
+
+ public void sendHeartbeatViaDataVersion(
+ final String clusterName,
+ final String brokerAddr,
+ final String brokerName,
+ final Long brokerId,
+ final int timeoutMillis,
+ final DataVersion dataVersion,
+ final boolean isInBrokerContainer) {
+ List<String> nameServerAddressList = this.remotingClient.getAvailableNameSrvList();
+ if (nameServerAddressList != null && nameServerAddressList.size() > 0) {
+ final QueryDataVersionRequestHeader requestHeader = new QueryDataVersionRequestHeader();
+ requestHeader.setBrokerAddr(brokerAddr);
+ requestHeader.setBrokerName(brokerName);
+ requestHeader.setBrokerId(brokerId);
+ requestHeader.setClusterName(clusterName);
+
+ for (final String namesrvAddr : nameServerAddressList) {
+ brokerOuterExecutor.execute(new AbstractBrokerRunnable(new BrokerIdentity(clusterName, brokerName, brokerId, isInBrokerContainer)) {
+
+ @Override
+ public void run2() {
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.QUERY_DATA_VERSION, requestHeader);
+ request.setBody(dataVersion.encode());
+
+ try {
+ BrokerOuterAPI.this.remotingClient.invokeOneway(namesrvAddr, request, timeoutMillis);
+ } catch (Exception e) {
+ LOGGER.error("sendHeartbeat Exception " + namesrvAddr, e);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ public void sendHeartbeat(final String clusterName,
+ final String brokerAddr,
+ final String brokerName,
+ final Long brokerId,
+ final int timeoutMills,
+ final boolean isInBrokerContainer) {
+ List<String> nameServerAddressList = this.remotingClient.getAvailableNameSrvList();
+
+ final BrokerHeartbeatRequestHeader requestHeader = new BrokerHeartbeatRequestHeader();
+ requestHeader.setClusterName(clusterName);
+ requestHeader.setBrokerAddr(brokerAddr);
+ requestHeader.setBrokerName(brokerName);
+
+ if (nameServerAddressList != null && nameServerAddressList.size() > 0) {
+ for (final String namesrvAddr : nameServerAddressList) {
+ brokerOuterExecutor.execute(new AbstractBrokerRunnable(new BrokerIdentity(clusterName, brokerName, brokerId, isInBrokerContainer)) {
+ @Override
+ public void run2() {
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.BROKER_HEARTBEAT, requestHeader);
+
+ try {
+ BrokerOuterAPI.this.remotingClient.invokeOneway(namesrvAddr, request, timeoutMills);
+ } catch (Exception e) {
+ LOGGER.error("sendHeartbeat Exception " + namesrvAddr, e);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ public BrokerSyncInfo retrieveBrokerHaInfo(String masterBrokerAddr)
+ throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException,
+ MQBrokerException, RemotingCommandException {
+ ExchangeHAInfoRequestHeader requestHeader = new ExchangeHAInfoRequestHeader();
+ requestHeader.setMasterHaAddress(null);
+
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.EXCHANGE_BROKER_HA_INFO, requestHeader);
+
+ RemotingCommand response = this.remotingClient.invokeSync(masterBrokerAddr, request, 3000);
+ assert response != null;
+ switch (response.getCode()) {
+ case ResponseCode.SUCCESS: {
+ ExchangeHAInfoResponseHeader responseHeader = response.decodeCommandCustomHeader(ExchangeHAInfoResponseHeader.class);
+ return new BrokerSyncInfo(responseHeader.getMasterHaAddress(), responseHeader.getMasterFlushOffset(), responseHeader.getMasterAddress());
+ }
+ default:
+ break;
+ }
+
+ throw new MQBrokerException(response.getCode(), response.getRemark());
+ }
+
+ public void sendBrokerHaInfo(String brokerAddr, String masterHaAddr, long brokerInitMaxOffset, String masterAddr)
+ throws InterruptedException, RemotingTimeoutException, RemotingSendRequestException, RemotingConnectException, MQBrokerException {
+ ExchangeHAInfoRequestHeader requestHeader = new ExchangeHAInfoRequestHeader();
+ requestHeader.setMasterHaAddress(masterHaAddr);
+ requestHeader.setMasterFlushOffset(brokerInitMaxOffset);
+ requestHeader.setMasterAddress(masterAddr);
+
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.EXCHANGE_BROKER_HA_INFO, requestHeader);
+
+ RemotingCommand response = this.remotingClient.invokeSync(brokerAddr, request, 3000);
+
+ assert response != null;
+ switch (response.getCode()) {
+ case ResponseCode.SUCCESS: {
+ return;
+ }
+ default:
+ break;
+ }
+
+ throw new MQBrokerException(response.getCode(), response.getRemark());
}
public List<RegisterBrokerResult> registerBrokerAll(
@@ -141,10 +363,56 @@ public class BrokerOuterAPI {
final List<String> filterServerList,
final boolean oneway,
final int timeoutMills,
- final boolean compressed) {
+ final boolean enableActingMaster,
+ final boolean compressed,
+ final boolean isInBrokerContainer) {
+ return registerBrokerAll(clusterName,
+ brokerAddr,
+ brokerName,
+ brokerId,
+ haServerAddr,
+ topicConfigWrapper,
+ filterServerList,
+ oneway, timeoutMills,
+ enableActingMaster,
+ compressed,
+ null,
+ isInBrokerContainer);
+ }
+
+ /**
+ * Considering compression brings much CPU overhead to name server, stream API will not support compression and
+ * compression feature is deprecated.
+ *
+ * @param clusterName
+ * @param brokerAddr
+ * @param brokerName
+ * @param brokerId
+ * @param haServerAddr
+ * @param topicConfigWrapper
+ * @param filterServerList
+ * @param oneway
+ * @param timeoutMills
+ * @param compressed default false
+ * @return
+ */
+ public List<RegisterBrokerResult> registerBrokerAll(
+ final String clusterName,
+ final String brokerAddr,
+ final String brokerName,
+ final long brokerId,
+ final String haServerAddr,
+ final TopicConfigSerializeWrapper topicConfigWrapper,
+ final List<String> filterServerList,
+ final boolean oneway,
+ final int timeoutMills,
+ final boolean enableActingMaster,
+ final boolean compressed,
+ final Long heartbeatTimeoutMillis,
+ final boolean isInBrokerContainer) {
final List<RegisterBrokerResult> registerBrokerResultList = new CopyOnWriteArrayList<>();
- List<String> nameServerAddressList = this.remotingClient.getNameServerAddressList();
+ List<String> nameServerAddressList = this.remotingClient.getAvailableNameSrvList();
if (nameServerAddressList != null && nameServerAddressList.size() > 0) {
final RegisterBrokerRequestHeader requestHeader = new RegisterBrokerRequestHeader();
@@ -153,7 +421,11 @@ public class BrokerOuterAPI {
requestHeader.setBrokerName(brokerName);
requestHeader.setClusterName(clusterName);
requestHeader.setHaServerAddr(haServerAddr);
- requestHeader.setCompressed(compressed);
+ requestHeader.setEnableActingMaster(enableActingMaster);
+ requestHeader.setCompressed(false);
+ if (heartbeatTimeoutMillis != null) {
+ requestHeader.setHeartbeatTimeoutMillis(heartbeatTimeoutMillis);
+ }
RegisterBrokerBody requestBody = new RegisterBrokerBody();
requestBody.setTopicConfigSerializeWrapper(TopicConfigAndMappingSerializeWrapper.from(topicConfigWrapper));
@@ -163,18 +435,17 @@ public class BrokerOuterAPI {
requestHeader.setBodyCrc32(bodyCrc32);
final CountDownLatch countDownLatch = new CountDownLatch(nameServerAddressList.size());
for (final String namesrvAddr : nameServerAddressList) {
- brokerOuterExecutor.execute(new Runnable() {
- @Override
- public void run() {
+ brokerOuterExecutor.execute(new AbstractBrokerRunnable(new BrokerIdentity(clusterName, brokerName, brokerId, isInBrokerContainer)) {
+ @Override public void run2() {
try {
RegisterBrokerResult result = registerBroker(namesrvAddr, oneway, timeoutMills, requestHeader, body);
if (result != null) {
registerBrokerResultList.add(result);
}
- log.info("register broker[{}]to name server {} OK", brokerId, namesrvAddr);
+ LOGGER.info("Registering current broker to name server completed. TargetHost={}", namesrvAddr);
} catch (Exception e) {
- log.warn("registerBroker Exception, {}", namesrvAddr, e);
+ LOGGER.error("Failed to register current broker to name server. TargetHost={}", namesrvAddr, e);
} finally {
countDownLatch.countDown();
}
@@ -183,8 +454,10 @@ public class BrokerOuterAPI {
}
try {
- countDownLatch.await(timeoutMills, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
+ if (!countDownLatch.await(timeoutMills, TimeUnit.MILLISECONDS)) {
+ LOGGER.warn("Registration to one or more name servers does NOT complete within deadline. Timeout threshold: {}ms", timeoutMills);
+ }
+ } catch (InterruptedException ignore) {
}
}
@@ -243,9 +516,9 @@ public class BrokerOuterAPI {
for (String namesrvAddr : nameServerAddressList) {
try {
this.unregisterBroker(namesrvAddr, clusterName, brokerAddr, brokerName, brokerId);
- log.info("unregisterBroker OK, NamesrvAddr: {}", namesrvAddr);
+ LOGGER.info("unregisterBroker OK, NamesrvAddr: {}", namesrvAddr);
} catch (Exception e) {
- log.warn("unregisterBroker Exception, {}", namesrvAddr, e);
+ LOGGER.warn("unregisterBroker Exception, {}", namesrvAddr, e);
}
}
}
@@ -284,15 +557,15 @@ public class BrokerOuterAPI {
final String brokerName,
final long brokerId,
final TopicConfigSerializeWrapper topicConfigWrapper,
- final int timeoutMills) {
+ final int timeoutMills,
+ final boolean isInBrokerContainer) {
final List<Boolean> changedList = new CopyOnWriteArrayList<>();
List<String> nameServerAddressList = this.remotingClient.getNameServerAddressList();
if (nameServerAddressList != null && nameServerAddressList.size() > 0) {
final CountDownLatch countDownLatch = new CountDownLatch(nameServerAddressList.size());
for (final String namesrvAddr : nameServerAddressList) {
- brokerOuterExecutor.execute(new Runnable() {
- @Override
- public void run() {
+ brokerOuterExecutor.execute(new AbstractBrokerRunnable(new BrokerIdentity(clusterName, brokerName, brokerId, isInBrokerContainer)) {
+ @Override public void run2() {
try {
QueryDataVersionRequestHeader requestHeader = new QueryDataVersionRequestHeader();
requestHeader.setBrokerAddr(brokerAddr);
@@ -323,10 +596,10 @@ public class BrokerOuterAPI {
default:
break;
}
- log.warn("Query data version from name server {} OK,changed {}, broker {},name server {}", namesrvAddr, changed, topicConfigWrapper.getDataVersion(), nameServerDataVersion == null ? "" : nameServerDataVersion);
+ LOGGER.warn("Query data version from name server {} OK, changed {}, broker {},name server {}", namesrvAddr, changed, topicConfigWrapper.getDataVersion(), nameServerDataVersion == null ? "" : nameServerDataVersion);
} catch (Exception e) {
changedList.add(Boolean.TRUE);
- log.error("Query data version from name server {} Exception, {}", namesrvAddr, e);
+ LOGGER.error("Query data version from name server {} Exception, {}", namesrvAddr, e);
} finally {
countDownLatch.countDown();
}
@@ -337,7 +610,7 @@ public class BrokerOuterAPI {
try {
countDownLatch.await(timeoutMills, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
- log.error("query dataversion from nameserver countDownLatch await Exception", e);
+ LOGGER.error("query dataversion from nameserver countDownLatch await Exception", e);
}
}
return changedList;
@@ -416,6 +689,220 @@ public class BrokerOuterAPI {
remotingClient.registerRPCHook(rpcHook);
}
+ public void clearRPCHook() {
+ remotingClient.clearRPCHook();
+ }
+
+ public long getMaxOffset(final String addr, final String topic, final int queueId, final boolean committed,
+ final boolean isOnlyThisBroker)
+ throws RemotingException, MQBrokerException, InterruptedException {
+ GetMaxOffsetRequestHeader requestHeader = new GetMaxOffsetRequestHeader();
+ requestHeader.setTopic(topic);
+ requestHeader.setQueueId(queueId);
+ requestHeader.setCommitted(committed);
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_MAX_OFFSET, requestHeader);
+
+ RemotingCommand response = this.remotingClient.invokeSync(addr, request, 3000);
+ assert response != null;
+ switch (response.getCode()) {
+ case ResponseCode.SUCCESS: {
+ GetMaxOffsetResponseHeader responseHeader = response.decodeCommandCustomHeader(GetMaxOffsetResponseHeader.class);
+
+ return responseHeader.getOffset();
+ }
+ default:
+ break;
+ }
+
+ throw new MQBrokerException(response.getCode(), response.getRemark());
+ }
+
+ public long getMinOffset(final String addr, final String topic, final int queueId, final boolean isOnlyThisBroker)
+ throws RemotingException, MQBrokerException, InterruptedException {
+ GetMinOffsetRequestHeader requestHeader = new GetMinOffsetRequestHeader();
+ requestHeader.setTopic(topic);
+ requestHeader.setQueueId(queueId);
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_MIN_OFFSET, requestHeader);
+
+ RemotingCommand response = this.remotingClient.invokeSync(addr, request, 3000);
+ assert response != null;
+ switch (response.getCode()) {
+ case ResponseCode.SUCCESS: {
+ GetMinOffsetResponseHeader responseHeader = response.decodeCommandCustomHeader(GetMinOffsetResponseHeader.class);
+
+ return responseHeader.getOffset();
+ }
+ default:
+ break;
+ }
+
+ throw new MQBrokerException(response.getCode(), response.getRemark());
+ }
+
+ public void lockBatchMQAsync(
+ final String addr,
+ final LockBatchRequestBody requestBody,
+ final long timeoutMillis,
+ final LockCallback callback) throws RemotingException, InterruptedException {
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.LOCK_BATCH_MQ, null);
+
+ request.setBody(requestBody.encode());
+ this.remotingClient.invokeAsync(addr, request, timeoutMillis, responseFuture -> {
+ if (callback == null) {
+ return;
+ }
+
+ try {
+ RemotingCommand response = responseFuture.getResponseCommand();
+ if (response != null) {
+ if (response.getCode() == ResponseCode.SUCCESS) {
+ LockBatchResponseBody responseBody = LockBatchResponseBody.decode(response.getBody(),
+ LockBatchResponseBody.class);
+ Set<MessageQueue> messageQueues = responseBody.getLockOKMQSet();
+ callback.onSuccess(messageQueues);
+ } else {
+ callback.onException(new MQBrokerException(response.getCode(), response.getRemark()));
+ }
+ }
+ } catch (Throwable ignored) {
+
+ }
+ });
+ }
+
+ public void unlockBatchMQAsync(
+ final String addr,
+ final UnlockBatchRequestBody requestBody,
+ final long timeoutMillis,
+ final UnlockCallback callback) throws RemotingException, InterruptedException {
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.UNLOCK_BATCH_MQ, null);
+
+ request.setBody(requestBody.encode());
+
+ this.remotingClient.invokeAsync(addr, request, timeoutMillis, responseFuture -> {
+ if (callback == null) {
+ return;
+ }
+
+ try {
+ RemotingCommand response = responseFuture.getResponseCommand();
+ if (response != null) {
+ if (response.getCode() == ResponseCode.SUCCESS) {
+ callback.onSuccess();
+ } else {
+ callback.onException(new MQBrokerException(response.getCode(), response.getRemark()));
+ }
+ }
+ } catch (Throwable ignored) {
+
+ }
+ });
+ }
+
+ public RemotingClient getRemotingClient() {
+ return this.remotingClient;
+ }
+
+ public SendResult sendMessageToSpecificBroker(String brokerAddr, final String brokerName,
+ final MessageExt msg, String group,
+ long timeoutMillis) throws RemotingException, MQBrokerException, InterruptedException {
+
+ SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
+ requestHeader.setProducerGroup(group);
+ requestHeader.setTopic(msg.getTopic());
+ requestHeader.setDefaultTopic(TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC);
+ requestHeader.setDefaultTopicQueueNums(8);
+ requestHeader.setQueueId(msg.getQueueId());
+ requestHeader.setSysFlag(msg.getSysFlag());
+ requestHeader.setBornTimestamp(msg.getBornTimestamp());
+ requestHeader.setFlag(msg.getFlag());
+ requestHeader.setProperties(MessageDecoder.messageProperties2String(msg.getProperties()));
+ requestHeader.setReconsumeTimes(msg.getReconsumeTimes());
+ requestHeader.setBatch(false);
+
+ SendMessageRequestHeaderV2 requestHeaderV2 = SendMessageRequestHeaderV2.createSendMessageRequestHeaderV2(requestHeader);
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE_V2, requestHeaderV2);
+
+ request.setBody(msg.getBody());
+
+ RemotingCommand response = this.remotingClient.invokeSync(brokerAddr, request, timeoutMillis);
+
+ return this.processSendResponse(brokerName, msg, response);
+ }
+
+ private SendResult processSendResponse(
+ final String brokerName,
+ final Message msg,
+ final RemotingCommand response
+ ) throws MQBrokerException, RemotingCommandException {
+ switch (response.getCode()) {
+ case ResponseCode.FLUSH_DISK_TIMEOUT:
+ case ResponseCode.FLUSH_SLAVE_TIMEOUT:
+ case ResponseCode.SLAVE_NOT_AVAILABLE:
+ case ResponseCode.SUCCESS: {
+ SendStatus sendStatus = SendStatus.SEND_OK;
+ switch (response.getCode()) {
+ case ResponseCode.FLUSH_DISK_TIMEOUT:
+ sendStatus = SendStatus.FLUSH_DISK_TIMEOUT;
+ break;
+ case ResponseCode.FLUSH_SLAVE_TIMEOUT:
+ sendStatus = SendStatus.FLUSH_SLAVE_TIMEOUT;
+ break;
+ case ResponseCode.SLAVE_NOT_AVAILABLE:
+ sendStatus = SendStatus.SLAVE_NOT_AVAILABLE;
+ break;
+ case ResponseCode.SUCCESS:
+ sendStatus = SendStatus.SEND_OK;
+ break;
+ default:
+ assert false;
+ break;
+ }
+
+ SendMessageResponseHeader responseHeader =
+ (SendMessageResponseHeader) response.decodeCommandCustomHeader(SendMessageResponseHeader.class);
+
+ //If namespace not null , reset Topic without namespace.
+ String topic = msg.getTopic();
+
+ MessageQueue messageQueue = new MessageQueue(topic, brokerName, responseHeader.getQueueId());
+
+ String uniqMsgId = MessageClientIDSetter.getUniqID(msg);
+ if (msg instanceof MessageBatch) {
+ StringBuilder sb = new StringBuilder();
+ for (Message message : (MessageBatch) msg) {
+ sb.append(sb.length() == 0 ? "" : ",").append(MessageClientIDSetter.getUniqID(message));
+ }
+ uniqMsgId = sb.toString();
+ }
+ SendResult sendResult = new SendResult(sendStatus,
+ uniqMsgId,
+ responseHeader.getMsgId(), messageQueue, responseHeader.getQueueOffset());
+ sendResult.setTransactionId(responseHeader.getTransactionId());
+ String regionId = response.getExtFields().get(MessageConst.PROPERTY_MSG_REGION);
+ String traceOn = response.getExtFields().get(MessageConst.PROPERTY_TRACE_SWITCH);
+ if (regionId == null || regionId.isEmpty()) {
+ regionId = MixAll.DEFAULT_TRACE_REGION_ID;
+ }
+ if (traceOn != null && traceOn.equals("false")) {
+ sendResult.setTraceOn(false);
+ } else {
+ sendResult.setTraceOn(true);
+ }
+ sendResult.setRegionId(regionId);
+ return sendResult;
+ }
+ default:
+ break;
+ }
+
+ throw new MQBrokerException(response.getCode(), response.getRemark());
+ }
+
+ public BrokerFixedThreadPoolExecutor getBrokerOuterExecutor() {
+ return brokerOuterExecutor;
+ }
+
public TopicRouteData getTopicRouteInfoFromNameServer(final String topic, final long timeoutMillis)
throws RemotingException, MQBrokerException, InterruptedException {
return getTopicRouteInfoFromNameServer(topic, timeoutMillis, true);
@@ -433,7 +920,7 @@ public class BrokerOuterAPI {
switch (response.getCode()) {
case ResponseCode.TOPIC_NOT_EXIST: {
if (allowTopicNotExist) {
- log.warn("get Topic [{}] RouteInfoFromNameServer is not exist value", topic);
+ LOGGER.warn("get Topic [{}] RouteInfoFromNameServer is not exist value", topic);
}
break;
@@ -466,17 +953,16 @@ public class BrokerOuterAPI {
throw new MQBrokerException(response.getCode(), response.getRemark());
}
- public void forwardRequest(String brokerAddr, RemotingCommand request, long timeoutMillis, InvokeCallback invokeCallback) throws InterruptedException, RemotingSendRequestException, RemotingTimeoutException, RemotingTooMuchRequestException, RemotingConnectException {
+ public void forwardRequest(String brokerAddr, RemotingCommand request, long timeoutMillis,
+ InvokeCallback invokeCallback) throws InterruptedException, RemotingSendRequestException, RemotingTimeoutException, RemotingTooMuchRequestException, RemotingConnectException {
this.remotingClient.invokeAsync(brokerAddr, request, timeoutMillis, invokeCallback);
}
-
public void refreshMetadata() throws Exception {
ClusterInfo brokerClusterInfo = getBrokerClusterInfo();
clientMetadata.refreshClusterInfo(brokerClusterInfo);
}
-
public ClientMetadata getClientMetadata() {
return clientMetadata;
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/pagecache/OneMessageTransfer.java b/broker/src/main/java/org/apache/rocketmq/broker/pagecache/OneMessageTransfer.java
index 558f091..952cf4f 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/pagecache/OneMessageTransfer.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/pagecache/OneMessageTransfer.java
@@ -70,6 +70,7 @@ public class OneMessageTransfer extends AbstractReferenceCounted implements File
return 0;
}
+
@Override
public FileRegion retain() {
super.retain();
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/plugin/AbstractPluginMessageStore.java b/broker/src/main/java/org/apache/rocketmq/broker/plugin/AbstractPluginMessageStore.java
index 9aa1d9b..4254221 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/plugin/AbstractPluginMessageStore.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/plugin/AbstractPluginMessageStore.java
@@ -17,22 +17,43 @@
package org.apache.rocketmq.broker.plugin;
+import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.LinkedList;
+import java.util.Optional;
import java.util.Set;
+import java.util.List;
import java.util.concurrent.CompletableFuture;
+import org.apache.rocketmq.common.SystemClock;
+import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.message.MessageExtBatch;
+import org.apache.rocketmq.common.protocol.body.HARuntimeInfo;
+import org.apache.rocketmq.store.AllocateMappedFileService;
+import org.apache.rocketmq.store.AppendMessageResult;
+import org.apache.rocketmq.store.CommitLog;
import org.apache.rocketmq.store.CommitLogDispatcher;
+import org.apache.rocketmq.store.DispatchRequest;
import org.apache.rocketmq.store.GetMessageResult;
-import org.apache.rocketmq.store.MessageExtBatch;
-import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
import org.apache.rocketmq.store.MessageFilter;
import org.apache.rocketmq.store.MessageStore;
import org.apache.rocketmq.store.PutMessageResult;
import org.apache.rocketmq.store.QueryMessageResult;
+import org.apache.rocketmq.store.RunningFlags;
import org.apache.rocketmq.store.SelectMappedBufferResult;
+import org.apache.rocketmq.store.StoreCheckpoint;
+import org.apache.rocketmq.store.StoreStatsService;
+import org.apache.rocketmq.store.TransientStorePool;
+import org.apache.rocketmq.store.config.MessageStoreConfig;
+import org.apache.rocketmq.store.ha.HAService;
+import org.apache.rocketmq.store.hook.PutMessageHook;
+import org.apache.rocketmq.store.hook.SendMessageBackHook;
+import org.apache.rocketmq.store.logfile.MappedFile;
import org.apache.rocketmq.store.queue.ConsumeQueueInterface;
+import org.apache.rocketmq.store.queue.ConsumeQueueStore;
import org.apache.rocketmq.store.stats.BrokerStatsManager;
+import org.apache.rocketmq.store.util.PerfCounter;
public abstract class AbstractPluginMessageStore implements MessageStore {
protected MessageStore next = null;
@@ -201,16 +222,6 @@ public abstract class AbstractPluginMessageStore implements MessageStore {
}
@Override
- public void updateHaMasterAddress(String newAddr) {
- next.updateHaMasterAddress(newAddr);
- }
-
- @Override
- public long slaveFallBehindMuch() {
- return next.slaveFallBehindMuch();
- }
-
- @Override
public long now() {
return next.now();
}
@@ -269,4 +280,255 @@ public abstract class AbstractPluginMessageStore implements MessageStore {
public BrokerStatsManager getBrokerStatsManager() {
return next.getBrokerStatsManager();
}
+
+ @Override
+ public int remainTransientStoreBufferNumbs() {
+ return next.remainTransientStoreBufferNumbs();
+ }
+
+ @Override
+ public long remainHowManyDataToCommit() {
+ return next.remainHowManyDataToCommit();
+ }
+
+ @Override
+ public long remainHowManyDataToFlush() {
+ return next.remainHowManyDataToFlush();
+ }
+
+ @Override
+ public DispatchRequest checkMessageAndReturnSize(final ByteBuffer byteBuffer, final boolean checkCRC,
+ final boolean checkDupInfo, final boolean readBody) {
+ return next.checkMessageAndReturnSize(byteBuffer, checkCRC, checkDupInfo, readBody);
+ }
+
+ @Override
+ public long getStateMachineVersion() {
+ return next.getStateMachineVersion();
+ }
+
+ @Override public PutMessageResult putMessages(MessageExtBatch messageExtBatch) {
+ return next.putMessages(messageExtBatch);
+ }
+
+ @Override public HARuntimeInfo getHARuntimeInfo() {
+ return next.getHARuntimeInfo();
+ }
+
+ @Override public boolean getLastMappedFile(long startOffset) {
+ return next.getLastMappedFile(startOffset);
+ }
+
+ @Override public void updateHaMasterAddress(String newAddr) {
+ next.updateHaMasterAddress(newAddr);
+ }
+
+ @Override public void updateMasterAddress(String newAddr) {
+ next.updateMasterAddress(newAddr);
+ }
+
+ @Override public long slaveFallBehindMuch() {
+ return next.slaveFallBehindMuch();
+ }
+
+ @Override public long getFlushedWhere() {
+ return next.getFlushedWhere();
+ }
+
+ @Override public MessageStore getMasterStoreInProcess() {
+ return next.getMasterStoreInProcess();
+ }
+
+ @Override public void setMasterStoreInProcess(MessageStore masterStoreInProcess) {
+ next.setMasterStoreInProcess(masterStoreInProcess);
+ }
+
+ @Override
+ public boolean getData(long offset, int size, ByteBuffer byteBuffer) {
+ return next.getData(offset, size, byteBuffer);
+ }
+
+ @Override public void setAliveReplicaNumInGroup(int aliveReplicaNums) {
+ next.setAliveReplicaNumInGroup(aliveReplicaNums);
+ }
+
+ @Override public int getAliveReplicaNumInGroup() {
+ return next.getAliveReplicaNumInGroup();
+ }
+
+ @Override public void wakeupHAClient() {
+ next.wakeupHAClient();
+ }
+
+ @Override public long getMasterFlushedOffset() {
+ return next.getMasterFlushedOffset();
+ }
+
+ @Override public long getBrokerInitMaxOffset() {
+ return next.getBrokerInitMaxOffset();
+ }
+
+ @Override public void setMasterFlushedOffset(long masterFlushedOffset) {
+ next.setMasterFlushedOffset(masterFlushedOffset);
+ }
+
+ @Override public void setBrokerInitMaxOffset(long brokerInitMaxOffset) {
+ next.setBrokerInitMaxOffset(brokerInitMaxOffset);
+ }
+
+ @Override public byte[] calcDeltaChecksum(long from, long to) {
+ return next.calcDeltaChecksum(from, to);
+ }
+
+ @Override public HAService getHaService() {
+ return next.getHaService();
+ }
+
+ @Override public boolean truncateFiles(long offsetToTruncate) {
+ return next.truncateFiles(offsetToTruncate);
+ }
+
+ @Override public boolean isOffsetAligned(long offset) {
+ return next.isOffsetAligned(offset);
+ }
+
+ @Override public RunningFlags getRunningFlags() {
+ return next.getRunningFlags();
+ }
+
+ @Override public void setSendMessageBackHook(SendMessageBackHook sendMessageBackHook) {
+ next.setSendMessageBackHook(sendMessageBackHook);
+ }
+
+ @Override public SendMessageBackHook getSendMessageBackHook() {
+ return next.getSendMessageBackHook();
+ }
+
+ @Override
+ public GetMessageResult getMessage(String group, String topic, int queueId, long offset,
+ int maxMsgNums, int maxTotalMsgSize, MessageFilter messageFilter) {
+ return next.getMessage(group, topic, queueId, offset, maxMsgNums, maxTotalMsgSize, messageFilter);
+ }
+
+ @Override public MessageExt lookMessageByOffset(long commitLogOffset, int size) {
+ return next.lookMessageByOffset(commitLogOffset, size);
+ }
+
+ @Override public List<SelectMappedBufferResult> getBulkCommitLogData(long offset, int size) {
+ return next.getBulkCommitLogData(offset, size);
+ }
+
+ @Override
+ public void onCommitLogAppend(MessageExtBrokerInner msg, AppendMessageResult result, MappedFile commitLogFile) {
+ next.onCommitLogAppend(msg, result, commitLogFile);
+ }
+
+ @Override
+ public void onCommitLogDispatch(DispatchRequest dispatchRequest, boolean doDispatch, MappedFile commitLogFile,
+ boolean isRecover, boolean isFileEnd) {
+ next.onCommitLogDispatch(dispatchRequest, doDispatch, commitLogFile, isRecover, isFileEnd);
+ }
+
+ @Override
+ public MessageStoreConfig getMessageStoreConfig() {
+ return next.getMessageStoreConfig();
+ }
+
+ @Override
+ public StoreStatsService getStoreStatsService() {
+ return next.getStoreStatsService();
+ }
+
+ @Override
+ public StoreCheckpoint getStoreCheckpoint() {
+ return next.getStoreCheckpoint();
+ }
+
+ @Override
+ public SystemClock getSystemClock() {
+ return next.getSystemClock();
+ }
+
+ @Override
+ public CommitLog getCommitLog() {
+ return next.getCommitLog();
+ }
+
+ @Override
+ public TransientStorePool getTransientStorePool() {
+ return next.getTransientStorePool();
+ }
+
+ @Override
+ public AllocateMappedFileService getAllocateMappedFileService() {
+ return next.getAllocateMappedFileService();
+ }
+
+ @Override
+ public void truncateDirtyLogicFiles(long phyOffset) {
+ next.truncateDirtyLogicFiles(phyOffset);
+ }
+
+ @Override
+ public void destroyLogics() {
+ next.destroyLogics();
+ }
+
+ @Override
+ public void unlockMappedFile(MappedFile unlockMappedFile) {
+ next.unlockMappedFile(unlockMappedFile);
+ }
+
+ @Override
+ public PerfCounter.Ticks getPerfCounter() {
+ return next.getPerfCounter();
+ }
+
+ @Override
+ public ConsumeQueueStore getQueueStore() {
+ return next.getQueueStore();
+ }
+
+ @Override
+ public boolean isSyncDiskFlush() {
+ return next.isSyncDiskFlush();
+ }
+
+ @Override
+ public boolean isSyncMaster() {
+ return next.isSyncMaster();
+ }
+
+ @Override
+ public void assignOffset(MessageExtBrokerInner msg, short messageNum) {
+ next.assignOffset(msg, messageNum);
+ }
+
+ @Override
+ public Optional<TopicConfig> getTopicConfig(String topic) {
+ return next.getTopicConfig(topic);
+ }
+
+ @Override
+ public List<PutMessageHook> getPutMessageHookList() {
+ return next.getPutMessageHookList();
+ }
+
+ @Override
+ public long getLastFileFromOffset() {
+ return next.getLastFileFromOffset();
+ }
+
+ @Override
+ public void setPhysicalOffset(long phyOffset) {
+ next.setPhysicalOffset(phyOffset);
+ }
+
+ @Override public boolean isMappedFilesEmpty() {
+ return next.isMappedFilesEmpty();
+ }
+
+ @Override public boolean isShutdown() {
+ return next.isShutdown();
+ }
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/plugin/BrokerAttachedPlugin.java b/broker/src/main/java/org/apache/rocketmq/broker/plugin/BrokerAttachedPlugin.java
new file mode 100644
index 0000000..0cd2a27
--- /dev/null
+++ b/broker/src/main/java/org/apache/rocketmq/broker/plugin/BrokerAttachedPlugin.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.rocketmq.broker.plugin;
+
+import java.util.Map;
+
+public interface BrokerAttachedPlugin {
+
+ /**
+ * Get plugin name
+ *
+ * @return plugin name
+ */
+ String pluginName();
+
+ /**
+ * Load broker attached plugin.
+ *
+ * @return load success or failed
+ */
+ boolean load();
+
+ /**
+ * Start broker attached plugin.
+ */
+ void start();
+
+ /**
+ * Shutdown broker attached plugin.
+ */
+ void shutdown();
+
+ /**
+ * Sync metadata from master.
+ */
+ void syncMetadata();
+
+ /**
+ * Sync metadata reverse from slave
+ *
+ * @param brokerAddr
+ */
+ void syncMetadataReverse(String brokerAddr) throws Exception;
+
+ /**
+ * Some plugin need build runningInfo when prepare runtime info.
+ *
+ * @param runtimeInfo
+ */
+ void buildRuntimeInfo(Map<String, String> runtimeInfo);
+
+ /**
+ * Some plugin need do something when status changed. For example, brokerRole change to master or slave.
+ *
+ * @param shouldStart
+ */
+ void statusChanged(boolean shouldStart);
+
+}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/plugin/MessageStoreFactory.java b/broker/src/main/java/org/apache/rocketmq/broker/plugin/MessageStoreFactory.java
index 8db538b..b64ab5a 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/plugin/MessageStoreFactory.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/plugin/MessageStoreFactory.java
@@ -22,8 +22,8 @@ import java.lang.reflect.Constructor;
import org.apache.rocketmq.store.MessageStore;
public final class MessageStoreFactory {
- public final static MessageStore build(MessageStorePluginContext context, MessageStore messageStore)
- throws IOException {
+ public final static MessageStore build(MessageStorePluginContext context,
+ MessageStore messageStore) throws IOException {
String plugin = context.getBrokerConfig().getMessageStorePlugIn();
if (plugin != null && plugin.trim().length() != 0) {
String[] pluginClasses = plugin.split(",");
@@ -31,12 +31,13 @@ public final class MessageStoreFactory {
String pluginClass = pluginClasses[i];
try {
@SuppressWarnings("unchecked")
- Class<AbstractPluginMessageStore> clazz = (Class<AbstractPluginMessageStore>) Class.forName(pluginClass);
+ Class<AbstractPluginMessageStore> clazz = (Class<AbstractPluginMessageStore>)Class.forName(pluginClass);
Constructor<AbstractPluginMessageStore> construct = clazz.getConstructor(MessageStorePluginContext.class, MessageStore.class);
- messageStore = construct.newInstance(context, messageStore);
- } catch (Throwable e) {
- throw new RuntimeException(String.format(
- "Initialize plugin's class %s not found!", pluginClass), e);
+ AbstractPluginMessageStore pluginMessageStore = construct.newInstance(context, messageStore);
+ messageStore = pluginMessageStore;
+ }
+ catch (Throwable e) {
+ throw new RuntimeException("Initialize plugin's class: " + pluginClass + " not found!", e);
}
}
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/plugin/MessageStorePluginContext.java b/broker/src/main/java/org/apache/rocketmq/broker/plugin/MessageStorePluginContext.java
index b822a2f..c132cf9 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/plugin/MessageStorePluginContext.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/plugin/MessageStorePluginContext.java
@@ -17,25 +17,25 @@
package org.apache.rocketmq.broker.plugin;
+import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.common.BrokerConfig;
import org.apache.rocketmq.store.MessageArrivingListener;
import org.apache.rocketmq.store.config.MessageStoreConfig;
import org.apache.rocketmq.store.stats.BrokerStatsManager;
public class MessageStorePluginContext {
+ private BrokerController controller;
private MessageStoreConfig messageStoreConfig;
private BrokerStatsManager brokerStatsManager;
private MessageArrivingListener messageArrivingListener;
- private BrokerConfig brokerConfig;
- public MessageStorePluginContext(MessageStoreConfig messageStoreConfig,
- BrokerStatsManager brokerStatsManager, MessageArrivingListener messageArrivingListener,
- BrokerConfig brokerConfig) {
+ public MessageStorePluginContext(BrokerController controller, MessageStoreConfig messageStoreConfig,
+ BrokerStatsManager brokerStatsManager, MessageArrivingListener messageArrivingListener) {
super();
this.messageStoreConfig = messageStoreConfig;
this.brokerStatsManager = brokerStatsManager;
this.messageArrivingListener = messageArrivingListener;
- this.brokerConfig = brokerConfig;
+ this.controller = controller;
}
public MessageStoreConfig getMessageStoreConfig() {
@@ -51,7 +51,11 @@ public class MessageStorePluginContext {
}
public BrokerConfig getBrokerConfig() {
- return brokerConfig;
+ return controller.getBrokerConfig();
+ }
+
+ public BrokerController getController() {
+ return controller;
}
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/plugin/PullMessageResultHandler.java b/broker/src/main/java/org/apache/rocketmq/broker/plugin/PullMessageResultHandler.java
new file mode 100644
index 0000000..3383a64
--- /dev/null
+++ b/broker/src/main/java/org/apache/rocketmq/broker/plugin/PullMessageResultHandler.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.rocketmq.broker.plugin;
+
+import io.netty.channel.Channel;
+import org.apache.rocketmq.common.protocol.header.PullMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData;
+import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
+import org.apache.rocketmq.remoting.protocol.RemotingCommand;
+import org.apache.rocketmq.store.GetMessageResult;
+import org.apache.rocketmq.store.MessageFilter;
+
+public interface PullMessageResultHandler {
+
+ /**
+ * Handle result of get message from store.
+ *
+ * @param getMessageResult store result
+ * @param request request
+ * @param requestHeader request header
+ * @param channel channel
+ * @param subscriptionData sub data
+ * @param subscriptionGroupConfig sub config
+ * @param brokerAllowSuspend brokerAllowSuspend
+ * @param messageFilter store message filter
+ * @param response response
+ * @return response or null
+ */
+ RemotingCommand handle(final GetMessageResult getMessageResult,
+ final RemotingCommand request,
+ final PullMessageRequestHeader requestHeader,
+ final Channel channel,
+ final SubscriptionData subscriptionData,
+ final SubscriptionGroupConfig subscriptionGroupConfig,
+ final boolean brokerAllowSuspend,
+ final MessageFilter messageFilter,
+ final RemotingCommand response);
+}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/AbstractSendMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/AbstractSendMessageProcessor.java
index 3303d70..1821239 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/AbstractSendMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/AbstractSendMessageProcessor.java
@@ -17,16 +17,26 @@
package org.apache.rocketmq.broker.processor;
import io.netty.channel.ChannelHandlerContext;
-import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.broker.mqtrace.AbortProcessException;
+import org.apache.rocketmq.broker.mqtrace.ConsumeMessageContext;
+import org.apache.rocketmq.broker.mqtrace.ConsumeMessageHook;
import org.apache.rocketmq.broker.mqtrace.SendMessageContext;
import org.apache.rocketmq.broker.mqtrace.SendMessageHook;
+import org.apache.rocketmq.common.BrokerConfig;
+import org.apache.rocketmq.common.MQVersion;
+import org.apache.rocketmq.common.UtilAll;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.message.MessageType;
+import org.apache.rocketmq.common.protocol.header.ConsumerSendMsgBackRequestHeader;
+import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.TopicConfig;
@@ -46,46 +56,315 @@ import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeaderV2;
import org.apache.rocketmq.common.protocol.header.SendMessageResponseHeader;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
import org.apache.rocketmq.common.sysflag.TopicSysFlag;
-import org.apache.rocketmq.common.utils.ChannelUtil;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
-import org.apache.rocketmq.remoting.netty.AsyncNettyRequestProcessor;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
+import org.apache.rocketmq.store.PutMessageResult;
+import org.apache.rocketmq.store.stats.BrokerStatsManager;
-public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProcessor implements NettyRequestProcessor {
- protected static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+public abstract class AbstractSendMessageProcessor implements NettyRequestProcessor {
+ protected static final InternalLogger LOGGER = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ protected static final InternalLogger DLQ_LOG = InternalLoggerFactory.getLogger(LoggerName.DLQ_LOGGER_NAME);
+
+ protected List<ConsumeMessageHook> consumeMessageHookList;
protected final static int DLQ_NUMS_PER_GROUP = 1;
- protected final BrokerController brokerController;
+ protected final Random random = new Random(System.currentTimeMillis());
protected final SocketAddress storeHost;
private List<SendMessageHook> sendMessageHookList;
+ protected final BrokerController brokerController;
+
public AbstractSendMessageProcessor(final BrokerController brokerController) {
this.brokerController = brokerController;
- this.storeHost =
- new InetSocketAddress(brokerController.getBrokerConfig().getBrokerIP1(), brokerController
- .getNettyServerConfig().getListenPort());
+ this.storeHost = brokerController.getStoreHost();
+ }
+
+ public void registerConsumeMessageHook(List<ConsumeMessageHook> consumeMessageHookList) {
+ this.consumeMessageHookList = consumeMessageHookList;
+ }
+
+ protected RemotingCommand consumerSendMsgBack(final ChannelHandlerContext ctx, final RemotingCommand request)
+ throws RemotingCommandException {
+ final RemotingCommand response = RemotingCommand.createResponseCommand(null);
+ final ConsumerSendMsgBackRequestHeader requestHeader =
+ (ConsumerSendMsgBackRequestHeader) request.decodeCommandCustomHeader(ConsumerSendMsgBackRequestHeader.class);
+
+ // The send back requests sent to SlaveBroker will be forwarded to the master broker beside
+ final BrokerController masterBroker = this.brokerController.peekMasterBroker();
+ if (null == masterBroker) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("no master available along with " + brokerController.getBrokerConfig().getBrokerIP1());
+ return response;
+ }
+
+ // The broker that received the request.
+ // It may be a master broker or a slave broker
+ final BrokerController currentBroker = this.brokerController;
+
+ SubscriptionGroupConfig subscriptionGroupConfig =
+ masterBroker.getSubscriptionGroupManager().findSubscriptionGroupConfig(requestHeader.getGroup());
+ if (null == subscriptionGroupConfig) {
+ response.setCode(ResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST);
+ response.setRemark("subscription group not exist, " + requestHeader.getGroup() + " "
+ + FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST));
+ return response;
+ }
+
+ BrokerConfig masterBrokerConfig = masterBroker.getBrokerConfig();
+ if (!PermName.isWriteable(masterBrokerConfig.getBrokerPermission())) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark("the broker[" + masterBrokerConfig.getBrokerIP1() + "] sending message is forbidden");
+ return response;
+ }
+
+ if (subscriptionGroupConfig.getRetryQueueNums() <= 0) {
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+ return response;
+ }
+
+ String newTopic = MixAll.getRetryTopic(requestHeader.getGroup());
+ int queueIdInt = Math.abs(this.random.nextInt() % 99999999) % subscriptionGroupConfig.getRetryQueueNums();
+
+ int topicSysFlag = 0;
+ if (requestHeader.isUnitMode()) {
+ topicSysFlag = TopicSysFlag.buildSysFlag(false, true);
+ }
+
+ // Create retry topic to master broker
+ TopicConfig topicConfig = masterBroker.getTopicConfigManager().createTopicInSendMessageBackMethod(
+ newTopic,
+ subscriptionGroupConfig.getRetryQueueNums(),
+ PermName.PERM_WRITE | PermName.PERM_READ, topicSysFlag);
+ if (null == topicConfig) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("topic[" + newTopic + "] not exist");
+ return response;
+ }
+
+ if (!PermName.isWriteable(topicConfig.getPerm())) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark(String.format("the topic[%s] sending message is forbidden", newTopic));
+ return response;
+ }
+
+ // Look message from the origin message store
+ MessageExt msgExt = currentBroker.getMessageStore().lookMessageByOffset(requestHeader.getOffset());
+ if (null == msgExt) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("look message by offset failed, " + requestHeader.getOffset());
+ return response;
+ }
+
+ //for logic queue
+ if (requestHeader.getOriginTopic() != null
+ && !msgExt.getTopic().equals(requestHeader.getOriginTopic())) {
+ //here just do some fence in case of some unexpected offset is income
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("look message by offset failed to check the topic name" + requestHeader.getOffset());
+ return response;
+ }
+
+ final String retryTopic = msgExt.getProperty(MessageConst.PROPERTY_RETRY_TOPIC);
+ if (null == retryTopic) {
+ MessageAccessor.putProperty(msgExt, MessageConst.PROPERTY_RETRY_TOPIC, msgExt.getTopic());
+ }
+ msgExt.setWaitStoreMsgOK(false);
+
+ int delayLevel = requestHeader.getDelayLevel();
+
+ int maxReconsumeTimes = subscriptionGroupConfig.getRetryMaxTimes();
+ if (request.getVersion() >= MQVersion.Version.V3_4_9.ordinal()) {
+ Integer times = requestHeader.getMaxReconsumeTimes();
+ if (times != null) {
+ maxReconsumeTimes = times;
+ }
+ }
+
+ boolean isDLQ = false;
+ if (msgExt.getReconsumeTimes() >= maxReconsumeTimes
+ || delayLevel < 0) {
+
+ isDLQ = true;
+ newTopic = MixAll.getDLQTopic(requestHeader.getGroup());
+ queueIdInt = randomQueueId(DLQ_NUMS_PER_GROUP);
+
+ // Create DLQ topic to master broker
+ topicConfig = masterBroker.getTopicConfigManager().createTopicInSendMessageBackMethod(newTopic,
+ DLQ_NUMS_PER_GROUP,
+ PermName.PERM_WRITE | PermName.PERM_READ, 0);
+
+ if (null == topicConfig) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("topic[" + newTopic + "] not exist");
+ return response;
+ }
+ msgExt.setDelayTimeLevel(0);
+ } else {
+ if (0 == delayLevel) {
+ delayLevel = 3 + msgExt.getReconsumeTimes();
+ }
+
+ msgExt.setDelayTimeLevel(delayLevel);
+ }
+
+ MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
+ msgInner.setTopic(newTopic);
+ msgInner.setBody(msgExt.getBody());
+ msgInner.setFlag(msgExt.getFlag());
+ MessageAccessor.setProperties(msgInner, msgExt.getProperties());
+ msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgExt.getProperties()));
+ msgInner.setTagsCode(MessageExtBrokerInner.tagsString2tagsCode(null, msgExt.getTags()));
+
+ msgInner.setQueueId(queueIdInt);
+ msgInner.setSysFlag(msgExt.getSysFlag());
+ msgInner.setBornTimestamp(msgExt.getBornTimestamp());
+ msgInner.setBornHost(msgExt.getBornHost());
+ msgInner.setStoreHost(this.getStoreHost());
+ msgInner.setReconsumeTimes(msgExt.getReconsumeTimes() + 1);
+
+ String originMsgId = MessageAccessor.getOriginMessageId(msgExt);
+ MessageAccessor.setOriginMessageId(msgInner, UtilAll.isBlank(originMsgId) ? msgExt.getMsgId() : originMsgId);
+ msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgExt.getProperties()));
+
+ boolean succeeded = false;
+
+ // Put retry topic to master message store
+ PutMessageResult putMessageResult = masterBroker.getMessageStore().putMessage(msgInner);
+ if (putMessageResult != null) {
+ String commercialOwner = request.getExtFields().get(BrokerStatsManager.COMMERCIAL_OWNER);
+
+ switch (putMessageResult.getPutMessageStatus()) {
+ case PUT_OK:
+ String backTopic = msgExt.getTopic();
+ String correctTopic = msgExt.getProperty(MessageConst.PROPERTY_RETRY_TOPIC);
+ if (correctTopic != null) {
+ backTopic = correctTopic;
+ }
+ if (TopicValidator.RMQ_SYS_SCHEDULE_TOPIC.equals(msgInner.getTopic())) {
+ masterBroker.getBrokerStatsManager().incTopicPutNums(msgInner.getTopic());
+ masterBroker.getBrokerStatsManager().incTopicPutSize(msgInner.getTopic(), putMessageResult.getAppendMessageResult().getWroteBytes());
+ masterBroker.getBrokerStatsManager().incQueuePutNums(msgInner.getTopic(), msgInner.getQueueId());
+ masterBroker.getBrokerStatsManager().incQueuePutSize(msgInner.getTopic(), msgInner.getQueueId(), putMessageResult.getAppendMessageResult().getWroteBytes());
+ }
+ masterBroker.getBrokerStatsManager().incSendBackNums(requestHeader.getGroup(), backTopic);
+
+ if (isDLQ) {
+ masterBroker.getBrokerStatsManager().incDLQStatValue(
+ BrokerStatsManager.SNDBCK2DLQ_TIMES,
+ commercialOwner,
+ requestHeader.getGroup(),
+ requestHeader.getOriginTopic(),
+ BrokerStatsManager.StatsType.SEND_BACK_TO_DLQ.name(),
+ 1);
+
+ String uniqKey = msgInner.getProperties().get(MessageConst.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX);
+ DLQ_LOG.info("send msg to DLQ {}, owner={}, originalTopic={}, consumerId={}, msgUniqKey={}, storeTimestamp={}",
+ newTopic,
+ commercialOwner,
+ requestHeader.getOriginTopic(),
+ requestHeader.getGroup(),
+ uniqKey,
+ putMessageResult.getAppendMessageResult().getStoreTimestamp());
+ }
+
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+
+ succeeded = true;
+ break;
+ default:
+ break;
+ }
+
+ if (!succeeded) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark(putMessageResult.getPutMessageStatus().name());
+ }
+ } else {
+ if (isDLQ) {
+ String owner = request.getExtFields().get(BrokerStatsManager.COMMERCIAL_OWNER);
+ String uniqKey = msgInner.getProperties().get(MessageConst.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX);
+ DLQ_LOG.info("failed to send msg to DLQ {}, owner={}, originalTopic={}, consumerId={}, msgUniqKey={}, result={}",
+ newTopic,
+ owner,
+ requestHeader.getOriginTopic(),
+ requestHeader.getGroup(),
+ uniqKey,
+ putMessageResult == null ? "null" : putMessageResult.getPutMessageStatus().toString());
+ }
+
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("putMessageResult is null");
+ }
+
+ if (this.hasConsumeMessageHook() && !UtilAll.isBlank(requestHeader.getOriginMsgId())) {
+ String namespace = NamespaceUtil.getNamespaceFromResource(requestHeader.getGroup());
+ ConsumeMessageContext context = new ConsumeMessageContext();
+ context.setNamespace(namespace);
+ context.setTopic(requestHeader.getOriginTopic());
+ context.setConsumerGroup(requestHeader.getGroup());
+ context.setCommercialRcvStats(BrokerStatsManager.StatsType.SEND_BACK);
+ context.setCommercialRcvTimes(1);
+ context.setCommercialOwner(request.getExtFields().get(BrokerStatsManager.COMMERCIAL_OWNER));
+
+ context.setAccountAuthType(request.getExtFields().get(BrokerStatsManager.ACCOUNT_AUTH_TYPE));
+ context.setAccountOwnerParent(request.getExtFields().get(BrokerStatsManager.ACCOUNT_OWNER_PARENT));
+ context.setAccountOwnerSelf(request.getExtFields().get(BrokerStatsManager.ACCOUNT_OWNER_SELF));
+ context.setRcvStat(isDLQ ? BrokerStatsManager.StatsType.SEND_BACK_TO_DLQ : BrokerStatsManager.StatsType.SEND_BACK);
+ context.setSuccess(succeeded);
+ context.setRcvMsgNum(1);
+ //Set msg body size 0 when sent back by consumer.
+ context.setRcvMsgSize(0);
+ context.setCommercialRcvMsgNum(succeeded ? 1 : 0);
+
+ try {
+ this.executeConsumeMessageHookAfter(context);
+ } catch (AbortProcessException e) {
+ response.setCode(e.getResponseCode());
+ response.setRemark(e.getErrorMessage());
+ }
+ }
+
+ return response;
+ }
+
+ public boolean hasConsumeMessageHook() {
+ return consumeMessageHookList != null && !this.consumeMessageHookList.isEmpty();
+ }
+
+ public void executeConsumeMessageHookAfter(final ConsumeMessageContext context) {
+ if (hasConsumeMessageHook()) {
+ for (ConsumeMessageHook hook : this.consumeMessageHookList) {
+ try {
+ hook.consumeMessageAfter(context);
+ } catch (Throwable e) {
+ // Ignore
+ }
+ }
+ }
}
protected SendMessageContext buildMsgContext(ChannelHandlerContext ctx,
SendMessageRequestHeader requestHeader) {
- if (!this.hasSendMessageHook()) {
- return null;
- }
String namespace = NamespaceUtil.getNamespaceFromResource(requestHeader.getTopic());
- SendMessageContext mqtraceContext = new SendMessageContext();
- mqtraceContext.setProducerGroup(requestHeader.getProducerGroup());
- mqtraceContext.setNamespace(namespace);
- mqtraceContext.setTopic(requestHeader.getTopic());
- mqtraceContext.setMsgProps(requestHeader.getProperties());
- mqtraceContext.setBornHost(RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
- mqtraceContext.setBrokerAddr(this.brokerController.getBrokerAddr());
- mqtraceContext.setBrokerRegionId(this.brokerController.getBrokerConfig().getRegionId());
- mqtraceContext.setBornTimeStamp(requestHeader.getBornTimestamp());
+
+ SendMessageContext traceContext;
+ traceContext = new SendMessageContext();
+ traceContext.setNamespace(namespace);
+ traceContext.setProducerGroup(requestHeader.getProducerGroup());
+ traceContext.setTopic(requestHeader.getTopic());
+ traceContext.setMsgProps(requestHeader.getProperties());
+ traceContext.setBornHost(RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
+ traceContext.setBrokerAddr(this.brokerController.getBrokerAddr());
+ traceContext.setBrokerRegionId(this.brokerController.getBrokerConfig().getRegionId());
+ traceContext.setBornTimeStamp(requestHeader.getBornTimestamp());
+ traceContext.setRequestTimeStamp(System.currentTimeMillis());
Map<String, String> properties = MessageDecoder.string2messageProperties(requestHeader.getProperties());
String uniqueKey = properties.get(MessageConst.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX);
@@ -96,8 +375,14 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
if (uniqueKey == null) {
uniqueKey = "";
}
- mqtraceContext.setMsgUniqueKey(uniqueKey);
- return mqtraceContext;
+ traceContext.setMsgUniqueKey(uniqueKey);
+
+ if (properties.containsKey(MessageConst.PROPERTY_SHARDING_KEY)) {
+ traceContext.setMsgType(MessageType.Order_Msg);
+ } else {
+ traceContext.setMsgType(MessageType.Normal_Msg);
+ }
+ return traceContext;
}
public boolean hasSendMessageHook() {
@@ -108,7 +393,7 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
final SendMessageRequestHeader requestHeader, final byte[] body, TopicConfig topicConfig) {
int queueIdInt = requestHeader.getQueueId();
if (queueIdInt < 0) {
- queueIdInt = ThreadLocalRandom.current().nextInt(99999999) % topicConfig.getWriteQueueNums();
+ queueIdInt = randomQueueId(topicConfig.getWriteQueueNums());
}
int sysFlag = requestHeader.getSysFlag();
@@ -143,19 +428,24 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
protected RemotingCommand msgContentCheck(final ChannelHandlerContext ctx,
final SendMessageRequestHeader requestHeader, RemotingCommand request,
final RemotingCommand response) {
- if (requestHeader.getTopic().length() > Byte.MAX_VALUE) {
- log.warn("putMessage message topic length too long {}", requestHeader.getTopic().length());
+ String topic = requestHeader.getTopic();
+ if (topic.length() > Byte.MAX_VALUE) {
+ LOGGER.warn("msgContentCheck: message topic length is too long, topic={}, topic length={}, threshold={}",
+ topic, topic.length(), Byte.MAX_VALUE);
response.setCode(ResponseCode.MESSAGE_ILLEGAL);
return response;
}
if (requestHeader.getProperties() != null && requestHeader.getProperties().length() > Short.MAX_VALUE) {
- log.warn("putMessage message properties length too long {}", requestHeader.getProperties().length());
+ LOGGER.warn(
+ "msgContentCheck: message properties length is too long, topic={}, properties length={}, threshold={}",
+ topic, requestHeader.getProperties().length(), Short.MAX_VALUE);
response.setCode(ResponseCode.MESSAGE_ILLEGAL);
return response;
}
if (request.getBody().length > DBMsgConstants.MAX_BODY_SIZE) {
- log.warn(" topic {} msg body size {} from {}", requestHeader.getTopic(),
- request.getBody().length, ChannelUtil.getRemoteIp(ctx.channel()));
+ LOGGER.warn(
+ "msgContentCheck: message body size exceeds the threshold, topic={}, body size={}, threshold={}bytes",
+ topic, request.getBody().length, DBMsgConstants.MAX_BODY_SIZE);
response.setRemark("msg body must be less 64KB");
response.setCode(ResponseCode.MESSAGE_ILLEGAL);
return response;
@@ -164,7 +454,8 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
}
protected RemotingCommand msgCheck(final ChannelHandlerContext ctx,
- final SendMessageRequestHeader requestHeader, final RemotingCommand response) {
+ final SendMessageRequestHeader requestHeader, final RemotingCommand request,
+ final RemotingCommand response) {
if (!PermName.isWriteable(this.brokerController.getBrokerConfig().getBrokerPermission())
&& this.brokerController.getTopicConfigManager().isOrderTopic(requestHeader.getTopic())) {
response.setCode(ResponseCode.NO_PERMISSION);
@@ -192,7 +483,7 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
}
}
- log.warn("the topic {} not exist, producer: {}", requestHeader.getTopic(), ctx.channel().remoteAddress());
+ LOGGER.warn("the topic {} not exist, producer: {}", requestHeader.getTopic(), ctx.channel().remoteAddress());
topicConfig = this.brokerController.getTopicConfigManager().createTopicInSendMessageMethod(
requestHeader.getTopic(),
requestHeader.getDefaultTopic(),
@@ -224,7 +515,7 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
topicConfig.toString(),
RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
- log.warn(errorInfo);
+ LOGGER.warn(errorInfo);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark(errorInfo);
@@ -243,9 +534,10 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
try {
ctx.writeAndFlush(response);
} catch (Throwable e) {
- log.error("SendMessageProcessor process request over, but response failed", e);
- log.error(request.toString());
- log.error(response.toString());
+ LOGGER.error(
+ "SendMessageProcessor finished processing the request, but failed to send response, client "
+ + "address={}, request={}, response={}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()),
+ request.toString(), response.toString(), e);
}
}
}
@@ -257,8 +549,8 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
try {
final SendMessageRequestHeader requestHeader = parseRequestHeader(request);
+ String namespace = NamespaceUtil.getNamespaceFromResource(requestHeader.getTopic());
if (null != requestHeader) {
- String namespace = NamespaceUtil.getNamespaceFromResource(requestHeader.getTopic());
context.setNamespace(namespace);
context.setProducerGroup(requestHeader.getProducerGroup());
context.setTopic(requestHeader.getTopic());
@@ -273,8 +565,10 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
if (requestHeader != null) {
requestHeader.setProperties(context.getMsgProps());
}
+ } catch (AbortProcessException e) {
+ throw e;
} catch (Throwable e) {
- // Ignore
+ //ignore
}
}
}
@@ -304,7 +598,7 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
}
static SendMessageRequestHeaderV2 decodeSendMessageHeaderV2(RemotingCommand request)
- throws RemotingCommandException {
+ throws RemotingCommandException {
SendMessageRequestHeaderV2 r = new SendMessageRequestHeaderV2();
HashMap<String, String> fields = request.getExtFields();
if (fields == null) {
@@ -376,6 +670,10 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
}
}
+ protected int randomQueueId(int writeQueueNums) {
+ return ThreadLocalRandom.current().nextInt(99999999) % writeQueueNums;
+ }
+
public void executeSendMessageHookAfter(final RemotingCommand response, final SendMessageContext context) {
if (hasSendMessageHook()) {
for (SendMessageHook hook : this.sendMessageHookList) {
@@ -391,7 +689,7 @@ public abstract class AbstractSendMessageProcessor extends AsyncNettyRequestProc
}
hook.sendMessageAfter(context);
} catch (Throwable e) {
- // Ignore
+ //ignore
}
}
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/AckMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/AckMessageProcessor.java
index 29f7507..9c7dbc4 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/AckMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/AckMessageProcessor.java
@@ -38,7 +38,7 @@ import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
import org.apache.rocketmq.store.PutMessageResult;
import org.apache.rocketmq.store.PutMessageStatus;
import org.apache.rocketmq.store.pop.AckMsg;
@@ -51,36 +51,54 @@ public class AckMessageProcessor implements NettyRequestProcessor {
public AckMessageProcessor(final BrokerController brokerController) {
this.brokerController = brokerController;
- this.reviveTopic = PopAckConstants.REVIVE_TOPIC + this.brokerController.getBrokerConfig().getBrokerClusterName();
+ this.reviveTopic = PopAckConstants.buildClusterReviveTopic(this.brokerController.getBrokerConfig().getBrokerClusterName());
this.popReviveServices = new PopReviveService[this.brokerController.getBrokerConfig().getReviveQueueNum()];
for (int i = 0; i < this.brokerController.getBrokerConfig().getReviveQueueNum(); i++) {
- this.popReviveServices[i] = new PopReviveService(i, brokerController, reviveTopic);
+ this.popReviveServices[i] = new PopReviveService(brokerController, reviveTopic, i);
+ this.popReviveServices[i].setShouldRunPopRevive(brokerController.getBrokerConfig().getBrokerId() == 0);
}
}
- @Override
- public RemotingCommand processRequest(final ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
- return this.processRequest(ctx.channel(), request, true);
+ public void startPopReviveService() {
+ for (PopReviveService popReviveService : popReviveServices) {
+ popReviveService.start();
+ }
}
- @Override
- public boolean rejectRequest() {
- return false;
+ public void shutdownPopReviveService() {
+ for (PopReviveService popReviveService : popReviveServices) {
+ popReviveService.stop();
+ }
}
- public void startPopReviveService() {
+ public void setPopReviveServiceStatus(boolean shouldStart) {
for (PopReviveService popReviveService : popReviveServices) {
- popReviveService.start();
+ popReviveService.setShouldRunPopRevive(shouldStart);
}
}
- public void shutdownPopReviveService() {
+ public boolean isPopReviveServiceRunning() {
for (PopReviveService popReviveService : popReviveServices) {
- popReviveService.shutdown();
+ if (popReviveService.isShouldRunPopRevive()) {
+ return true;
+ }
}
+
+ return false;
+ }
+
+ @Override
+ public RemotingCommand processRequest(final ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ return this.processRequest(ctx.channel(), request, true);
}
- private RemotingCommand processRequest(final Channel channel, RemotingCommand request, boolean brokerAllowSuspend) throws RemotingCommandException {
+ @Override public boolean rejectRequest() {
+ return false;
+ }
+
+ private RemotingCommand processRequest(final Channel channel, RemotingCommand request,
+ boolean brokerAllowSuspend) throws RemotingCommandException {
final AckMessageRequestHeader requestHeader = (AckMessageRequestHeader) request.decodeCommandCustomHeader(AckMessageRequestHeader.class);
MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
AckMsg ackMsg = new AckMsg();
@@ -105,7 +123,11 @@ public class AckMessageProcessor implements NettyRequestProcessor {
long minOffset = this.brokerController.getMessageStore().getMinOffsetInQueue(requestHeader.getTopic(), requestHeader.getQueueId());
long maxOffset = this.brokerController.getMessageStore().getMaxOffsetInQueue(requestHeader.getTopic(), requestHeader.getQueueId());
if (requestHeader.getOffset() < minOffset || requestHeader.getOffset() > maxOffset) {
+ String errorInfo = String.format("offset is illegal, key:%s@%d, commit:%d, store:%d~%d",
+ requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getOffset(), minOffset, maxOffset);
+ POP_LOGGER.warn(errorInfo);
response.setCode(ResponseCode.NO_MESSAGE);
+ response.setRemark(errorInfo);
return response;
}
String[] extraInfo = ExtraInfoUtil.split(requestHeader.getExtraInfo());
@@ -116,15 +138,19 @@ public class AckMessageProcessor implements NettyRequestProcessor {
ackMsg.setTopic(requestHeader.getTopic());
ackMsg.setQueueId(requestHeader.getQueueId());
ackMsg.setPopTime(ExtraInfoUtil.getPopTime(extraInfo));
+ ackMsg.setBrokerName(ExtraInfoUtil.getBrokerName(extraInfo));
int rqId = ExtraInfoUtil.getReviveQid(extraInfo);
+ this.brokerController.getBrokerStatsManager().incBrokerAckNums(1);
+ this.brokerController.getBrokerStatsManager().incGroupAckNums(requestHeader.getConsumerGroup(), requestHeader.getTopic(), 1);
+
if (rqId == KeyBuilder.POP_ORDER_REVIVE_QUEUE) {
// order
String lockKey = requestHeader.getTopic() + PopAckConstants.SPLIT
- + requestHeader.getConsumerGroup() + PopAckConstants.SPLIT + requestHeader.getQueueId();
+ + requestHeader.getConsumerGroup() + PopAckConstants.SPLIT + requestHeader.getQueueId();
long oldOffset = this.brokerController.getConsumerOffsetManager().queryOffset(requestHeader.getConsumerGroup(),
- requestHeader.getTopic(), requestHeader.getQueueId());
+ requestHeader.getTopic(), requestHeader.getQueueId());
if (requestHeader.getOffset() < oldOffset) {
return response;
}
@@ -137,18 +163,18 @@ public class AckMessageProcessor implements NettyRequestProcessor {
return response;
}
long nextOffset = brokerController.getConsumerOrderInfoManager().commitAndNext(
- requestHeader.getTopic(), requestHeader.getConsumerGroup(),
- requestHeader.getQueueId(), requestHeader.getOffset());
+ requestHeader.getTopic(), requestHeader.getConsumerGroup(),
+ requestHeader.getQueueId(), requestHeader.getOffset());
if (nextOffset > -1) {
this.brokerController.getConsumerOffsetManager().commitOffset(channel.remoteAddress().toString(),
- requestHeader.getConsumerGroup(), requestHeader.getTopic(),
- requestHeader.getQueueId(),
- nextOffset);
+ requestHeader.getConsumerGroup(), requestHeader.getTopic(),
+ requestHeader.getQueueId(),
+ nextOffset);
this.brokerController.getPopMessageProcessor().notifyMessageArriving(requestHeader.getTopic(), requestHeader.getConsumerGroup(),
- requestHeader.getQueueId());
+ requestHeader.getQueueId());
} else if (nextOffset == -1) {
String errorInfo = String.format("offset is illegal, key:%s, old:%d, commit:%d, next:%d, %s",
- lockKey, oldOffset, requestHeader.getOffset(), nextOffset, channel.remoteAddress());
+ lockKey, oldOffset, requestHeader.getOffset(), nextOffset, channel.remoteAddress());
POP_LOGGER.warn(errorInfo);
response.setCode(ResponseCode.MESSAGE_ILLEGAL);
response.setRemark(errorInfo);
@@ -175,7 +201,7 @@ public class AckMessageProcessor implements NettyRequestProcessor {
MsgUtil.setMessageDeliverTime(this.brokerController, msgInner, ExtraInfoUtil.getPopTime(extraInfo) + ExtraInfoUtil.getInvisibleTime(extraInfo));
msgInner.getProperties().put(MessageConst.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX, PopMessageProcessor.genAckUniqueId(ackMsg));
msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgInner.getProperties()));
- PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner);
+ PutMessageResult putMessageResult = this.brokerController.getEscapeBridge().putMessageToSpecificQueue(msgInner);
if (putMessageResult.getPutMessageStatus() != PutMessageStatus.PUT_OK
&& putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_DISK_TIMEOUT
&& putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_SLAVE_TIMEOUT
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java
index 4606480..a283228 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java
@@ -20,6 +20,10 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.acl.AccessValidator;
import org.apache.rocketmq.acl.plain.PlainAccessValidator;
import org.apache.rocketmq.broker.BrokerController;
@@ -27,20 +31,25 @@ import org.apache.rocketmq.broker.client.ClientChannelInfo;
import org.apache.rocketmq.broker.client.ConsumerGroupInfo;
import org.apache.rocketmq.broker.filter.ConsumerFilterData;
import org.apache.rocketmq.broker.filter.ExpressionMessageFilter;
+import org.apache.rocketmq.broker.plugin.BrokerAttachedPlugin;
+import org.apache.rocketmq.broker.subscription.SubscriptionGroupManager;
import org.apache.rocketmq.broker.transaction.queue.TransactionalMessageUtil;
import org.apache.rocketmq.common.AclConfig;
-import org.apache.rocketmq.common.BrokerConfig;
+import org.apache.rocketmq.common.LockCallback;
import org.apache.rocketmq.common.MQVersion;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.PlainAccessConfig;
import org.apache.rocketmq.common.TopicConfig;
+import org.apache.rocketmq.common.UnlockCallback;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.admin.ConsumeStats;
import org.apache.rocketmq.common.admin.OffsetWrapper;
import org.apache.rocketmq.common.admin.TopicOffset;
import org.apache.rocketmq.common.admin.TopicStatsTable;
import org.apache.rocketmq.common.attribute.AttributeParser;
+import org.apache.rocketmq.common.constant.ConsumeInitMode;
import org.apache.rocketmq.common.constant.LoggerName;
+import org.apache.rocketmq.common.constant.PermName;
import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageDecoder;
@@ -49,6 +58,7 @@ import org.apache.rocketmq.common.message.MessageId;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.protocol.body.BrokerMemberGroup;
import org.apache.rocketmq.common.protocol.body.BrokerStatsData;
import org.apache.rocketmq.common.protocol.body.BrokerStatsItem;
import org.apache.rocketmq.common.protocol.body.Connection;
@@ -56,6 +66,7 @@ import org.apache.rocketmq.common.protocol.body.ConsumeQueueData;
import org.apache.rocketmq.common.protocol.body.ConsumeStatsList;
import org.apache.rocketmq.common.protocol.body.ConsumerConnection;
import org.apache.rocketmq.common.protocol.body.GroupList;
+import org.apache.rocketmq.common.protocol.body.HARuntimeInfo;
import org.apache.rocketmq.common.protocol.body.KVTable;
import org.apache.rocketmq.common.protocol.body.LockBatchRequestBody;
import org.apache.rocketmq.common.protocol.body.LockBatchResponseBody;
@@ -63,6 +74,7 @@ import org.apache.rocketmq.common.protocol.body.ProducerConnection;
import org.apache.rocketmq.common.protocol.body.QueryConsumeQueueResponseBody;
import org.apache.rocketmq.common.protocol.body.QueryConsumeTimeSpanBody;
import org.apache.rocketmq.common.protocol.body.QueryCorrectionOffsetBody;
+import org.apache.rocketmq.common.protocol.body.QuerySubscriptionResponseBody;
import org.apache.rocketmq.common.protocol.body.QueueTimeSpan;
import org.apache.rocketmq.common.protocol.body.TopicConfigAndMappingSerializeWrapper;
import org.apache.rocketmq.common.protocol.body.TopicList;
@@ -74,6 +86,8 @@ import org.apache.rocketmq.common.protocol.header.CreateTopicRequestHeader;
import org.apache.rocketmq.common.protocol.header.DeleteAccessConfigRequestHeader;
import org.apache.rocketmq.common.protocol.header.DeleteSubscriptionGroupRequestHeader;
import org.apache.rocketmq.common.protocol.header.DeleteTopicRequestHeader;
+import org.apache.rocketmq.common.protocol.header.ExchangeHAInfoRequestHeader;
+import org.apache.rocketmq.common.protocol.header.ExchangeHAInfoResponseHeader;
import org.apache.rocketmq.common.protocol.header.GetAllTopicConfigResponseHeader;
import org.apache.rocketmq.common.protocol.header.GetBrokerAclConfigResponseHeader;
import org.apache.rocketmq.common.protocol.header.GetBrokerClusterAclConfigResponseBody;
@@ -91,22 +105,27 @@ import org.apache.rocketmq.common.protocol.header.GetMaxOffsetResponseHeader;
import org.apache.rocketmq.common.protocol.header.GetMinOffsetRequestHeader;
import org.apache.rocketmq.common.protocol.header.GetMinOffsetResponseHeader;
import org.apache.rocketmq.common.protocol.header.GetProducerConnectionListRequestHeader;
+import org.apache.rocketmq.common.protocol.header.GetSubscriptionGroupConfigRequestHeader;
import org.apache.rocketmq.common.protocol.header.GetTopicConfigRequestHeader;
import org.apache.rocketmq.common.protocol.header.GetTopicStatsInfoRequestHeader;
+import org.apache.rocketmq.common.protocol.header.NotifyMinBrokerIdChangeRequestHeader;
import org.apache.rocketmq.common.protocol.header.QueryConsumeQueueRequestHeader;
import org.apache.rocketmq.common.protocol.header.QueryConsumeTimeSpanRequestHeader;
import org.apache.rocketmq.common.protocol.header.QueryCorrectionOffsetHeader;
+import org.apache.rocketmq.common.protocol.header.QuerySubscriptionByConsumerRequestHeader;
import org.apache.rocketmq.common.protocol.header.QueryTopicConsumeByWhoRequestHeader;
+import org.apache.rocketmq.common.protocol.header.QueryTopicsByConsumerRequestHeader;
+import org.apache.rocketmq.common.protocol.header.ResetMasterFlushOffsetHeader;
import org.apache.rocketmq.common.protocol.header.ResetOffsetRequestHeader;
import org.apache.rocketmq.common.protocol.header.ResumeCheckHalfMessageRequestHeader;
import org.apache.rocketmq.common.protocol.header.SearchOffsetRequestHeader;
import org.apache.rocketmq.common.protocol.header.SearchOffsetResponseHeader;
import org.apache.rocketmq.common.protocol.header.UpdateGlobalWhiteAddrsConfigRequestHeader;
+import org.apache.rocketmq.common.protocol.header.UpdateGroupForbiddenRequestHeader;
import org.apache.rocketmq.common.protocol.header.ViewBrokerStatsDataRequestHeader;
import org.apache.rocketmq.common.protocol.header.filtersrv.RegisterFilterServerRequestHeader;
import org.apache.rocketmq.common.protocol.header.filtersrv.RegisterFilterServerResponseHeader;
import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData;
-import org.apache.rocketmq.common.rpc.RpcClient;
import org.apache.rocketmq.common.rpc.RpcClientUtils;
import org.apache.rocketmq.common.rpc.RpcException;
import org.apache.rocketmq.common.rpc.RpcRequest;
@@ -118,6 +137,7 @@ import org.apache.rocketmq.common.statictopic.TopicQueueMappingDetail;
import org.apache.rocketmq.common.statictopic.TopicQueueMappingUtils;
import org.apache.rocketmq.common.stats.StatsItem;
import org.apache.rocketmq.common.stats.StatsSnapshot;
+import org.apache.rocketmq.common.subscription.GroupForbidden;
import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
import org.apache.rocketmq.common.topic.TopicValidator;
import org.apache.rocketmq.filter.util.BitsArray;
@@ -126,15 +146,13 @@ import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
-import org.apache.rocketmq.remoting.netty.AsyncNettyRequestProcessor;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.LanguageCode;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.remoting.protocol.RemotingSerializable;
import org.apache.rocketmq.remoting.protocol.RemotingSysResponseCode;
import org.apache.rocketmq.store.ConsumeQueueExt;
-import org.apache.rocketmq.store.DefaultMessageStore;
-import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
import org.apache.rocketmq.store.MessageFilter;
import org.apache.rocketmq.store.MessageStore;
import org.apache.rocketmq.store.PutMessageResult;
@@ -159,16 +177,12 @@ import java.util.concurrent.ConcurrentMap;
import static org.apache.rocketmq.remoting.protocol.RemotingCommand.buildErrorResponse;
-public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements NettyRequestProcessor {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
- private final BrokerController brokerController;
- private final RpcClient rpcClient;
- private final BrokerConfig brokerConfig;
+public class AdminBrokerProcessor implements NettyRequestProcessor {
+ private static final InternalLogger LOGGER = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ protected final BrokerController brokerController;
public AdminBrokerProcessor(final BrokerController brokerController) {
this.brokerController = brokerController;
- this.brokerConfig = brokerController.getBrokerConfig();
- this.rpcClient = brokerController.getBrokerOuterAPI().getRpcClient();
}
@Override
@@ -223,6 +237,10 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return this.getConsumerStatus(ctx, request);
case RequestCode.QUERY_TOPIC_CONSUME_BY_WHO:
return this.queryTopicConsumeByWho(ctx, request);
+ case RequestCode.QUERY_TOPICS_BY_CONSUMER:
+ return this.queryTopicsByConsumer(ctx, request);
+ case RequestCode.QUERY_SUBSCRIPTION_BY_CONSUMER:
+ return this.querySubscriptionByConsumer(ctx, request);
case RequestCode.REGISTER_FILTER_SERVER:
return this.registerFilterServer(ctx, request);
case RequestCode.QUERY_CONSUME_TIME_SPAN:
@@ -247,6 +265,10 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return fetchAllConsumeStatsInBroker(ctx, request);
case RequestCode.QUERY_CONSUME_QUEUE:
return queryConsumeQueue(ctx, request);
+ case RequestCode.UPDATE_AND_GET_GROUP_FORBIDDEN:
+ return this.updateAndGetGroupForbidden(ctx, request);
+ case RequestCode.GET_SUBSCRIPTIONGROUP_CONFIG:
+ return this.getSubscriptionGroup(ctx, request);
case RequestCode.UPDATE_AND_CREATE_ACL_CONFIG:
return updateAndCreateAccessConfig(ctx, request);
case RequestCode.DELETE_ACL_CONFIG:
@@ -263,11 +285,83 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return getTopicConfig(ctx, request);
case RequestCode.UPDATE_AND_CREATE_STATIC_TOPIC:
return this.updateAndCreateStaticTopic(ctx, request);
+ case RequestCode.NOTIFY_MIN_BROKER_ID_CHANGE:
+ return this.notifyMinBrokerIdChange(ctx, request);
+ case RequestCode.EXCHANGE_BROKER_HA_INFO:
+ return this.updateBrokerHaInfo(ctx, request);
+ case RequestCode.GET_BROKER_HA_STATUS:
+ return this.getBrokerHaStatus(ctx, request);
+ case RequestCode.RESET_MASTER_FLUSH_OFFSET:
+ return this.resetMasterFlushOffset(ctx, request);
default:
return getUnknownCmdResponse(ctx, request);
}
}
+ /**
+ * @param ctx
+ * @param request
+ * @return
+ * @throws RemotingCommandException
+ */
+ private RemotingCommand getSubscriptionGroup(ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ GetSubscriptionGroupConfigRequestHeader requestHeader = (GetSubscriptionGroupConfigRequestHeader) request.decodeCommandCustomHeader(GetSubscriptionGroupConfigRequestHeader.class);
+ final RemotingCommand response = RemotingCommand.createResponseCommand(null);
+
+ SubscriptionGroupConfig groupConfig = this.brokerController.getSubscriptionGroupManager().getSubscriptionGroupTable().get(requestHeader.getGroup());
+ if (groupConfig == null) {
+ LOGGER.error("No group in this broker, client: {} group: {}", ctx.channel().remoteAddress(), requestHeader.getGroup());
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("No group in this broker");
+ return response;
+ }
+ String content = JSONObject.toJSONString(groupConfig);
+ try {
+ response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET));
+ } catch (UnsupportedEncodingException e) {
+ LOGGER.error("UnsupportedEncodingException getSubscriptionGroup: group=" + groupConfig.getGroupName(), e);
+
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("UnsupportedEncodingException " + e.getMessage());
+ return response;
+ }
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+
+ return response;
+ }
+
+ /**
+ * @param ctx
+ * @param request
+ * @return
+ */
+ private RemotingCommand updateAndGetGroupForbidden(ChannelHandlerContext ctx, RemotingCommand request)
+ throws RemotingCommandException {
+ final RemotingCommand response = RemotingCommand.createResponseCommand(null);
+ UpdateGroupForbiddenRequestHeader requestHeader = (UpdateGroupForbiddenRequestHeader) //
+ request.decodeCommandCustomHeader(UpdateGroupForbiddenRequestHeader.class);
+ String group = requestHeader.getGroup();
+ String topic = requestHeader.getTopic();
+ LOGGER.info("updateAndGetGroupForbidden called by {} for object {}@{} readable={}",//
+ RemotingHelper.parseChannelRemoteAddr(ctx.channel()), group, //
+ topic, requestHeader.getReadable());
+ SubscriptionGroupManager groupManager = this.brokerController.getSubscriptionGroupManager();
+ if (requestHeader.getReadable() != null) {
+ groupManager.updateForbidden(group, topic, PermName.INDEX_PERM_READ, !requestHeader.getReadable());
+ }
+
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark("");
+ GroupForbidden groupForbidden = new GroupForbidden();
+ groupForbidden.setGroup(group);
+ groupForbidden.setTopic(topic);
+ groupForbidden.setReadable(!groupManager.getForbidden(group, topic, PermName.INDEX_PERM_READ));
+ response.setBody(groupForbidden.toJson().getBytes());
+ return response;
+ }
+
@Override
public boolean rejectRequest() {
return false;
@@ -278,7 +372,9 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
final CreateTopicRequestHeader requestHeader =
(CreateTopicRequestHeader) request.decodeCommandCustomHeader(CreateTopicRequestHeader.class);
- log.info("updateAndCreateTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
+
+ LOGGER.info("Broker receive request to update or create topic={}, caller address={}",
+ requestHeader.getTopic(), RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
String topic = requestHeader.getTopic();
@@ -302,8 +398,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
this.brokerController.getTopicConfigManager().updateTopicConfig(topicConfig);
this.brokerController.registerIncrementBrokerData(topicConfig, this.brokerController.getTopicConfigManager().getDataVersion());
response.setCode(ResponseCode.SUCCESS);
- } catch (Exception e) {
- log.error("Update / create topic failed for [{}]", request, e);
+ } catch (Exception e) {
+ LOGGER.error("Update / create topic failed for [{}]", request, e);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark(e.getMessage());
}
@@ -311,11 +407,11 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
}
private synchronized RemotingCommand updateAndCreateStaticTopic(ChannelHandlerContext ctx,
- RemotingCommand request) throws RemotingCommandException {
+ 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()));
+ (CreateTopicRequestHeader) request.decodeCommandCustomHeader(CreateTopicRequestHeader.class);
+ LOGGER.info("Broker receive request to update or create static topic={}, caller address={}", requestHeader.getTopic(), RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
final TopicQueueMappingDetail topicQueueMappingDetail = RemotingSerializable.decode(request.getBody(), TopicQueueMappingDetail.class);
@@ -347,21 +443,21 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
this.brokerController.registerIncrementBrokerData(topicConfig, this.brokerController.getTopicConfigManager().getDataVersion());
response.setCode(ResponseCode.SUCCESS);
} catch (Exception e) {
- log.error("Update static topic failed for [{}]", request, e);
+ LOGGER.error("Update static topic failed for [{}]", request, e);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark(e.getMessage());
}
return response;
}
-
private synchronized 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()));
+ LOGGER.info("AdminBrokerProcessor#deleteTopic: broker receive request to delete topic={}, caller={}",
+ requestHeader.getTopic(), RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
String topic = requestHeader.getTopic();
if (!TopicValidator.validateTopic(topic, response)) {
@@ -371,9 +467,9 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return response;
}
- this.brokerController.getTopicConfigManager().deleteTopicConfig(topic);
- this.brokerController.getTopicQueueMappingManager().delete(topic);
-
+ this.brokerController.getTopicConfigManager().deleteTopicConfig(requestHeader.getTopic());
+ this.brokerController.getTopicQueueMappingManager().delete(requestHeader.getTopic());
+ this.brokerController.getConsumerOffsetManager().cleanOffsetByTopic(requestHeader.getTopic());
this.brokerController.getMessageStore()
.cleanUnusedTopic(this.brokerController.getTopicConfigManager().getTopicConfigTable().keySet());
if (this.brokerController.getBrokerConfig().isAutoDeleteUnusedStats()) {
@@ -412,13 +508,13 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
ctx.writeAndFlush(response);
} else {
String errorMsg = "The accesskey[" + requestHeader.getAccessKey() + "] corresponding to accessConfig has been updated failed.";
- log.warn(errorMsg);
+ LOGGER.warn(errorMsg);
response.setCode(ResponseCode.UPDATE_AND_CREATE_ACL_CONFIG_FAILED);
response.setRemark(errorMsg);
return response;
}
} catch (Exception e) {
- log.error("Failed to generate a proper update accessvalidator response", e);
+ LOGGER.error("Failed to generate a proper update accessvalidator response", e);
response.setCode(ResponseCode.UPDATE_AND_CREATE_ACL_CONFIG_FAILED);
response.setRemark(e.getMessage());
return response;
@@ -433,7 +529,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
final DeleteAccessConfigRequestHeader requestHeader =
(DeleteAccessConfigRequestHeader) request.decodeCommandCustomHeader(DeleteAccessConfigRequestHeader.class);
- log.info("DeleteAccessConfig called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
+ LOGGER.info("DeleteAccessConfig called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
try {
String accessKey = requestHeader.getAccessKey();
@@ -446,14 +542,14 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
ctx.writeAndFlush(response);
} else {
String errorMsg = "The accesskey[" + requestHeader.getAccessKey() + "] corresponding to accessConfig has been deleted failed.";
- log.warn(errorMsg);
+ LOGGER.warn(errorMsg);
response.setCode(ResponseCode.DELETE_ACL_CONFIG_FAILED);
response.setRemark(errorMsg);
return response;
}
} catch (Exception e) {
- log.error("Failed to generate a proper delete accessvalidator response", e);
+ LOGGER.error("Failed to generate a proper delete accessvalidator response", e);
response.setCode(ResponseCode.DELETE_ACL_CONFIG_FAILED);
response.setRemark(e.getMessage());
return response;
@@ -480,13 +576,13 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
ctx.writeAndFlush(response);
} else {
String errorMsg = "The globalWhiteAddresses[" + requestHeader.getGlobalWhiteAddrs() + "] has been updated failed.";
- log.warn(errorMsg);
+ LOGGER.warn(errorMsg);
response.setCode(ResponseCode.UPDATE_GLOBAL_WHITE_ADDRS_CONFIG_FAILED);
response.setRemark(errorMsg);
return response;
}
} catch (Exception e) {
- log.error("Failed to generate a proper update globalWhiteAddresses response", e);
+ LOGGER.error("Failed to generate a proper update globalWhiteAddresses response", e);
response.setCode(ResponseCode.UPDATE_GLOBAL_WHITE_ADDRS_CONFIG_FAILED);
response.setRemark(e.getMessage());
return response;
@@ -499,12 +595,11 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
final RemotingCommand response = RemotingCommand.createResponseCommand(GetBrokerAclConfigResponseHeader.class);
- final GetBrokerAclConfigResponseHeader responseHeader = (GetBrokerAclConfigResponseHeader)response.readCustomHeader();
+ final GetBrokerAclConfigResponseHeader responseHeader = (GetBrokerAclConfigResponseHeader) response.readCustomHeader();
try {
AccessValidator accessValidator = this.brokerController.getAccessValidatorMap().get(PlainAccessValidator.class);
- responseHeader.setAllAclFileVersion(JSON.toJSONString(accessValidator.getAllAclConfigVersion()));
responseHeader.setVersion(accessValidator.getAclConfigVersion());
responseHeader.setBrokerAddr(this.brokerController.getBrokerAddr());
responseHeader.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName());
@@ -514,7 +609,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
response.setRemark(null);
return response;
} catch (Exception e) {
- log.error("Failed to generate a proper getBrokerAclConfigVersion response", e);
+ LOGGER.error("Failed to generate a proper getBrokerAclConfigVersion response", e);
}
return null;
@@ -535,7 +630,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
response.setRemark(null);
return response;
} catch (Exception e) {
- log.error("Failed to generate a proper getBrokerClusterAclConfig response", e);
+ LOGGER.error("Failed to generate a proper getBrokerClusterAclConfig response", e);
}
return null;
@@ -544,7 +639,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
private RemotingCommand getUnknownCmdResponse(ChannelHandlerContext ctx, RemotingCommand request) {
String error = " request type " + request.getCode() + " not supported";
final RemotingCommand response =
- RemotingCommand.createResponseCommand(RemotingSysResponseCode.REQUEST_CODE_NOT_SUPPORTED, error);
+ RemotingCommand.createResponseCommand(RemotingSysResponseCode.REQUEST_CODE_NOT_SUPPORTED, error);
return response;
}
@@ -561,20 +656,19 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
topicConfigAndMappingSerializeWrapper.setMappingDataVersion(this.brokerController.getTopicQueueMappingManager().getDataVersion());
topicConfigAndMappingSerializeWrapper.setTopicQueueMappingDetailMap(this.brokerController.getTopicQueueMappingManager().getTopicQueueMappingTable());
-
String content = topicConfigAndMappingSerializeWrapper.toJson();
if (content != null && content.length() > 0) {
try {
response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET));
} catch (UnsupportedEncodingException e) {
- log.error("", e);
+ LOGGER.error("", e);
response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("UnsupportedEncodingException " + e);
+ response.setRemark("UnsupportedEncodingException " + e.getMessage());
return response;
}
} else {
- log.error("No topic in this broker, client: {}", ctx.channel().remoteAddress());
+ LOGGER.error("No topic in this broker, client: {}", ctx.channel().remoteAddress());
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("No topic in this broker");
return response;
@@ -589,7 +683,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
private synchronized RemotingCommand updateBrokerConfig(ChannelHandlerContext ctx, RemotingCommand request) {
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
- log.info("updateBrokerConfig called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
+ final String callerAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel());
+ LOGGER.info("Broker receive request to update config, caller address={}", callerAddress);
byte[] body = request.getBody();
if (body != null) {
@@ -597,20 +692,21 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
String bodyStr = new String(body, MixAll.DEFAULT_CHARSET);
Properties properties = MixAll.string2Properties(bodyStr);
if (properties != null) {
- log.info("updateBrokerConfig, new config: [{}] client: {} ", properties, ctx.channel().remoteAddress());
+ LOGGER.info("updateBrokerConfig, new config: [{}] client: {} ", properties, ctx.channel().remoteAddress());
this.brokerController.getConfiguration().update(properties);
if (properties.containsKey("brokerPermission")) {
this.brokerController.getTopicConfigManager().getDataVersion().nextVersion();
this.brokerController.registerBrokerAll(false, false, true);
}
} else {
- log.error("string2Properties error");
+ LOGGER.error("string2Properties error");
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("string2Properties error");
return response;
}
} catch (UnsupportedEncodingException e) {
- log.error("", e);
+ LOGGER.error("AdminBrokerProcessor#updateBrokerConfig: unexpected error, caller={}",
+ callerAddress, e);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("UnsupportedEncodingException " + e);
return response;
@@ -632,7 +728,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
try {
response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET));
} catch (UnsupportedEncodingException e) {
- log.error("", e);
+ LOGGER.error("AdminBrokerProcessor#getBrokerConfig: unexpected error, caller={}",
+ RemotingHelper.parseChannelRemoteAddr(ctx.channel()), e);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("UnsupportedEncodingException " + e);
@@ -647,7 +744,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return response;
}
- private RemotingCommand rewriteRequestForStaticTopic(SearchOffsetRequestHeader requestHeader, TopicQueueMappingContext mappingContext) {
+ private RemotingCommand rewriteRequestForStaticTopic(SearchOffsetRequestHeader requestHeader,
+ TopicQueueMappingContext mappingContext) {
try {
if (mappingContext.getMappingDetail() == null) {
return null;
@@ -684,7 +782,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
}
SearchOffsetResponseHeader offsetResponseHeader = (SearchOffsetResponseHeader) rpcResponse.getHeader();
if (offsetResponseHeader.getOffset() < 0
- || (item.checkIfEndOffsetDecided() && offsetResponseHeader.getOffset() >= item.getEndOffset())) {
+ || (item.checkIfEndOffsetDecided() && offsetResponseHeader.getOffset() >= item.getEndOffset())) {
continue;
} else {
offset = item.computeStaticQueueOffsetStrictly(offsetResponseHeader.getOffset());
@@ -727,7 +825,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return response;
}
- private RemotingCommand rewriteRequestForStaticTopic(GetMaxOffsetRequestHeader requestHeader, TopicQueueMappingContext mappingContext) {
+ private RemotingCommand rewriteRequestForStaticTopic(GetMaxOffsetRequestHeader requestHeader,
+ TopicQueueMappingContext mappingContext) {
if (mappingContext.getMappingDetail() == null) {
return null;
}
@@ -793,7 +892,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return response;
}
- private CompletableFuture<RpcResponse> handleGetMinOffsetForStaticTopic(RpcRequest request, TopicQueueMappingContext mappingContext) {
+ private CompletableFuture<RpcResponse> handleGetMinOffsetForStaticTopic(RpcRequest request,
+ TopicQueueMappingContext mappingContext) {
if (mappingContext.getMappingDetail() == null) {
return null;
}
@@ -801,11 +901,11 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
if (!mappingContext.isLeader()) {
//this may not
return CompletableFuture.completedFuture(new RpcResponse(new RpcException(ResponseCode.NOT_LEADER_FOR_QUEUE,
- String.format("%s-%d is not leader in broker %s, request code %d", mappingContext.getTopic(), mappingContext.getGlobalId(), mappingDetail.getBname(), request.getCode()))));
+ String.format("%s-%d is not leader in broker %s, request code %d", mappingContext.getTopic(), mappingContext.getGlobalId(), mappingDetail.getBname(), request.getCode()))));
}
GetMinOffsetRequestHeader requestHeader = (GetMinOffsetRequestHeader) request.getHeader();
LogicQueueMappingItem mappingItem = TopicQueueMappingUtils.findLogicQueueMappingItem(mappingContext.getMappingItemList(), 0L, true);
- assert mappingItem != null;
+ assert mappingItem != null;
try {
requestHeader.setBname(mappingItem.getBname());
requestHeader.setLo(false);
@@ -829,12 +929,12 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
responseHeader.setOffset(offset);
return CompletableFuture.completedFuture(new RpcResponse(ResponseCode.SUCCESS, responseHeader, null));
} catch (Throwable t) {
- log.error("rewriteRequestForStaticTopic failed", t);
+ LOGGER.error("rewriteRequestForStaticTopic failed", t);
return CompletableFuture.completedFuture(new RpcResponse(new RpcException(ResponseCode.SYSTEM_ERROR, t.getMessage(), t)));
}
}
- private CompletableFuture<RpcResponse> handleGetMinOffset(RpcRequest request) {
+ private CompletableFuture<RpcResponse> handleGetMinOffset(RpcRequest request) {
assert request.getCode() == RequestCode.GET_MIN_OFFSET;
GetMinOffsetRequestHeader requestHeader = (GetMinOffsetRequestHeader) request.getHeader();
TopicQueueMappingContext mappingContext = this.brokerController.getTopicQueueMappingManager().buildTopicQueueMappingContext(requestHeader, false);
@@ -854,14 +954,15 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
(GetMinOffsetRequestHeader) request.decodeCommandCustomHeader(GetMinOffsetRequestHeader.class);
try {
CompletableFuture<RpcResponse> responseFuture = handleGetMinOffset(new RpcRequest(RequestCode.GET_MIN_OFFSET, requestHeader, null));
- RpcResponse rpcResponse = responseFuture.get();
+ RpcResponse rpcResponse = responseFuture.get();
return RpcClientUtils.createCommandForRpcResponse(rpcResponse);
} catch (Throwable t) {
return buildErrorResponse(ResponseCode.SYSTEM_ERROR, t.getMessage());
}
}
- private RemotingCommand rewriteRequestForStaticTopic(GetEarliestMsgStoretimeRequestHeader requestHeader, TopicQueueMappingContext mappingContext) {
+ private RemotingCommand rewriteRequestForStaticTopic(GetEarliestMsgStoretimeRequestHeader requestHeader,
+ TopicQueueMappingContext mappingContext) {
if (mappingContext.getMappingDetail() == null) {
return null;
}
@@ -935,10 +1036,78 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
LockBatchRequestBody requestBody = LockBatchRequestBody.decode(request.getBody(), LockBatchRequestBody.class);
- Set<MessageQueue> lockOKMQSet = this.brokerController.getRebalanceLockManager().tryLockBatch(
+ Set<MessageQueue> lockOKMQSet = new HashSet<>();
+ Set<MessageQueue> selfLockOKMQSet = this.brokerController.getRebalanceLockManager().tryLockBatch(
requestBody.getConsumerGroup(),
requestBody.getMqSet(),
requestBody.getClientId());
+ if (requestBody.isOnlyThisBroker() || !brokerController.getBrokerConfig().isLockInStrictMode()) {
+ lockOKMQSet = selfLockOKMQSet;
+ } else {
+ requestBody.setOnlyThisBroker(true);
+ int replicaSize = this.brokerController.getMessageStoreConfig().getTotalReplicas();
+
+ int quorum = replicaSize / 2 + 1;
+
+ if (quorum <= 1) {
+ lockOKMQSet = selfLockOKMQSet;
+ } else {
+ final ConcurrentMap<MessageQueue, Integer> mqLockMap = new ConcurrentHashMap<>();
+ for (MessageQueue mq : selfLockOKMQSet) {
+ if (!mqLockMap.containsKey(mq)) {
+ mqLockMap.put(mq, 0);
+ }
+ mqLockMap.put(mq, mqLockMap.get(mq) + 1);
+ }
+
+ BrokerMemberGroup memberGroup = this.brokerController.getBrokerMemberGroup();
+
+ if (memberGroup != null) {
+ Map<Long, String> addrMap = new HashMap<>(memberGroup.getBrokerAddrs());
+ addrMap.remove(this.brokerController.getBrokerConfig().getBrokerId());
+ final CountDownLatch countDownLatch = new CountDownLatch(addrMap.size());
+ requestBody.setMqSet(selfLockOKMQSet);
+ requestBody.setOnlyThisBroker(true);
+ for (Long brokerId : addrMap.keySet()) {
+ try {
+ this.brokerController.getBrokerOuterAPI().lockBatchMQAsync(addrMap.get(brokerId),
+ requestBody, 1000, new LockCallback() {
+ @Override
+ public void onSuccess(Set<MessageQueue> lockOKMQSet) {
+ for (MessageQueue mq : lockOKMQSet) {
+ if (!mqLockMap.containsKey(mq)) {
+ mqLockMap.put(mq, 0);
+ }
+ mqLockMap.put(mq, mqLockMap.get(mq) + 1);
+ }
+ countDownLatch.countDown();
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ LOGGER.warn("lockBatchMQAsync on {} failed, {}", addrMap.get(brokerId), e);
+ countDownLatch.countDown();
+ }
+ });
+ } catch (Exception e) {
+ LOGGER.warn("lockBatchMQAsync on {} failed, {}", addrMap.get(brokerId), e);
+ countDownLatch.countDown();
+ }
+ }
+ try {
+ countDownLatch.await(2000, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ LOGGER.warn("lockBatchMQ exception on {}, {}", this.brokerController.getBrokerConfig().getBrokerName(), e);
+ }
+ }
+
+ for (MessageQueue mq : mqLockMap.keySet()) {
+ if (mqLockMap.get(mq) >= quorum) {
+ lockOKMQSet.add(mq);
+ }
+ }
+ }
+ }
LockBatchResponseBody responseBody = new LockBatchResponseBody();
responseBody.setLockOKMQSet(lockOKMQSet);
@@ -954,10 +1123,36 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
UnlockBatchRequestBody requestBody = UnlockBatchRequestBody.decode(request.getBody(), UnlockBatchRequestBody.class);
- this.brokerController.getRebalanceLockManager().unlockBatch(
- requestBody.getConsumerGroup(),
- requestBody.getMqSet(),
- requestBody.getClientId());
+ if (requestBody.isOnlyThisBroker() || !this.brokerController.getBrokerConfig().isLockInStrictMode()) {
+ this.brokerController.getRebalanceLockManager().unlockBatch(
+ requestBody.getConsumerGroup(),
+ requestBody.getMqSet(),
+ requestBody.getClientId());
+ } else {
+ requestBody.setOnlyThisBroker(true);
+ BrokerMemberGroup memberGroup = this.brokerController.getBrokerMemberGroup();
+
+ if (memberGroup != null) {
+ Map<Long, String> addrMap = memberGroup.getBrokerAddrs();
+ for (Long brokerId : addrMap.keySet()) {
+ try {
+ this.brokerController.getBrokerOuterAPI().unlockBatchMQAsync(addrMap.get(brokerId), requestBody, 1000, new UnlockCallback() {
+ @Override
+ public void onSuccess() {
+
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ LOGGER.warn("unlockBatchMQ exception on {}, {}", addrMap.get(brokerId), e);
+ }
+ });
+ } catch (Exception e) {
+ LOGGER.warn("unlockBatchMQ exception on {}, {}", addrMap.get(brokerId), e);
+ }
+ }
+ }
+ }
response.setCode(ResponseCode.SUCCESS);
response.setRemark(null);
@@ -968,7 +1163,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
throws RemotingCommandException {
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
- log.info("updateAndCreateSubscriptionGroup called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
+ LOGGER.info("AdminBrokerProcessor#updateAndCreateSubscriptionGroup called by {}",
+ RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
SubscriptionGroupConfig config = RemotingSerializable.decode(request.getBody(), SubscriptionGroupConfig.class);
if (config != null) {
@@ -980,6 +1176,26 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return response;
}
+ private void initConsumerOffset(String clientHost, String groupName, int mode, TopicConfig topicConfig) {
+ String topic = topicConfig.getTopicName();
+ for (int queueId = 0; queueId < topicConfig.getReadQueueNums(); queueId++) {
+ if (this.brokerController.getConsumerOffsetManager().queryOffset(groupName, topic, queueId) > -1) {
+ continue;
+ }
+ long offset = 0;
+ if (this.brokerController.getMessageStore().getConsumeQueue(topic, queueId) != null) {
+ if (ConsumeInitMode.MAX == mode) {
+ offset = this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, queueId);
+ } else if (ConsumeInitMode.MIN == mode) {
+ offset = this.brokerController.getMessageStore().getMinOffsetInQueue(topic, queueId);
+ }
+ }
+ this.brokerController.getConsumerOffsetManager().commitOffset(clientHost, groupName, topic, queueId, offset);
+ LOGGER.info("AdminBrokerProcessor#initConsumerOffset: consumerGroup={}, topic={}, queueId={}, offset={}",
+ groupName, topic, queueId, offset);
+ }
+ }
+
private RemotingCommand getAllSubscriptionGroup(ChannelHandlerContext ctx,
RemotingCommand request) throws RemotingCommandException {
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
@@ -988,14 +1204,14 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
try {
response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET));
} catch (UnsupportedEncodingException e) {
- log.error("", e);
+ LOGGER.error("UnsupportedEncodingException getAllSubscriptionGroup", e);
response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("UnsupportedEncodingException " + e);
+ response.setRemark("UnsupportedEncodingException " + e.getMessage());
return response;
}
} else {
- log.error("No subscription group in this broker, client:{} ", ctx.channel().remoteAddress());
+ LOGGER.error("No subscription group in this broker, client:{} ", ctx.channel().remoteAddress());
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("No subscription group in this broker");
return response;
@@ -1013,11 +1229,12 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
DeleteSubscriptionGroupRequestHeader requestHeader =
(DeleteSubscriptionGroupRequestHeader) request.decodeCommandCustomHeader(DeleteSubscriptionGroupRequestHeader.class);
- log.info("deleteSubscriptionGroup called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
+ LOGGER.info("AdminBrokerProcessor#deleteSubscriptionGroup, caller={}",
+ RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
this.brokerController.getSubscriptionGroupManager().deleteSubscriptionGroupConfig(requestHeader.getGroupName());
- if (requestHeader.isRemoveOffset()) {
+ if (requestHeader.isCleanOffset()) {
this.brokerController.getConsumerOffsetManager().removeOffset(requestHeader.getGroupName());
}
@@ -1029,8 +1246,6 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return response;
}
-
-
private RemotingCommand getTopicStatsInfo(ChannelHandlerContext ctx,
RemotingCommand request) throws RemotingCommandException {
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
@@ -1044,8 +1259,8 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
response.setRemark("topic[" + topic + "] not exist");
return response;
}
- TopicStatsTable topicStatsTable = new TopicStatsTable();
+ TopicStatsTable topicStatsTable = new TopicStatsTable();
for (int i = 0; i < topicConfig.getWriteQueueNums(); i++) {
MessageQueue mq = new MessageQueue();
mq.setTopic(topic);
@@ -1054,12 +1269,14 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
TopicOffset topicOffset = new TopicOffset();
long min = this.brokerController.getMessageStore().getMinOffsetInQueue(topic, i);
- if (min < 0)
+ if (min < 0) {
min = 0;
+ }
long max = this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, i);
- if (max < 0)
+ if (max < 0) {
max = 0;
+ }
long timestamp = 0;
if (max > 0) {
@@ -1172,7 +1389,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
for (String topic : topics) {
TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(topic);
if (null == topicConfig) {
- log.warn("consumeStats, topic config not exist, {}", topic);
+ LOGGER.warn("AdminBrokerProcessor#getConsumeStats: topic config does not exist, topic={}", topic);
continue;
}
@@ -1184,7 +1401,9 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
if (null == findSubscriptionData
&& this.brokerController.getConsumerManager().findSubscriptionDataCount(requestHeader.getConsumerGroup()) > 0) {
- log.warn("consumeStats, the consumer group[{}], topic[{}] not exist", requestHeader.getConsumerGroup(), topic);
+ LOGGER.warn(
+ "AdminBrokerProcessor#getConsumeStats: topic does not exist in consumer group's subscription, "
+ + "topic={}, consumer group={}", topic, requestHeader.getConsumerGroup());
continue;
}
}
@@ -1198,19 +1417,20 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
OffsetWrapper offsetWrapper = new OffsetWrapper();
long brokerOffset = this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, i);
- if (brokerOffset < 0)
+ if (brokerOffset < 0) {
brokerOffset = 0;
+ }
long consumerOffset = this.brokerController.getConsumerOffsetManager().queryOffset(
- requestHeader.getConsumerGroup(),
- topic,
- i);
+ requestHeader.getConsumerGroup(), topic, i);
+
// the consumerOffset cannot be zero for static topic because of the "double read check" strategy
// just remain the logic for dynamic topic
// maybe we should remove it in the future
if (mappingDetail == null) {
- if (consumerOffset < 0)
+ if (consumerOffset < 0) {
consumerOffset = 0;
+ }
}
offsetWrapper.setBrokerOffset(brokerOffset);
@@ -1223,6 +1443,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
offsetWrapper.setLastTimestamp(lastTimestamp);
}
}
+
consumeStats.getOffsetTable().put(mq, offsetWrapper);
}
@@ -1247,14 +1468,14 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
try {
response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET));
} catch (UnsupportedEncodingException e) {
- log.error("get all consumer offset from master error.", e);
+ LOGGER.error("get all consumer offset from master error.", e);
response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("UnsupportedEncodingException " + e);
+ response.setRemark("UnsupportedEncodingException " + e.getMessage());
return response;
}
} else {
- log.error("No consumer offset in this broker, client: {} ", ctx.channel().remoteAddress());
+ LOGGER.error("No consumer offset in this broker, client: {} ", ctx.channel().remoteAddress());
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("No consumer offset in this broker");
return response;
@@ -1269,26 +1490,21 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
private RemotingCommand getAllDelayOffset(ChannelHandlerContext ctx, RemotingCommand request) {
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
- if (!(this.brokerController.getMessageStore() instanceof DefaultMessageStore)) {
- log.error("Delay offset not supported in this messagetore, client: {} ", ctx.channel().remoteAddress());
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("Delay offset not supported in this messagetore");
- return response;
- }
-
- String content = ((DefaultMessageStore) this.brokerController.getMessageStore()).getScheduleMessageService().encode();
+ String content = this.brokerController.getScheduleMessageService().encode();
if (content != null && content.length() > 0) {
try {
response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET));
} catch (UnsupportedEncodingException e) {
- log.error("Get all delay offset from master error.", e);
+ LOGGER.error("AdminBrokerProcessor#getAllDelayOffset: unexpected error, caller={}.",
+ RemotingHelper.parseChannelRemoteAddr(ctx.channel()), e);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("UnsupportedEncodingException " + e);
return response;
}
} else {
- log.error("No delay offset in this broker, client: {} ", ctx.channel().remoteAddress());
+ LOGGER.error("AdminBrokerProcessor#getAllDelayOffset: no delay offset in this broker, caller={}",
+ RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("No delay offset in this broker");
return response;
@@ -1304,7 +1520,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
RemotingCommand request) throws RemotingCommandException {
final ResetOffsetRequestHeader requestHeader =
(ResetOffsetRequestHeader) request.decodeCommandCustomHeader(ResetOffsetRequestHeader.class);
- log.info("[reset-offset] reset offset started by {}. topic={}, group={}, timestamp={}, isForce={}",
+ LOGGER.info("[reset-offset] reset offset started by {}. topic={}, group={}, timestamp={}, isForce={}",
RemotingHelper.parseChannelRemoteAddr(ctx.channel()), requestHeader.getTopic(), requestHeader.getGroup(),
requestHeader.getTimestamp(), requestHeader.isForce());
boolean isC = false;
@@ -1323,7 +1539,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
final GetConsumerStatusRequestHeader requestHeader =
(GetConsumerStatusRequestHeader) request.decodeCommandCustomHeader(GetConsumerStatusRequestHeader.class);
- log.info("[get-consumer-status] get consumer status by {}. topic={}, group={}",
+ LOGGER.info("[get-consumer-status] get consumer status by {}. topic={}, group={}",
RemotingHelper.parseChannelRemoteAddr(ctx.channel()), requestHeader.getTopic(), requestHeader.getGroup());
return this.brokerController.getBroker2Client().getConsumeStatus(requestHeader.getTopic(), requestHeader.getGroup(),
@@ -1353,6 +1569,47 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return response;
}
+ private RemotingCommand queryTopicsByConsumer(ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ final RemotingCommand response = RemotingCommand.createResponseCommand(null);
+ QueryTopicsByConsumerRequestHeader requestHeader =
+ (QueryTopicsByConsumerRequestHeader) request.decodeCommandCustomHeader(QueryTopicsByConsumerRequestHeader.class);
+
+ Set<String> topics = this.brokerController.getConsumerOffsetManager().whichTopicByConsumer(requestHeader.getGroup());
+
+ TopicList topicList = new TopicList();
+ topicList.setTopicList(topics);
+ topicList.setBrokerAddr(brokerController.getBrokerAddr());
+ byte[] body = topicList.encode();
+
+ response.setBody(body);
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+ return response;
+ }
+
+ private RemotingCommand querySubscriptionByConsumer(ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ final RemotingCommand response = RemotingCommand.createResponseCommand(null);
+ QuerySubscriptionByConsumerRequestHeader requestHeader =
+ (QuerySubscriptionByConsumerRequestHeader) request.decodeCommandCustomHeader(QuerySubscriptionByConsumerRequestHeader.class);
+
+ SubscriptionData subscriptionData =
+ this.brokerController.getConsumerManager().findSubscriptionData(requestHeader.getGroup(), requestHeader.getTopic());
+
+ QuerySubscriptionResponseBody responseBody = new QuerySubscriptionResponseBody();
+ responseBody.setGroup(requestHeader.getGroup());
+ responseBody.setTopic(requestHeader.getTopic());
+ responseBody.setSubscriptionData(subscriptionData);
+ byte[] body = responseBody.encode();
+
+ response.setBody(body);
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+ return response;
+
+ }
+
private RemotingCommand registerFilterServer(ChannelHandlerContext ctx,
RemotingCommand request) throws RemotingCommandException {
final RemotingCommand response = RemotingCommand.createResponseCommand(RegisterFilterServerResponseHeader.class);
@@ -1440,20 +1697,20 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
}
public RemotingCommand cleanExpiredConsumeQueue() {
- log.warn("invoke cleanExpiredConsumeQueue start.");
+ LOGGER.info("AdminBrokerProcessor#cleanExpiredConsumeQueue: start.");
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
brokerController.getMessageStore().cleanExpiredConsumerQueue();
- log.warn("invoke cleanExpiredConsumeQueue end.");
+ LOGGER.info("AdminBrokerProcessor#cleanExpiredConsumeQueue: end.");
response.setCode(ResponseCode.SUCCESS);
response.setRemark(null);
return response;
}
public RemotingCommand cleanUnusedTopic() {
- log.warn("invoke cleanUnusedTopic start.");
+ LOGGER.warn("invoke cleanUnusedTopic start.");
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
brokerController.getMessageStore().cleanUnusedTopic(brokerController.getTopicConfigManager().getTopicConfigTable().keySet());
- log.warn("invoke cleanUnusedTopic end.");
+ LOGGER.warn("invoke cleanUnusedTopic end.");
response.setCode(ResponseCode.SUCCESS);
response.setRemark(null);
return response;
@@ -1501,7 +1758,22 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
final ConsumeMessageDirectlyResultRequestHeader requestHeader = (ConsumeMessageDirectlyResultRequestHeader) request
.decodeCommandCustomHeader(ConsumeMessageDirectlyResultRequestHeader.class);
+ // brokerName
request.getExtFields().put("brokerName", this.brokerController.getBrokerConfig().getBrokerName());
+ // topicSysFlag
+ if (StringUtils.isNotEmpty(requestHeader.getTopic())) {
+ TopicConfig topicConfig = this.brokerController.getTopicConfigManager().getTopicConfigTable().get(requestHeader.getTopic());
+ if (topicConfig != null) {
+ request.addExtField("topicSysFlag", String.valueOf(topicConfig.getTopicSysFlag()));
+ }
+ }
+ // groupSysFlag
+ if (StringUtils.isNotEmpty(requestHeader.getConsumerGroup())) {
+ SubscriptionGroupConfig groupConfig = brokerController.getSubscriptionGroupManager().getSubscriptionGroupTable().get(requestHeader.getConsumerGroup());
+ if (groupConfig != null) {
+ request.addExtField("groupSysFlag", String.valueOf(groupConfig.getGroupSysFlag()));
+ }
+ }
SelectMappedBufferResult selectMappedBufferResult = null;
try {
MessageId messageId = MessageDecoder.decodeMessageId(requestHeader.getMsgId());
@@ -1538,7 +1810,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
for (String topic : topics) {
TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(topic);
if (null == topicConfig) {
- log.warn("[cloneGroupOffset], topic config not exist, {}", topic);
+ LOGGER.warn("[cloneGroupOffset], topic config not exist, {}", topic);
continue;
}
@@ -1548,7 +1820,9 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
this.brokerController.getConsumerManager().findSubscriptionData(requestHeader.getSrcGroup(), topic);
if (this.brokerController.getConsumerManager().findSubscriptionDataCount(requestHeader.getSrcGroup()) > 0
&& findSubscriptionData == null) {
- log.warn("[cloneGroupOffset], the consumer group[{}], topic[{}] not exist", requestHeader.getSrcGroup(), topic);
+ LOGGER.warn(
+ "AdminBrokerProcessor#cloneGroupOffset: topic does not exist in consumer group's "
+ + "subscription, topic={}, consumer group={}", topic, requestHeader.getSrcGroup());
continue;
}
}
@@ -1633,7 +1907,9 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
ConsumeStats consumeStats = new ConsumeStats();
TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(topic);
if (null == topicConfig) {
- log.warn("consumeStats, topic config not exist, {}", topic);
+ LOGGER.warn(
+ "AdminBrokerProcessor#fetchAllConsumeStatsInBroker: topic config does not exist, topic={}",
+ topic);
continue;
}
@@ -1646,7 +1922,9 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
if (null == findSubscriptionData
&& this.brokerController.getConsumerManager().findSubscriptionDataCount(group) > 0) {
- log.warn("consumeStats, the consumer group[{}], topic[{}] not exist", group, topic);
+ LOGGER.warn(
+ "AdminBrokerProcessor#fetchAllConsumeStatsInBroker: topic does not exist in consumer "
+ + "group's subscription, topic={}, consumer group={}", topic, group);
continue;
}
}
@@ -1658,8 +1936,9 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
mq.setQueueId(i);
OffsetWrapper offsetWrapper = new OffsetWrapper();
long brokerOffset = this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, i);
- if (brokerOffset < 0)
+ if (brokerOffset < 0) {
brokerOffset = 0;
+ }
long consumerOffset = this.brokerController.getConsumerOffsetManager().queryOffset(
group,
topic,
@@ -1700,6 +1979,15 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
private HashMap<String, String> prepareRuntimeInfo() {
HashMap<String, String> runtimeInfo = this.brokerController.getMessageStore().getRuntimeInfo();
+
+ for (BrokerAttachedPlugin brokerAttachedPlugin : brokerController.getBrokerAttachedPlugins()) {
+ if (brokerAttachedPlugin != null) {
+ brokerAttachedPlugin.buildRuntimeInfo(runtimeInfo);
+ }
+ }
+
+ this.brokerController.getScheduleMessageService().buildRunningStats(runtimeInfo);
+ runtimeInfo.put("brokerActive", String.valueOf(this.brokerController.isSpecialServiceRunning()));
runtimeInfo.put("brokerVersionDesc", MQVersion.getVersionDesc(MQVersion.CURRENT_VERSION));
runtimeInfo.put("brokerVersion", String.valueOf(MQVersion.CURRENT_VERSION));
@@ -1713,8 +2001,25 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
runtimeInfo.put("msgGetTotalTodayMorning", String.valueOf(this.brokerController.getBrokerStats().getMsgGetTotalTodayMorning()));
runtimeInfo.put("msgGetTotalTodayNow", String.valueOf(this.brokerController.getBrokerStats().getMsgGetTotalTodayNow()));
- runtimeInfo.put("sendThreadPoolQueueSize", String.valueOf(this.brokerController.getSendThreadPoolQueue().size()));
+ runtimeInfo.put("dispatchBehindBytes", String.valueOf(this.brokerController.getMessageStore().dispatchBehindBytes()));
+ runtimeInfo.put("pageCacheLockTimeMills", String.valueOf(this.brokerController.getMessageStore().lockTimeMills()));
+
+ runtimeInfo.put("earliestMessageTimeStamp", String.valueOf(this.brokerController.getMessageStore().getEarliestMessageTime()));
+ runtimeInfo.put("startAcceptSendRequestTimeStamp", String.valueOf(this.brokerController.getBrokerConfig().getStartAcceptSendRequestTimeStamp()));
+ MessageStore messageStore = this.brokerController.getMessageStore();
+ runtimeInfo.put("remainTransientStoreBufferNumbs", String.valueOf(messageStore.remainTransientStoreBufferNumbs()));
+ if (this.brokerController.getMessageStoreConfig().isTransientStorePoolEnable()) {
+ runtimeInfo.put("remainHowManyDataToCommit", MixAll.humanReadableByteCount(messageStore.remainHowManyDataToCommit(), false));
+ }
+ runtimeInfo.put("remainHowManyDataToFlush", MixAll.humanReadableByteCount(messageStore.remainHowManyDataToFlush(), false));
+
+ java.io.File commitLogDir = new java.io.File(this.brokerController.getMessageStoreConfig().getStorePathRootDir());
+ if (commitLogDir.exists()) {
+ runtimeInfo.put("commitLogDirCapacity", String.format("Total : %s, Free : %s.", MixAll.humanReadableByteCount(commitLogDir.getTotalSpace(), false), MixAll.humanReadableByteCount(commitLogDir.getFreeSpace(), false)));
+ }
+
+ runtimeInfo.put("sendThreadPoolQueueSize", String.valueOf(this.brokerController.getSendThreadPoolQueue().size()));
runtimeInfo.put("sendThreadPoolQueueCapacity",
String.valueOf(this.brokerController.getBrokerConfig().getSendThreadPoolQueueCapacity()));
@@ -1722,36 +2027,22 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
runtimeInfo.put("pullThreadPoolQueueCapacity",
String.valueOf(this.brokerController.getBrokerConfig().getPullThreadPoolQueueCapacity()));
+ runtimeInfo.put("litePullThreadPoolQueueSize", String.valueOf(brokerController.getLitePullThreadPoolQueue().size()));
+ runtimeInfo.put("litePullThreadPoolQueueCapacity",
+ String.valueOf(this.brokerController.getBrokerConfig().getLitePullThreadPoolQueueCapacity()));
+
runtimeInfo.put("queryThreadPoolQueueSize", String.valueOf(this.brokerController.getQueryThreadPoolQueue().size()));
runtimeInfo.put("queryThreadPoolQueueCapacity",
String.valueOf(this.brokerController.getBrokerConfig().getQueryThreadPoolQueueCapacity()));
- runtimeInfo.put("EndTransactionQueueSize", String.valueOf(this.brokerController.getEndTransactionThreadPoolQueue().size()));
- runtimeInfo.put("EndTransactionThreadPoolQueueCapacity",
- String.valueOf(this.brokerController.getBrokerConfig().getEndTransactionPoolQueueCapacity()));
-
- runtimeInfo.put("dispatchBehindBytes", String.valueOf(this.brokerController.getMessageStore().dispatchBehindBytes()));
- runtimeInfo.put("pageCacheLockTimeMills", String.valueOf(this.brokerController.getMessageStore().lockTimeMills()));
-
runtimeInfo.put("sendThreadPoolQueueHeadWaitTimeMills", String.valueOf(this.brokerController.headSlowTimeMills4SendThreadPoolQueue()));
- runtimeInfo.put("pullThreadPoolQueueHeadWaitTimeMills", String.valueOf(this.brokerController.headSlowTimeMills4PullThreadPoolQueue()));
+ runtimeInfo.put("pullThreadPoolQueueHeadWaitTimeMills", String.valueOf(brokerController.headSlowTimeMills4PullThreadPoolQueue()));
runtimeInfo.put("queryThreadPoolQueueHeadWaitTimeMills", String.valueOf(this.brokerController.headSlowTimeMills4QueryThreadPoolQueue()));
+ runtimeInfo.put("litePullThreadPoolQueueHeadWaitTimeMills", String.valueOf(brokerController.headSlowTimeMills4LitePullThreadPoolQueue()));
- runtimeInfo.put("earliestMessageTimeStamp", String.valueOf(this.brokerController.getMessageStore().getEarliestMessageTime()));
- runtimeInfo.put("startAcceptSendRequestTimeStamp", String.valueOf(this.brokerController.getBrokerConfig().getStartAcceptSendRequestTimeStamp()));
- if (this.brokerController.getMessageStore() instanceof DefaultMessageStore) {
- DefaultMessageStore defaultMessageStore = (DefaultMessageStore) this.brokerController.getMessageStore();
- runtimeInfo.put("remainTransientStoreBufferNumbs", String.valueOf(defaultMessageStore.remainTransientStoreBufferNumbs()));
- if (defaultMessageStore.getMessageStoreConfig().isTransientStorePoolEnable()) {
- runtimeInfo.put("remainHowManyDataToCommit", MixAll.humanReadableByteCount(defaultMessageStore.getCommitLog().remainHowManyDataToCommit(), false));
- }
- runtimeInfo.put("remainHowManyDataToFlush", MixAll.humanReadableByteCount(defaultMessageStore.getCommitLog().remainHowManyDataToFlush(), false));
- }
-
- java.io.File commitLogDir = new java.io.File(this.brokerController.getMessageStoreConfig().getStorePathRootDir());
- if (commitLogDir.exists()) {
- runtimeInfo.put("commitLogDirCapacity", String.format("Total : %s, Free : %s.", MixAll.humanReadableByteCount(commitLogDir.getTotalSpace(), false), MixAll.humanReadableByteCount(commitLogDir.getUsableSpace(), false)));
- }
+ runtimeInfo.put("EndTransactionQueueSize", String.valueOf(this.brokerController.getEndTransactionThreadPoolQueue().size()));
+ runtimeInfo.put("EndTransactionThreadPoolQueueCapacity",
+ String.valueOf(this.brokerController.getBrokerConfig().getEndTransactionPoolQueueCapacity()));
return runtimeInfo;
}
@@ -1844,7 +2135,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
List<ConsumeQueueData> queues = new ArrayList<>();
while (result.hasNext()) {
CqUnit cqUnit = result.next();
- if (cqUnit.getQueueOffset() - requestHeader.getIndex() >= requestHeader.getCount()) {
+ if (cqUnit.getQueueOffset() - requestHeader.getIndex() >= requestHeader.getCount()) {
break;
}
@@ -1898,18 +2189,18 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
.putMessage(toMessageExtBrokerInner(msg));
if (putMessageResult != null
&& putMessageResult.getPutMessageStatus() == PutMessageStatus.PUT_OK) {
- log.info(
+ LOGGER.info(
"Put message back to RMQ_SYS_TRANS_HALF_TOPIC. real topic={}",
msg.getUserProperty(MessageConst.PROPERTY_REAL_TOPIC));
response.setCode(ResponseCode.SUCCESS);
response.setRemark(null);
} else {
- log.error("Put message back to RMQ_SYS_TRANS_HALF_TOPIC failed.");
+ LOGGER.error("Put message back to RMQ_SYS_TRANS_HALF_TOPIC failed.");
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("Put message back to RMQ_SYS_TRANS_HALF_TOPIC failed.");
}
} catch (Exception e) {
- log.error("Exception was thrown when putting message back to RMQ_SYS_TRANS_HALF_TOPIC.");
+ LOGGER.error("Exception was thrown when putting message back to RMQ_SYS_TRANS_HALF_TOPIC.");
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("Exception was thrown when putting message back to RMQ_SYS_TRANS_HALF_TOPIC.");
} finally {
@@ -1946,7 +2237,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
TopicConfig topicConfig = this.brokerController.getTopicConfigManager().getTopicConfigTable().get(requestHeader.getTopic());
if (topicConfig == null) {
- log.error("No topic in this broker, client: {} topic: {}", ctx.channel().remoteAddress(), requestHeader.getTopic());
+ LOGGER.error("No topic in this broker, client: {} topic: {}", ctx.channel().remoteAddress(), requestHeader.getTopic());
//be care of the response code, should set "not-exist" explictly
response.setCode(ResponseCode.TOPIC_NOT_EXIST);
response.setRemark("No topic in this broker. topic: " + requestHeader.getTopic());
@@ -1960,7 +2251,7 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
try {
response.setBody(content.getBytes(MixAll.DEFAULT_CHARSET));
} catch (UnsupportedEncodingException e) {
- log.error("UnsupportedEncodingException getTopicConfig: topic=" + topicConfig.getTopicName(), e);
+ LOGGER.error("UnsupportedEncodingException getTopicConfig: topic=" + topicConfig.getTopicName(), e);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("UnsupportedEncodingException " + e.getMessage());
@@ -1971,4 +2262,84 @@ public class AdminBrokerProcessor extends AsyncNettyRequestProcessor implements
return response;
}
+
+ private RemotingCommand notifyMinBrokerIdChange(ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ NotifyMinBrokerIdChangeRequestHeader requestHeader = request.decodeCommandCustomHeader(NotifyMinBrokerIdChangeRequestHeader.class);
+
+ RemotingCommand response = RemotingCommand.createResponseCommand(null);
+
+ LOGGER.warn("min broker id changed, prev {}, new {}", this.brokerController.getMinBrokerIdInGroup(), requestHeader.getMinBrokerId());
+
+ this.brokerController.updateMinBroker(requestHeader.getMinBrokerId(), requestHeader.getMinBrokerAddr(),
+ requestHeader.getOfflineBrokerAddr(),
+ requestHeader.getHaBrokerAddr());
+
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+
+ return response;
+ }
+
+ private RemotingCommand updateBrokerHaInfo(ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ RemotingCommand response = RemotingCommand.createResponseCommand(ExchangeHAInfoResponseHeader.class);
+
+ ExchangeHAInfoRequestHeader requestHeader = request.decodeCommandCustomHeader(ExchangeHAInfoRequestHeader.class);
+ if (requestHeader.getMasterHaAddress() != null) {
+ this.brokerController.getMessageStore().updateHaMasterAddress(requestHeader.getMasterHaAddress());
+ this.brokerController.getMessageStore().updateMasterAddress(requestHeader.getMasterAddress());
+ if (this.brokerController.getMessageStore().getMasterFlushedOffset() == 0
+ && this.brokerController.getMessageStoreConfig().isSyncMasterFlushOffsetWhenStartup()) {
+ LOGGER.info("Set master flush offset in slave to {}", requestHeader.getMasterFlushOffset());
+ this.brokerController.getMessageStore().setMasterFlushedOffset(requestHeader.getMasterFlushOffset());
+ }
+ } else if (this.brokerController.getBrokerConfig().getBrokerId() == MixAll.MASTER_ID) {
+ final ExchangeHAInfoResponseHeader responseHeader = (ExchangeHAInfoResponseHeader) response.readCustomHeader();
+ responseHeader.setMasterHaAddress(this.brokerController.getHAServerAddr());
+ responseHeader.setMasterFlushOffset(this.brokerController.getMessageStore().getBrokerInitMaxOffset());
+ responseHeader.setMasterAddress(this.brokerController.getBrokerAddr());
+ }
+
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+
+ return response;
+ }
+
+ private RemotingCommand getBrokerHaStatus(ChannelHandlerContext ctx, RemotingCommand request) {
+ final RemotingCommand response = RemotingCommand.createResponseCommand(null);
+
+ HARuntimeInfo runtimeInfo = this.brokerController.getMessageStore().getHARuntimeInfo();
+
+ if (runtimeInfo != null) {
+ byte[] body = runtimeInfo.encode();
+ response.setBody(body);
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+ } else {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("Can not get HARuntimeInfo, may be duplicationEnable is true");
+ }
+
+ return response;
+ }
+
+ private RemotingCommand resetMasterFlushOffset(ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ final RemotingCommand response = RemotingCommand.createResponseCommand(null);
+
+ if (this.brokerController.getBrokerConfig().getBrokerId() != MixAll.MASTER_ID) {
+
+ ResetMasterFlushOffsetHeader requestHeader = request.decodeCommandCustomHeader(ResetMasterFlushOffsetHeader.class);
+
+ if (requestHeader.getMasterFlushOffset() != null) {
+ this.brokerController.getMessageStore().setMasterFlushedOffset(requestHeader.getMasterFlushOffset());
+ }
+ }
+
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+ return response;
+ }
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/ChangeInvisibleTimeProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/ChangeInvisibleTimeProcessor.java
index e40a5e8..991a705 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/ChangeInvisibleTimeProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/ChangeInvisibleTimeProcessor.java
@@ -38,7 +38,7 @@ import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
import org.apache.rocketmq.store.PutMessageResult;
import org.apache.rocketmq.store.PutMessageStatus;
import org.apache.rocketmq.store.pop.AckMsg;
@@ -47,16 +47,16 @@ import org.apache.rocketmq.store.pop.PopCheckPoint;
public class ChangeInvisibleTimeProcessor implements NettyRequestProcessor {
private static final InternalLogger POP_LOGGER = InternalLoggerFactory.getLogger(LoggerName.ROCKETMQ_POP_LOGGER_NAME);
private final BrokerController brokerController;
- private String reviveTopic;
+ private final String reviveTopic;
public ChangeInvisibleTimeProcessor(final BrokerController brokerController) {
this.brokerController = brokerController;
- this.reviveTopic = PopAckConstants.REVIVE_TOPIC + this.brokerController.getBrokerConfig().getBrokerClusterName();
-
+ this.reviveTopic = PopAckConstants.buildClusterReviveTopic(this.brokerController.getBrokerConfig().getBrokerClusterName());
}
@Override
- public RemotingCommand processRequest(final ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
+ public RemotingCommand processRequest(final ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
return this.processRequest(ctx.channel(), request, true);
}
@@ -65,7 +65,8 @@ public class ChangeInvisibleTimeProcessor implements NettyRequestProcessor {
return false;
}
- private RemotingCommand processRequest(final Channel channel, RemotingCommand request, boolean brokerAllowSuspend) throws RemotingCommandException {
+ private RemotingCommand processRequest(final Channel channel, RemotingCommand request,
+ boolean brokerAllowSuspend) throws RemotingCommandException {
final ChangeInvisibleTimeRequestHeader requestHeader = (ChangeInvisibleTimeRequestHeader) request.decodeCommandCustomHeader(ChangeInvisibleTimeRequestHeader.class);
RemotingCommand response = RemotingCommand.createResponseCommand(ChangeInvisibleTimeResponseHeader.class);
response.setCode(ResponseCode.SUCCESS);
@@ -98,7 +99,7 @@ public class ChangeInvisibleTimeProcessor implements NettyRequestProcessor {
// add new ck
long now = System.currentTimeMillis();
- PutMessageResult ckResult = appendCheckPoint(requestHeader, ExtraInfoUtil.getReviveQid(extraInfo), requestHeader.getQueueId(), requestHeader.getOffset(), now);
+ PutMessageResult ckResult = appendCheckPoint(requestHeader, ExtraInfoUtil.getReviveQid(extraInfo), requestHeader.getQueueId(), requestHeader.getOffset(), now, ExtraInfoUtil.getBrokerName(extraInfo));
if (ckResult.getPutMessageStatus() != PutMessageStatus.PUT_OK
&& ckResult.getPutMessageStatus() != PutMessageStatus.FLUSH_DISK_TIMEOUT
@@ -133,9 +134,13 @@ public class ChangeInvisibleTimeProcessor implements NettyRequestProcessor {
ackMsg.setTopic(requestHeader.getTopic());
ackMsg.setQueueId(requestHeader.getQueueId());
ackMsg.setPopTime(ExtraInfoUtil.getPopTime(extraInfo));
+ ackMsg.setBrokerName(ExtraInfoUtil.getBrokerName(extraInfo));
int rqId = ExtraInfoUtil.getReviveQid(extraInfo);
+ this.brokerController.getBrokerStatsManager().incBrokerAckNums(1);
+ this.brokerController.getBrokerStatsManager().incGroupAckNums(requestHeader.getConsumerGroup(), requestHeader.getTopic(), 1);
+
if (brokerController.getPopMessageProcessor().getPopBufferMergeService().addAk(rqId, ackMsg)) {
return;
}
@@ -150,7 +155,7 @@ public class ChangeInvisibleTimeProcessor implements NettyRequestProcessor {
MsgUtil.setMessageDeliverTime(this.brokerController, msgInner, ExtraInfoUtil.getPopTime(extraInfo) + ExtraInfoUtil.getInvisibleTime(extraInfo));
msgInner.getProperties().put(MessageConst.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX, PopMessageProcessor.genAckUniqueId(ackMsg));
msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgInner.getProperties()));
- PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner);
+ PutMessageResult putMessageResult = this.brokerController.getEscapeBridge().putMessageToSpecificQueue(msgInner);
if (putMessageResult.getPutMessageStatus() != PutMessageStatus.PUT_OK
&& putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_DISK_TIMEOUT
&& putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_SLAVE_TIMEOUT
@@ -159,7 +164,8 @@ public class ChangeInvisibleTimeProcessor implements NettyRequestProcessor {
}
}
- private PutMessageResult appendCheckPoint(final ChangeInvisibleTimeRequestHeader requestHeader, int reviveQid, int queueId, long offset, long popTime) {
+ private PutMessageResult appendCheckPoint(final ChangeInvisibleTimeRequestHeader requestHeader, int reviveQid,
+ int queueId, long offset, long popTime, String brokerName) {
// add check point msg to revive log
MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
msgInner.setTopic(reviveTopic);
@@ -187,7 +193,12 @@ public class ChangeInvisibleTimeProcessor implements NettyRequestProcessor {
if (brokerController.getBrokerConfig().isEnablePopLog()) {
POP_LOGGER.info("change Invisible , appendCheckPoint, topic {}, queueId {},reviveId {}, cid {}, startOffset {}, rt {}, result {}", requestHeader.getTopic(), queueId, reviveQid, requestHeader.getConsumerGroup(), offset,
- ck.getReviveTime(), putMessageResult);
+ ck.getReviveTime(), putMessageResult);
+ }
+
+ if (putMessageResult != null && putMessageResult.isOk()) {
+ this.brokerController.getBrokerStatsManager().incBrokerCkNums(1);
+ this.brokerController.getBrokerStatsManager().incGroupCkNums(requestHeader.getConsumerGroup(), requestHeader.getTopic(), 1);
}
return putMessageResult;
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/ClientManageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/ClientManageProcessor.java
index aa7d0a3..3a453b6 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/ClientManageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/ClientManageProcessor.java
@@ -28,6 +28,7 @@ import org.apache.rocketmq.common.protocol.ResponseCode;
import org.apache.rocketmq.common.protocol.body.CheckClientRequestBody;
import org.apache.rocketmq.common.protocol.header.UnregisterClientRequestHeader;
import org.apache.rocketmq.common.protocol.header.UnregisterClientResponseHeader;
+import org.apache.rocketmq.common.protocol.heartbeat.ConsumeType;
import org.apache.rocketmq.common.protocol.heartbeat.ConsumerData;
import org.apache.rocketmq.common.protocol.heartbeat.HeartbeatData;
import org.apache.rocketmq.common.protocol.heartbeat.ProducerData;
@@ -40,11 +41,10 @@ import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
-import org.apache.rocketmq.remoting.netty.AsyncNettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-public class ClientManageProcessor extends AsyncNettyRequestProcessor implements NettyRequestProcessor {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+public class ClientManageProcessor implements NettyRequestProcessor {
+ private static final InternalLogger LOGGER = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private final BrokerController brokerController;
public ClientManageProcessor(final BrokerController brokerController) {
@@ -82,39 +82,54 @@ public class ClientManageProcessor extends AsyncNettyRequestProcessor implements
request.getVersion()
);
- for (ConsumerData data : heartbeatData.getConsumerDataSet()) {
+ for (ConsumerData consumerData : heartbeatData.getConsumerDataSet()) {
+ //Reject the PullConsumer
+ if (brokerController.getBrokerConfig().isRejectPullConsumerEnable()) {
+ if (ConsumeType.CONSUME_ACTIVELY == consumerData.getConsumeType()) {
+ continue;
+ }
+ }
+
+ boolean hasOrderTopicSub = false;
+
+ for (final SubscriptionData subscriptionData : consumerData.getSubscriptionDataSet()) {
+ if (this.brokerController.getTopicConfigManager().isOrderTopic(subscriptionData.getTopic())) {
+ hasOrderTopicSub = true;
+ break;
+ }
+ }
+
SubscriptionGroupConfig subscriptionGroupConfig =
this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig(
- data.getGroupName());
+ consumerData.getGroupName());
boolean isNotifyConsumerIdsChangedEnable = true;
if (null != subscriptionGroupConfig) {
isNotifyConsumerIdsChangedEnable = subscriptionGroupConfig.isNotifyConsumerIdsChangedEnable();
int topicSysFlag = 0;
- if (data.isUnitMode()) {
+ if (consumerData.isUnitMode()) {
topicSysFlag = TopicSysFlag.buildSysFlag(false, true);
}
- String newTopic = MixAll.getRetryTopic(data.getGroupName());
+ String newTopic = MixAll.getRetryTopic(consumerData.getGroupName());
this.brokerController.getTopicConfigManager().createTopicInSendMessageBackMethod(
newTopic,
subscriptionGroupConfig.getRetryQueueNums(),
- PermName.PERM_WRITE | PermName.PERM_READ, topicSysFlag);
+ PermName.PERM_WRITE | PermName.PERM_READ, hasOrderTopicSub, topicSysFlag);
}
boolean changed = this.brokerController.getConsumerManager().registerConsumer(
- data.getGroupName(),
+ consumerData.getGroupName(),
clientChannelInfo,
- data.getConsumeType(),
- data.getMessageModel(),
- data.getConsumeFromWhere(),
- data.getSubscriptionDataSet(),
+ consumerData.getConsumeType(),
+ consumerData.getMessageModel(),
+ consumerData.getConsumeFromWhere(),
+ consumerData.getSubscriptionDataSet(),
isNotifyConsumerIdsChangedEnable
);
if (changed) {
- log.info("registerConsumer info changed {} {}",
- data.toString(),
- RemotingHelper.parseChannelRemoteAddr(ctx.channel())
- );
+ LOGGER.info(
+ "ClientManageProcessor: registerConsumer info changed, SDK address={}, consumerData={}",
+ RemotingHelper.parseChannelRemoteAddr(ctx.channel()), consumerData.toString());
}
}
@@ -190,7 +205,7 @@ public class ClientManageProcessor extends AsyncNettyRequestProcessor implements
try {
FilterFactory.INSTANCE.get(subscriptionData.getExpressionType()).compile(subscriptionData.getSubString());
} catch (Exception e) {
- log.warn("Client {}@{} filter message, but failed to compile expression! sub={}, error={}",
+ LOGGER.warn("Client {}@{} filter message, but failed to compile expression! sub={}, error={}",
requestBody.getClientId(), requestBody.getGroup(), requestBody.getSubscriptionData(), e.getMessage());
response.setCode(ResponseCode.SUBSCRIPTION_PARSE_FAILED);
response.setRemark(e.getMessage());
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/ConsumerManageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/ConsumerManageProcessor.java
index 31a7993..afa1aa4 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/ConsumerManageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/ConsumerManageProcessor.java
@@ -17,6 +17,7 @@
package org.apache.rocketmq.broker.processor;
import io.netty.channel.ChannelHandlerContext;
+import java.util.Set;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.broker.client.ConsumerGroupInfo;
import org.apache.rocketmq.common.constant.LoggerName;
@@ -40,7 +41,6 @@ import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
-import org.apache.rocketmq.remoting.netty.AsyncNettyRequestProcessor;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
@@ -48,9 +48,8 @@ import java.util.List;
import static org.apache.rocketmq.remoting.protocol.RemotingCommand.buildErrorResponse;
-public class ConsumerManageProcessor extends AsyncNettyRequestProcessor implements NettyRequestProcessor {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
-
+public class ConsumerManageProcessor implements NettyRequestProcessor {
+ private static final InternalLogger LOGGER = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private final BrokerController brokerController;
public ConsumerManageProcessor(final BrokerController brokerController) {
@@ -99,11 +98,11 @@ public class ConsumerManageProcessor extends AsyncNettyRequestProcessor implemen
response.setRemark(null);
return response;
} else {
- log.warn("getAllClientId failed, {} {}", requestHeader.getConsumerGroup(),
+ LOGGER.warn("getAllClientId failed, {} {}", requestHeader.getConsumerGroup(),
RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
}
} else {
- log.warn("getConsumerGroupInfo failed, {} {}", requestHeader.getConsumerGroup(),
+ LOGGER.warn("getConsumerGroupInfo failed, {} {}", requestHeader.getConsumerGroup(),
RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
}
@@ -156,10 +155,17 @@ public class ConsumerManageProcessor extends AsyncNettyRequestProcessor implemen
if (rewriteResult != null) {
return rewriteResult;
}
- this.brokerController.getConsumerOffsetManager().commitOffset(RemotingHelper.parseChannelRemoteAddr(ctx.channel()), requestHeader.getConsumerGroup(),
- requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getCommitOffset());
- response.setCode(ResponseCode.SUCCESS);
- response.setRemark(null);
+ Set<String> topicSets = this.brokerController.getTopicConfigManager().getTopicConfigTable().keySet();
+ if (topicSets.contains(requestHeader.getTopic())) {
+ this.brokerController.getConsumerOffsetManager().commitOffset(RemotingHelper.parseChannelRemoteAddr(ctx.channel()), requestHeader.getConsumerGroup(),
+ requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getCommitOffset());
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+ } else {
+ response.setCode(ResponseCode.TOPIC_NOT_EXIST);
+ response.setRemark("Topic " + requestHeader.getTopic() + " not exist!");
+ }
+
return response;
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/DefaultPullMessageResultHandler.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/DefaultPullMessageResultHandler.java
new file mode 100644
index 0000000..0e6a112
--- /dev/null
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/DefaultPullMessageResultHandler.java
@@ -0,0 +1,244 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.rocketmq.broker.processor;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.FileRegion;
+import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.broker.longpolling.PullRequest;
+import org.apache.rocketmq.broker.pagecache.ManyMessageTransfer;
+import org.apache.rocketmq.broker.plugin.PullMessageResultHandler;
+import org.apache.rocketmq.common.TopicFilterType;
+import org.apache.rocketmq.common.constant.LoggerName;
+import org.apache.rocketmq.common.message.MessageDecoder;
+import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.protocol.header.PullMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.header.PullMessageResponseHeader;
+import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData;
+import org.apache.rocketmq.common.protocol.topic.OffsetMovedEvent;
+import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
+import org.apache.rocketmq.common.sysflag.MessageSysFlag;
+import org.apache.rocketmq.common.sysflag.PullSysFlag;
+import org.apache.rocketmq.common.topic.TopicValidator;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.logging.InternalLoggerFactory;
+import org.apache.rocketmq.remoting.common.RemotingUtil;
+import org.apache.rocketmq.remoting.protocol.RemotingCommand;
+import org.apache.rocketmq.store.GetMessageResult;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
+import org.apache.rocketmq.store.MessageFilter;
+import org.apache.rocketmq.store.PutMessageResult;
+import org.apache.rocketmq.store.config.BrokerRole;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+public class DefaultPullMessageResultHandler implements PullMessageResultHandler {
+
+ protected static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ protected final BrokerController brokerController;
+
+ public DefaultPullMessageResultHandler(final BrokerController brokerController) {
+ this.brokerController = brokerController;
+ }
+
+ @Override
+ public RemotingCommand handle(final GetMessageResult getMessageResult,
+ final RemotingCommand request,
+ final PullMessageRequestHeader requestHeader,
+ final Channel channel,
+ final SubscriptionData subscriptionData,
+ final SubscriptionGroupConfig subscriptionGroupConfig,
+ final boolean brokerAllowSuspend,
+ final MessageFilter messageFilter,
+ RemotingCommand response) {
+
+ final PullMessageResponseHeader responseHeader = (PullMessageResponseHeader) response.readCustomHeader();
+
+ switch (response.getCode()) {
+ case ResponseCode.SUCCESS:
+ this.brokerController.getBrokerStatsManager().incGroupGetNums(requestHeader.getConsumerGroup(), requestHeader.getTopic(),
+ getMessageResult.getMessageCount());
+
+ this.brokerController.getBrokerStatsManager().incGroupGetSize(requestHeader.getConsumerGroup(), requestHeader.getTopic(),
+ getMessageResult.getBufferTotalSize());
+
+ this.brokerController.getBrokerStatsManager().incBrokerGetNums(getMessageResult.getMessageCount());
+
+ if (!channelIsWritable(channel, requestHeader)) {
+ getMessageResult.release();
+ //ignore pull request
+ return null;
+ }
+
+ if (this.brokerController.getBrokerConfig().isTransferMsgByHeap()) {
+
+ final long beginTimeMills = this.brokerController.getMessageStore().now();
+ final byte[] r = this.readGetMessageResult(getMessageResult, requestHeader.getConsumerGroup(), requestHeader.getTopic(), requestHeader.getQueueId());
+ this.brokerController.getBrokerStatsManager().incGroupGetLatency(requestHeader.getConsumerGroup(),
+ requestHeader.getTopic(), requestHeader.getQueueId(),
+ (int) (this.brokerController.getMessageStore().now() - beginTimeMills));
+ response.setBody(r);
+ return response;
+ } else {
+ try {
+ FileRegion fileRegion =
+ new ManyMessageTransfer(response.encodeHeader(getMessageResult.getBufferTotalSize()), getMessageResult);
+ channel.writeAndFlush(fileRegion).addListener(new ChannelFutureListener() {
+ @Override
+ public void operationComplete(ChannelFuture future) throws Exception {
+ getMessageResult.release();
+ if (!future.isSuccess()) {
+ log.error("Fail to transfer messages from page cache to {}", channel.remoteAddress(), future.cause());
+ }
+ }
+ });
+ } catch (Throwable e) {
+ log.error("Error occurred when transferring messages from page cache", e);
+ getMessageResult.release();
+ }
+ return null;
+ }
+ case ResponseCode.PULL_NOT_FOUND:
+ final boolean hasSuspendFlag = PullSysFlag.hasSuspendFlag(requestHeader.getSysFlag());
+ final long suspendTimeoutMillisLong = hasSuspendFlag ? requestHeader.getSuspendTimeoutMillis() : 0;
+
+ if (brokerAllowSuspend && hasSuspendFlag) {
+ long pollingTimeMills = suspendTimeoutMillisLong;
+ if (!this.brokerController.getBrokerConfig().isLongPollingEnable()) {
+ pollingTimeMills = this.brokerController.getBrokerConfig().getShortPollingTimeMills();
+ }
+
+ String topic = requestHeader.getTopic();
+ long offset = requestHeader.getQueueOffset();
+ int queueId = requestHeader.getQueueId();
+ PullRequest pullRequest = new PullRequest(request, channel, pollingTimeMills,
+ this.brokerController.getMessageStore().now(), offset, subscriptionData, messageFilter);
+ this.brokerController.getPullRequestHoldService().suspendPullRequest(topic, queueId, pullRequest);
+ return null;
+ }
+ case ResponseCode.PULL_RETRY_IMMEDIATELY:
+ break;
+ case ResponseCode.PULL_OFFSET_MOVED:
+ if (this.brokerController.getMessageStoreConfig().getBrokerRole() != BrokerRole.SLAVE
+ || this.brokerController.getMessageStoreConfig().isOffsetCheckInSlave()) {
+ MessageQueue mq = new MessageQueue();
+ mq.setTopic(requestHeader.getTopic());
+ mq.setQueueId(requestHeader.getQueueId());
+ mq.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName());
+
+ OffsetMovedEvent event = new OffsetMovedEvent();
+ event.setConsumerGroup(requestHeader.getConsumerGroup());
+ event.setMessageQueue(mq);
+ event.setOffsetRequest(requestHeader.getQueueOffset());
+ event.setOffsetNew(getMessageResult.getNextBeginOffset());
+ log.warn(
+ "PULL_OFFSET_MOVED:correction offset. topic={}, groupId={}, requestOffset={}, newOffset={}, suggestBrokerId={}",
+ requestHeader.getTopic(), requestHeader.getConsumerGroup(), event.getOffsetRequest(), event.getOffsetNew(),
+ responseHeader.getSuggestWhichBrokerId());
+ } else {
+ responseHeader.setSuggestWhichBrokerId(subscriptionGroupConfig.getBrokerId());
+ response.setCode(ResponseCode.PULL_RETRY_IMMEDIATELY);
+ log.warn("PULL_OFFSET_MOVED:none correction. topic={}, groupId={}, requestOffset={}, suggestBrokerId={}",
+ requestHeader.getTopic(), requestHeader.getConsumerGroup(), requestHeader.getQueueOffset(),
+ responseHeader.getSuggestWhichBrokerId());
+ }
+
+ break;
+ default:
+ log.warn("[BUG] impossible result code of get message: {}", response.getCode());
+ assert false;
+ }
+
+ return response;
+ }
+
+ private boolean channelIsWritable(Channel channel, PullMessageRequestHeader requestHeader) {
+ if (this.brokerController.getBrokerConfig().isNetWorkFlowController()) {
+ if (!channel.isWritable()) {
+ log.warn("channel {} not writable ,cid {}", channel.remoteAddress(), requestHeader.getConsumerGroup());
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ protected byte[] readGetMessageResult(final GetMessageResult getMessageResult, final String group, final String topic,
+ final int queueId) {
+ final ByteBuffer byteBuffer = ByteBuffer.allocate(getMessageResult.getBufferTotalSize());
+
+ long storeTimestamp = 0;
+ try {
+ List<ByteBuffer> messageBufferList = getMessageResult.getMessageBufferList();
+ for (ByteBuffer bb : messageBufferList) {
+
+ byteBuffer.put(bb);
+ int sysFlag = bb.getInt(MessageDecoder.SYSFLAG_POSITION);
+// bornhost has the IPv4 ip if the MessageSysFlag.BORNHOST_V6_FLAG bit of sysFlag is 0
+// IPv4 host = ip(4 byte) + port(4 byte); IPv6 host = ip(16 byte) + port(4 byte)
+ int bornhostLength = (sysFlag & MessageSysFlag.BORNHOST_V6_FLAG) == 0 ? 8 : 20;
+ int msgStoreTimePos = 4 // 1 TOTALSIZE
+ + 4 // 2 MAGICCODE
+ + 4 // 3 BODYCRC
+ + 4 // 4 QUEUEID
+ + 4 // 5 FLAG
+ + 8 // 6 QUEUEOFFSET
+ + 8 // 7 PHYSICALOFFSET
+ + 4 // 8 SYSFLAG
+ + 8 // 9 BORNTIMESTAMP
+ + bornhostLength; // 10 BORNHOST
+ storeTimestamp = bb.getLong(msgStoreTimePos);
+ }
+ } finally {
+ getMessageResult.release();
+ }
+
+ this.brokerController.getBrokerStatsManager().recordDiskFallBehindTime(group, topic, queueId, this.brokerController.getMessageStore().now() - storeTimestamp);
+ return byteBuffer.array();
+ }
+
+ protected void generateOffsetMovedEvent(final OffsetMovedEvent event) {
+ try {
+ MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
+ msgInner.setTopic(TopicValidator.RMQ_SYS_OFFSET_MOVED_EVENT);
+ msgInner.setTags(event.getConsumerGroup());
+ msgInner.setDelayTimeLevel(0);
+ msgInner.setKeys(event.getConsumerGroup());
+ msgInner.setBody(event.encode());
+ msgInner.setFlag(0);
+ msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgInner.getProperties()));
+ msgInner.setTagsCode(MessageExtBrokerInner.tagsString2tagsCode(TopicFilterType.SINGLE_TAG, msgInner.getTags()));
+
+ msgInner.setQueueId(0);
+ msgInner.setSysFlag(0);
+ msgInner.setBornTimestamp(System.currentTimeMillis());
+ msgInner.setBornHost(RemotingUtil.string2SocketAddress(this.brokerController.getBrokerAddr()));
+ msgInner.setStoreHost(msgInner.getBornHost());
+
+ msgInner.setReconsumeTimes(0);
+
+ PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner);
+ } catch (Exception e) {
+ log.warn(String.format("generateOffsetMovedEvent Exception, %s", event.toString()), e);
+ }
+ }
+}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/EndTransactionProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/EndTransactionProcessor.java
index 41e7df3..8ac52a4 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/EndTransactionProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/EndTransactionProcessor.java
@@ -32,17 +32,16 @@ import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
-import org.apache.rocketmq.remoting.netty.AsyncNettyRequestProcessor;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
import org.apache.rocketmq.store.PutMessageResult;
import org.apache.rocketmq.store.config.BrokerRole;
/**
* EndTransaction processor: process commit and rollback message
*/
-public class EndTransactionProcessor extends AsyncNettyRequestProcessor implements NettyRequestProcessor {
+public class EndTransactionProcessor implements NettyRequestProcessor {
private static final InternalLogger LOGGER = InternalLoggerFactory.getLogger(LoggerName.TRANSACTION_LOGGER_NAME);
private final BrokerController brokerController;
@@ -231,7 +230,7 @@ public class EndTransactionProcessor extends AsyncNettyRequestProcessor implemen
response.setRemark(null);
break;
// Failed
- case CREATE_MAPEDFILE_FAILED:
+ case CREATE_MAPPED_FILE_FAILED:
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("Create mapped file failed.");
break;
@@ -244,7 +243,7 @@ public class EndTransactionProcessor extends AsyncNettyRequestProcessor implemen
response.setCode(ResponseCode.SERVICE_NOT_AVAILABLE);
response.setRemark("Service not available now.");
break;
- case OS_PAGECACHE_BUSY:
+ case OS_PAGE_CACHE_BUSY:
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("OS page cache busy, please try another machine");
break;
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/ForwardRequestProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/ForwardRequestProcessor.java
index cd93598..b0f0a05 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/ForwardRequestProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/ForwardRequestProcessor.java
@@ -21,11 +21,10 @@ import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
-import org.apache.rocketmq.remoting.netty.AsyncNettyRequestProcessor;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-public class ForwardRequestProcessor extends AsyncNettyRequestProcessor implements NettyRequestProcessor {
+public class ForwardRequestProcessor implements NettyRequestProcessor {
private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
private final BrokerController brokerController;
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/NotificationProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/NotificationProcessor.java
new file mode 100644
index 0000000..e007367
--- /dev/null
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/NotificationProcessor.java
@@ -0,0 +1,318 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.rocketmq.broker.processor;
+
+import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.broker.longpolling.NotificationRequest;
+import org.apache.rocketmq.common.AbstractBrokerRunnable;
+import org.apache.rocketmq.common.KeyBuilder;
+import org.apache.rocketmq.common.TopicConfig;
+import org.apache.rocketmq.common.constant.LoggerName;
+import org.apache.rocketmq.common.constant.PermName;
+import org.apache.rocketmq.common.help.FAQUrl;
+import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.protocol.header.NotificationRequestHeader;
+import org.apache.rocketmq.common.protocol.header.NotificationResponseHeader;
+import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.logging.InternalLoggerFactory;
+import org.apache.rocketmq.remoting.common.RemotingHelper;
+import org.apache.rocketmq.remoting.exception.RemotingCommandException;
+import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
+import org.apache.rocketmq.remoting.netty.RequestTask;
+import org.apache.rocketmq.remoting.protocol.RemotingCommand;
+
+public class NotificationProcessor implements NettyRequestProcessor {
+ private static final InternalLogger POP_LOGGER = InternalLoggerFactory.getLogger(LoggerName.ROCKETMQ_POP_LOGGER_NAME);
+ private final BrokerController brokerController;
+ private Random random = new Random(System.currentTimeMillis());
+ private static final String BORN_TIME = "bornTime";
+ private ConcurrentLinkedHashMap<String, ArrayBlockingQueue<NotificationRequest>> pollingMap = new ConcurrentLinkedHashMap.Builder<String, ArrayBlockingQueue<NotificationRequest>>().maximumWeightedCapacity(100000).build();
+ private Thread checkNotificationPollingThread;
+
+ public NotificationProcessor(final BrokerController brokerController) {
+ this.brokerController = brokerController;
+ this.checkNotificationPollingThread = new Thread(new AbstractBrokerRunnable(brokerController.getBrokerConfig()) {
+ @Override public void run2() {
+ while (true) {
+ if (Thread.currentThread().isInterrupted()) {
+ break;
+ }
+ try {
+ Thread.sleep(2000L);
+ Collection<ArrayBlockingQueue<NotificationRequest>> pops = pollingMap.values();
+ for (ArrayBlockingQueue<NotificationRequest> popQ : pops) {
+ NotificationRequest tmPopRequest = popQ.peek();
+ while (tmPopRequest != null) {
+ if (tmPopRequest.isTimeout()) {
+ tmPopRequest = popQ.poll();
+ if (tmPopRequest == null) {
+ break;
+ }
+ if (!tmPopRequest.isTimeout()) {
+ POP_LOGGER.info("not timeout , but wakeUp Notification in advance: {}", tmPopRequest);
+ wakeUp(tmPopRequest, false);
+ break;
+ } else {
+ POP_LOGGER.info("timeout , wakeUp Notification : {}", tmPopRequest);
+ wakeUp(tmPopRequest, false);
+ tmPopRequest = popQ.peek();
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ } catch (InterruptedException e) {
+ break;
+ } catch (Exception e) {
+ POP_LOGGER.error("checkNotificationPolling error", e);
+ }
+ }
+ }
+ });
+ this.checkNotificationPollingThread.setDaemon(true);
+ this.checkNotificationPollingThread.setName("checkNotificationPolling");
+ this.checkNotificationPollingThread.start();
+ }
+
+ public void shutdown() {
+ this.checkNotificationPollingThread.interrupt();
+ }
+
+ @Override
+ public RemotingCommand processRequest(final ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ request.addExtField(BORN_TIME, String.valueOf(System.currentTimeMillis()));
+ return this.processRequest(ctx.channel(), request);
+ }
+
+ @Override
+ public boolean rejectRequest() {
+ return false;
+ }
+
+ public void notifyMessageArriving(final String topic, final int queueId) {
+ ArrayBlockingQueue<NotificationRequest> remotingCommands = pollingMap.get(KeyBuilder.buildPollingNotificationKey(topic, -1));
+ if (remotingCommands != null) {
+ List<NotificationRequest> c = new ArrayList<>();
+ remotingCommands.drainTo(c);
+ for (NotificationRequest notificationRequest : c) {
+ POP_LOGGER.info("new msg arrive , wakeUp : {}", notificationRequest);
+ wakeUp(notificationRequest, true);
+
+ }
+ }
+ remotingCommands = pollingMap.get(KeyBuilder.buildPollingNotificationKey(topic, queueId));
+ if (remotingCommands != null) {
+ List<NotificationRequest> c = new ArrayList<>();
+ remotingCommands.drainTo(c);
+ for (NotificationRequest notificationRequest : c) {
+ POP_LOGGER.info("new msg arrive , wakeUp : {}", notificationRequest);
+ wakeUp(notificationRequest, true);
+ }
+ }
+ }
+
+ private void wakeUp(final NotificationRequest request, final boolean hasMsg) {
+ if (request == null || !request.complete()) {
+ return;
+ }
+ if (!request.getChannel().isActive()) {
+ return;
+ }
+ Runnable run = new Runnable() {
+ @Override
+ public void run() {
+ final RemotingCommand response = NotificationProcessor.this.responseNotification(request.getChannel(), hasMsg);
+
+ if (response != null) {
+ response.setOpaque(request.getRemotingCommand().getOpaque());
+ response.markResponseType();
+ try {
+ request.getChannel().writeAndFlush(response).addListener(new ChannelFutureListener() {
+ @Override
+ public void operationComplete(ChannelFuture future) throws Exception {
+ if (!future.isSuccess()) {
+ POP_LOGGER.error("ProcessRequestWrapper response to {} failed", future.channel().remoteAddress(), future.cause());
+ POP_LOGGER.error(request.toString());
+ POP_LOGGER.error(response.toString());
+ }
+ }
+ });
+ } catch (Throwable e) {
+ POP_LOGGER.error("ProcessRequestWrapper process request over, but response failed", e);
+ POP_LOGGER.error(request.toString());
+ POP_LOGGER.error(response.toString());
+ }
+ }
+ }
+ };
+ this.brokerController.getPullMessageExecutor().submit(new RequestTask(run, request.getChannel(), request.getRemotingCommand()));
+ }
+
+ public RemotingCommand responseNotification(final Channel channel, boolean hasMsg) {
+ RemotingCommand response = RemotingCommand.createResponseCommand(NotificationResponseHeader.class);
+ final NotificationResponseHeader responseHeader = (NotificationResponseHeader) response.readCustomHeader();
+ responseHeader.setHasMsg(hasMsg);
+ response.setCode(ResponseCode.SUCCESS);
+ return response;
+ }
+
+ private RemotingCommand processRequest(final Channel channel, RemotingCommand request)
+ throws RemotingCommandException {
+ RemotingCommand response = RemotingCommand.createResponseCommand(NotificationResponseHeader.class);
+ final NotificationResponseHeader responseHeader = (NotificationResponseHeader) response.readCustomHeader();
+ final NotificationRequestHeader requestHeader =
+ (NotificationRequestHeader) request.decodeCommandCustomHeader(NotificationRequestHeader.class);
+
+ response.setOpaque(request.getOpaque());
+
+ if (!PermName.isReadable(this.brokerController.getBrokerConfig().getBrokerPermission())) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark(String.format("the broker[%s] peeking message is forbidden", this.brokerController.getBrokerConfig().getBrokerIP1()));
+ return response;
+ }
+
+ TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(requestHeader.getTopic());
+ if (null == topicConfig) {
+ POP_LOGGER.error("The topic {} not exist, consumer: {} ", requestHeader.getTopic(), RemotingHelper.parseChannelRemoteAddr(channel));
+ response.setCode(ResponseCode.TOPIC_NOT_EXIST);
+ response.setRemark(String.format("topic[%s] not exist, apply first please! %s", requestHeader.getTopic(), FAQUrl.suggestTodo(FAQUrl.APPLY_TOPIC_URL)));
+ return response;
+ }
+
+ if (!PermName.isReadable(topicConfig.getPerm())) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark("the topic[" + requestHeader.getTopic() + "] peeking message is forbidden");
+ return response;
+ }
+
+ if (requestHeader.getQueueId() >= topicConfig.getReadQueueNums()) {
+ String errorInfo = String.format("queueId[%d] is illegal, topic:[%s] topicConfig.readQueueNums:[%d] consumer:[%s]",
+ requestHeader.getQueueId(), requestHeader.getTopic(), topicConfig.getReadQueueNums(), channel.remoteAddress());
+ POP_LOGGER.warn(errorInfo);
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark(errorInfo);
+ return response;
+ }
+ SubscriptionGroupConfig subscriptionGroupConfig = this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig(requestHeader.getConsumerGroup());
+ if (null == subscriptionGroupConfig) {
+ response.setCode(ResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST);
+ response.setRemark(String.format("subscription group [%s] does not exist, %s", requestHeader.getConsumerGroup(), FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST)));
+ return response;
+ }
+
+ if (!subscriptionGroupConfig.isConsumeEnable()) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark("subscription group no permission, " + requestHeader.getConsumerGroup());
+ return response;
+ }
+ int randomQ = random.nextInt(100);
+ boolean hasMsg = false;
+ boolean needRetry = randomQ % 5 == 0;
+ if (needRetry) {
+ TopicConfig retryTopicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup()));
+ if (retryTopicConfig != null) {
+ for (int i = 0; i < retryTopicConfig.getReadQueueNums(); i++) {
+ int queueId = (randomQ + i) % retryTopicConfig.getReadQueueNums();
+ hasMsg = hasMsgFromQueue(true, requestHeader, queueId);
+ }
+ }
+ }
+ if (!hasMsg && requestHeader.getQueueId() < 0) {
+ // read all queue
+ for (int i = 0; i < topicConfig.getReadQueueNums(); i++) {
+ int queueId = (randomQ + i) % topicConfig.getReadQueueNums();
+ hasMsg = hasMsgFromQueue(false, requestHeader, queueId);
+ if (hasMsg) {
+ break;
+ }
+ }
+ } else {
+ int queueId = requestHeader.getQueueId();
+ hasMsg = hasMsgFromQueue(false, requestHeader, queueId);
+ }
+
+ if (!hasMsg) {
+ if (polling(channel, request, requestHeader)) {
+ return null;
+ }
+ }
+ response.setCode(ResponseCode.SUCCESS);
+ responseHeader.setHasMsg(hasMsg);
+ return response;
+ }
+
+ private boolean hasMsgFromQueue(boolean isRetry, NotificationRequestHeader requestHeader, int queueId) {
+ String topic = isRetry ? KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup()) : requestHeader.getTopic();
+ long offset = getPopOffset(topic, requestHeader.getConsumerGroup(), queueId);
+ long restNum = this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, queueId) - offset;
+ return restNum > 0;
+ }
+
+ private long getPopOffset(String topic, String cid, int queueId) {
+ long offset = this.brokerController.getConsumerOffsetManager().queryOffset(cid, topic, queueId);
+ if (offset < 0) {
+ offset = this.brokerController.getMessageStore().getMinOffsetInQueue(topic, queueId);
+ }
+ long bufferOffset = this.brokerController.getPopMessageProcessor().getPopBufferMergeService()
+ .getLatestOffset(topic, cid, queueId);
+ if (bufferOffset < 0) {
+ return offset;
+ } else {
+ return bufferOffset > offset ? bufferOffset : offset;
+ }
+ }
+
+ private boolean polling(final Channel channel, RemotingCommand remotingCommand,
+ final NotificationRequestHeader requestHeader) {
+ if (requestHeader.getPollTime() <= 0) {
+ return false;
+ }
+
+ long expired = requestHeader.getBornTime() + requestHeader.getPollTime();
+ final NotificationRequest request = new NotificationRequest(remotingCommand, channel, expired);
+ boolean result = false;
+ if (!request.isTimeout()) {
+ String key = KeyBuilder.buildPollingNotificationKey(requestHeader.getTopic(), requestHeader.getQueueId());
+ ArrayBlockingQueue<NotificationRequest> queue = pollingMap.get(key);
+ if (queue == null) {
+ queue = new ArrayBlockingQueue<>(this.brokerController.getBrokerConfig().getPopPollingSize());
+ pollingMap.put(key, queue);
+ result = queue.offer(request);
+ } else {
+ result = queue.offer(request);
+ }
+ }
+ POP_LOGGER.info("polling {}, result {}", remotingCommand, result);
+ return result;
+
+ }
+}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/PeekMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/PeekMessageProcessor.java
new file mode 100644
index 0000000..7cc15f2
--- /dev/null
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/PeekMessageProcessor.java
@@ -0,0 +1,271 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.rocketmq.broker.processor;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.FileRegion;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.broker.pagecache.ManyMessageTransfer;
+import org.apache.rocketmq.common.KeyBuilder;
+import org.apache.rocketmq.common.TopicConfig;
+import org.apache.rocketmq.common.constant.LoggerName;
+import org.apache.rocketmq.common.constant.PermName;
+import org.apache.rocketmq.common.help.FAQUrl;
+import org.apache.rocketmq.common.message.MessageDecoder;
+import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.protocol.header.PeekMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.header.PopMessageResponseHeader;
+import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.logging.InternalLoggerFactory;
+import org.apache.rocketmq.remoting.common.RemotingHelper;
+import org.apache.rocketmq.remoting.exception.RemotingCommandException;
+import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
+import org.apache.rocketmq.remoting.protocol.RemotingCommand;
+import org.apache.rocketmq.store.GetMessageResult;
+import org.apache.rocketmq.store.GetMessageStatus;
+import org.apache.rocketmq.store.SelectMappedBufferResult;
+
+public class PeekMessageProcessor implements NettyRequestProcessor {
+ private static final InternalLogger LOG = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
+ private final BrokerController brokerController;
+ private Random random = new Random(System.currentTimeMillis());
+
+ public PeekMessageProcessor(final BrokerController brokerController) {
+ this.brokerController = brokerController;
+ }
+
+ @Override
+ public RemotingCommand processRequest(final ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ return this.processRequest(ctx.channel(), request, true);
+ }
+
+ @Override
+ public boolean rejectRequest() {
+ return false;
+ }
+
+ private RemotingCommand processRequest(final Channel channel, RemotingCommand request, boolean brokerAllowSuspend)
+ throws RemotingCommandException {
+ RemotingCommand response = RemotingCommand.createResponseCommand(PopMessageResponseHeader.class);
+ final PopMessageResponseHeader responseHeader = (PopMessageResponseHeader) response.readCustomHeader();
+ final PeekMessageRequestHeader requestHeader =
+ (PeekMessageRequestHeader) request.decodeCommandCustomHeader(PeekMessageRequestHeader.class);
+
+ response.setOpaque(request.getOpaque());
+
+ if (!PermName.isReadable(this.brokerController.getBrokerConfig().getBrokerPermission())) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark(String.format("the broker[%s] peeking message is forbidden", this.brokerController.getBrokerConfig().getBrokerIP1()));
+ return response;
+ }
+
+ TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(requestHeader.getTopic());
+ if (null == topicConfig) {
+ LOG.error("The topic {} not exist, consumer: {} ", requestHeader.getTopic(), RemotingHelper.parseChannelRemoteAddr(channel));
+ response.setCode(ResponseCode.TOPIC_NOT_EXIST);
+ response.setRemark(String.format("topic[%s] not exist, apply first please! %s", requestHeader.getTopic(), FAQUrl.suggestTodo(FAQUrl.APPLY_TOPIC_URL)));
+ return response;
+ }
+
+ if (!PermName.isReadable(topicConfig.getPerm())) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark("the topic[" + requestHeader.getTopic() + "] peeking message is forbidden");
+ return response;
+ }
+
+ if (requestHeader.getQueueId() >= topicConfig.getReadQueueNums()) {
+ String errorInfo = String.format("queueId[%d] is illegal, topic:[%s] topicConfig.readQueueNums:[%d] consumer:[%s]",
+ requestHeader.getQueueId(), requestHeader.getTopic(), topicConfig.getReadQueueNums(), channel.remoteAddress());
+ LOG.warn(errorInfo);
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark(errorInfo);
+ return response;
+ }
+ SubscriptionGroupConfig subscriptionGroupConfig = this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig(requestHeader.getConsumerGroup());
+ if (null == subscriptionGroupConfig) {
+ response.setCode(ResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST);
+ response.setRemark(String.format("subscription group [%s] does not exist, %s", requestHeader.getConsumerGroup(), FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST)));
+ return response;
+ }
+
+ if (!subscriptionGroupConfig.isConsumeEnable()) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark("subscription group no permission, " + requestHeader.getConsumerGroup());
+ return response;
+ }
+ int randomQ = random.nextInt(100);
+ int reviveQid = randomQ % this.brokerController.getBrokerConfig().getReviveQueueNum();
+ int commercialSizePerMsg = this.brokerController.getBrokerConfig().getCommercialSizePerMsg();
+ GetMessageResult getMessageResult = new GetMessageResult(commercialSizePerMsg);
+ boolean needRetry = randomQ % 5 == 0;
+ long popTime = System.currentTimeMillis();
+ long restNum = 0;
+ if (needRetry) {
+ TopicConfig retryTopicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup()));
+ if (retryTopicConfig != null) {
+ for (int i = 0; i < retryTopicConfig.getReadQueueNums(); i++) {
+ int queueId = (randomQ + i) % retryTopicConfig.getReadQueueNums();
+ restNum = peekMsgFromQueue(true, getMessageResult, requestHeader, queueId, restNum, reviveQid, channel, popTime);
+ }
+ }
+ }
+ if (requestHeader.getQueueId() < 0) {
+ // read all queue
+ for (int i = 0; i < topicConfig.getReadQueueNums(); i++) {
+ int queueId = (randomQ + i) % topicConfig.getReadQueueNums();
+ restNum = peekMsgFromQueue(false, getMessageResult, requestHeader, queueId, restNum, reviveQid, channel, popTime);
+ }
+ } else {
+ int queueId = requestHeader.getQueueId();
+ restNum = peekMsgFromQueue(false, getMessageResult, requestHeader, queueId, restNum, reviveQid, channel, popTime);
+ }
+ // if not full , fetch retry again
+ if (!needRetry && getMessageResult.getMessageMapedList().size() < requestHeader.getMaxMsgNums()) {
+ TopicConfig retryTopicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup()));
+ if (retryTopicConfig != null) {
+ for (int i = 0; i < retryTopicConfig.getReadQueueNums(); i++) {
+ int queueId = (randomQ + i) % retryTopicConfig.getReadQueueNums();
+ restNum = peekMsgFromQueue(true, getMessageResult, requestHeader, queueId, restNum, reviveQid, channel, popTime);
+ }
+ }
+ }
+ if (!getMessageResult.getMessageBufferList().isEmpty()) {
+ response.setCode(ResponseCode.SUCCESS);
+ getMessageResult.setStatus(GetMessageStatus.FOUND);
+ } else {
+ response.setCode(ResponseCode.PULL_NOT_FOUND);
+ getMessageResult.setStatus(GetMessageStatus.NO_MESSAGE_IN_QUEUE);
+
+ }
+ responseHeader.setRestNum(restNum);
+ response.setRemark(getMessageResult.getStatus().name());
+ switch (response.getCode()) {
+ case ResponseCode.SUCCESS:
+
+ this.brokerController.getBrokerStatsManager().incGroupGetNums(requestHeader.getConsumerGroup(), requestHeader.getTopic(),
+ getMessageResult.getMessageCount());
+
+ this.brokerController.getBrokerStatsManager().incGroupGetSize(requestHeader.getConsumerGroup(), requestHeader.getTopic(),
+ getMessageResult.getBufferTotalSize());
+
+ this.brokerController.getBrokerStatsManager().incBrokerGetNums(getMessageResult.getMessageCount());
+ if (this.brokerController.getBrokerConfig().isTransferMsgByHeap()) {
+ final long beginTimeMills = this.brokerController.getMessageStore().now();
+ final byte[] r = this.readGetMessageResult(getMessageResult, requestHeader.getConsumerGroup(), requestHeader.getTopic(), requestHeader.getQueueId());
+ this.brokerController.getBrokerStatsManager().incGroupGetLatency(requestHeader.getConsumerGroup(),
+ requestHeader.getTopic(), requestHeader.getQueueId(),
+ (int) (this.brokerController.getMessageStore().now() - beginTimeMills));
+ response.setBody(r);
+ } else {
+ final GetMessageResult tmpGetMessageResult = getMessageResult;
+ try {
+ FileRegion fileRegion =
+ new ManyMessageTransfer(response.encodeHeader(getMessageResult.getBufferTotalSize()), getMessageResult);
+ channel.writeAndFlush(fileRegion).addListener(new ChannelFutureListener() {
+ @Override
+ public void operationComplete(ChannelFuture future) throws Exception {
+ tmpGetMessageResult.release();
+ if (!future.isSuccess()) {
+ LOG.error("Fail to transfer messages from page cache to {}", channel.remoteAddress(), future.cause());
+ }
+ }
+ });
+ } catch (Throwable e) {
+ LOG.error("Error occurred when transferring messages from page cache", e);
+ getMessageResult.release();
+ }
+
+ response = null;
+ }
+ break;
+ default:
+ assert false;
+ }
+ return response;
+ }
+
+ private long peekMsgFromQueue(boolean isRetry, GetMessageResult getMessageResult,
+ PeekMessageRequestHeader requestHeader, int queueId, long restNum, int reviveQid, Channel channel,
+ long popTime) {
+ String topic = isRetry ? KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup()) : requestHeader.getTopic();
+ GetMessageResult getMessageTmpResult;
+ long offset = getPopOffset(topic, requestHeader.getConsumerGroup(), queueId);
+ restNum = this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, queueId) - offset + restNum;
+ if (getMessageResult.getMessageMapedList().size() >= requestHeader.getMaxMsgNums()) {
+ return restNum;
+ }
+ getMessageTmpResult = this.brokerController.getMessageStore().getMessage(requestHeader.getConsumerGroup(), topic, queueId, offset,
+ requestHeader.getMaxMsgNums() - getMessageResult.getMessageMapedList().size(), null);
+ // maybe store offset is not correct.
+ if (GetMessageStatus.OFFSET_TOO_SMALL.equals(getMessageTmpResult.getStatus()) || GetMessageStatus.OFFSET_OVERFLOW_BADLY.equals(getMessageTmpResult.getStatus())) {
+ offset = getMessageTmpResult.getNextBeginOffset();
+ getMessageTmpResult = this.brokerController.getMessageStore().getMessage(requestHeader.getConsumerGroup(), topic, queueId, offset,
+ requestHeader.getMaxMsgNums() - getMessageResult.getMessageMapedList().size(), null);
+ }
+ if (getMessageTmpResult != null) {
+ for (SelectMappedBufferResult mapedBuffer : getMessageTmpResult.getMessageMapedList()) {
+ getMessageResult.addMessage(mapedBuffer);
+ }
+ }
+ return restNum;
+ }
+
+ private long getPopOffset(String topic, String cid, int queueId) {
+ long offset = this.brokerController.getConsumerOffsetManager().queryOffset(cid, topic, queueId);
+ if (offset < 0) {
+ offset = this.brokerController.getMessageStore().getMinOffsetInQueue(topic, queueId);
+ }
+ long bufferOffset = this.brokerController.getPopMessageProcessor().getPopBufferMergeService()
+ .getLatestOffset(topic, cid, queueId);
+ if (bufferOffset < 0) {
+ return offset;
+ } else {
+ return bufferOffset > offset ? bufferOffset : offset;
+ }
+ }
+
+ private byte[] readGetMessageResult(final GetMessageResult getMessageResult, final String group, final String topic,
+ final int queueId) {
+ final ByteBuffer byteBuffer = ByteBuffer.allocate(getMessageResult.getBufferTotalSize());
+
+ long storeTimestamp = 0;
+ try {
+ List<ByteBuffer> messageBufferList = getMessageResult.getMessageBufferList();
+ for (ByteBuffer bb : messageBufferList) {
+
+ byteBuffer.put(bb);
+ storeTimestamp = bb.getLong(MessageDecoder.MESSAGE_STORE_TIMESTAMP_POSITION);
+ }
+ } finally {
+ getMessageResult.release();
+ }
+
+ this.brokerController.getBrokerStatsManager().recordDiskFallBehindTime(group, topic, queueId, this.brokerController.getMessageStore().now() - storeTimestamp);
+ return byteBuffer.array();
+ }
+
+}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/PollingInfoProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/PollingInfoProcessor.java
new file mode 100644
index 0000000..827a8d6
--- /dev/null
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/PollingInfoProcessor.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.rocketmq.broker.processor;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import java.util.concurrent.ConcurrentSkipListSet;
+import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.broker.longpolling.PopRequest;
+import org.apache.rocketmq.common.KeyBuilder;
+import org.apache.rocketmq.common.TopicConfig;
+import org.apache.rocketmq.common.constant.LoggerName;
+import org.apache.rocketmq.common.constant.PermName;
+import org.apache.rocketmq.common.help.FAQUrl;
+import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.protocol.header.PollingInfoRequestHeader;
+import org.apache.rocketmq.common.protocol.header.PollingInfoResponseHeader;
+import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.logging.InternalLoggerFactory;
+import org.apache.rocketmq.remoting.common.RemotingHelper;
+import org.apache.rocketmq.remoting.exception.RemotingCommandException;
+import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
+import org.apache.rocketmq.remoting.protocol.RemotingCommand;
+
+public class PollingInfoProcessor implements NettyRequestProcessor {
+ private static final InternalLogger POP_LOGGER = InternalLoggerFactory.getLogger(LoggerName.ROCKETMQ_POP_LOGGER_NAME);
+ private final BrokerController brokerController;
+
+ public PollingInfoProcessor(final BrokerController brokerController) {
+ this.brokerController = brokerController;
+ }
+
+ @Override
+ public RemotingCommand processRequest(final ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+ return this.processRequest(ctx.channel(), request);
+ }
+
+ @Override
+ public boolean rejectRequest() {
+ return false;
+ }
+
+ private RemotingCommand processRequest(final Channel channel, RemotingCommand request)
+ throws RemotingCommandException {
+ RemotingCommand response = RemotingCommand.createResponseCommand(PollingInfoResponseHeader.class);
+ final PollingInfoResponseHeader responseHeader = (PollingInfoResponseHeader) response.readCustomHeader();
+ final PollingInfoRequestHeader requestHeader =
+ (PollingInfoRequestHeader) request.decodeCommandCustomHeader(PollingInfoRequestHeader.class);
+
+ response.setOpaque(request.getOpaque());
+
+ if (!PermName.isReadable(this.brokerController.getBrokerConfig().getBrokerPermission())) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark(String.format("the broker[%s] peeking message is forbidden", this.brokerController.getBrokerConfig().getBrokerIP1()));
+ return response;
+ }
+
+ TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(requestHeader.getTopic());
+ if (null == topicConfig) {
+ POP_LOGGER.error("The topic {} not exist, consumer: {} ", requestHeader.getTopic(), RemotingHelper.parseChannelRemoteAddr(channel));
+ response.setCode(ResponseCode.TOPIC_NOT_EXIST);
+ response.setRemark(String.format("topic[%s] not exist, apply first please! %s", requestHeader.getTopic(), FAQUrl.suggestTodo(FAQUrl.APPLY_TOPIC_URL)));
+ return response;
+ }
+
+ if (!PermName.isReadable(topicConfig.getPerm())) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark("the topic[" + requestHeader.getTopic() + "] peeking message is forbidden");
+ return response;
+ }
+
+ if (requestHeader.getQueueId() >= topicConfig.getReadQueueNums()) {
+ String errorInfo = String.format("queueId[%d] is illegal, topic:[%s] topicConfig.readQueueNums:[%d] consumer:[%s]",
+ requestHeader.getQueueId(), requestHeader.getTopic(), topicConfig.getReadQueueNums(), channel.remoteAddress());
+ POP_LOGGER.warn(errorInfo);
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark(errorInfo);
+ return response;
+ }
+ SubscriptionGroupConfig subscriptionGroupConfig = this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig(requestHeader.getConsumerGroup());
+ if (null == subscriptionGroupConfig) {
+ response.setCode(ResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST);
+ response.setRemark(String.format("subscription group [%s] does not exist, %s", requestHeader.getConsumerGroup(), FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST)));
+ return response;
+ }
+
+ if (!subscriptionGroupConfig.isConsumeEnable()) {
+ response.setCode(ResponseCode.NO_PERMISSION);
+ response.setRemark("subscription group no permission, " + requestHeader.getConsumerGroup());
+ return response;
+ }
+ String key = KeyBuilder.buildPollingKey(requestHeader.getTopic(), requestHeader.getConsumerGroup(), requestHeader.getQueueId());
+ ConcurrentSkipListSet<PopRequest> queue = this.brokerController.getPopMessageProcessor().getPollingMap().get(key);
+ if (queue != null) {
+ responseHeader.setPollingNum(queue.size());
+ } else {
+ responseHeader.setPollingNum(0);
+ }
+ response.setCode(ResponseCode.SUCCESS);
+ return response;
+ }
+
+}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/PopBufferMergeService.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/PopBufferMergeService.java
index 615a70e..cee84e6 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/PopBufferMergeService.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/PopBufferMergeService.java
@@ -33,7 +33,7 @@ import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.utils.DataConverter;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
-import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
import org.apache.rocketmq.store.PutMessageResult;
import org.apache.rocketmq.store.PutMessageStatus;
import org.apache.rocketmq.store.config.BrokerRole;
@@ -43,9 +43,9 @@ import org.apache.rocketmq.store.pop.PopCheckPoint;
public class PopBufferMergeService extends ServiceThread {
private static final InternalLogger POP_LOGGER = InternalLoggerFactory.getLogger(LoggerName.ROCKETMQ_POP_LOGGER_NAME);
ConcurrentHashMap<String/*mergeKey*/, PopCheckPointWrapper>
- buffer = new ConcurrentHashMap<>(1024 * 16);
+ buffer = new ConcurrentHashMap<>(1024 * 16);
ConcurrentHashMap<String/*topic@cid@queueId*/, QueueWithTime<PopCheckPointWrapper>> commitOffsets =
- new ConcurrentHashMap<>();
+ new ConcurrentHashMap<>();
private volatile boolean serving = true;
private AtomicInteger counter = new AtomicInteger(0);
private int scanTimes = 0;
@@ -61,20 +61,25 @@ public class PopBufferMergeService extends ServiceThread {
private volatile boolean master = false;
public PopBufferMergeService(BrokerController brokerController, PopMessageProcessor popMessageProcessor) {
- super();
this.brokerController = brokerController;
this.popMessageProcessor = popMessageProcessor;
this.queueLockManager = popMessageProcessor.getQueueLockManager();
}
- private boolean checkAndSetMaster() {
+ private boolean isShouldRunning() {
+ if (this.brokerController.getBrokerConfig().isEnableSlaveActingMaster()) {
+ return true;
+ }
this.master = brokerController.getMessageStoreConfig().getBrokerRole() != BrokerRole.SLAVE;
return this.master;
}
@Override
public String getServiceName() {
- return "PopBufferMergeService";
+ if (this.brokerController != null && this.brokerController.getBrokerConfig().isInBrokerContainer()) {
+ return brokerController.getBrokerConfig().getLoggerIdentifier() + PopBufferMergeService.class.getSimpleName();
+ }
+ return PopBufferMergeService.class.getSimpleName();
}
@Override
@@ -82,11 +87,11 @@ public class PopBufferMergeService extends ServiceThread {
// scan
while (!this.isStopped()) {
try {
- if (!checkAndSetMaster()) {
+ if (!isShouldRunning()) {
// slave
this.waitForRunning(interval * 200 * 5);
POP_LOGGER.info("Broker is {}, {}, clear all data",
- brokerController.getMessageStoreConfig().getBrokerRole(), this.master);
+ brokerController.getMessageStoreConfig().getBrokerRole(), this.master);
this.buffer.clear();
this.commitOffsets.clear();
continue;
@@ -113,7 +118,7 @@ public class PopBufferMergeService extends ServiceThread {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
- if (!checkAndSetMaster()) {
+ if (!isShouldRunning()) {
return;
}
while (this.buffer.size() > 0 || totalSize() > 0) {
@@ -133,7 +138,7 @@ public class PopBufferMergeService extends ServiceThread {
// 2. ck is buffer(acked)
// 3. ck is buffer(not all acked), all ak are stored and ck is stored
if ((pointWrapper.isJustOffset() && pointWrapper.isCkStored()) || isCkDone(pointWrapper)
- || (isCkDoneForFinish(pointWrapper) && pointWrapper.isCkStored())) {
+ || (isCkDoneForFinish(pointWrapper) && pointWrapper.isCkStored())) {
if (commitOffset(pointWrapper)) {
queue.poll();
} else {
@@ -141,7 +146,7 @@ public class PopBufferMergeService extends ServiceThread {
}
} else {
if (System.currentTimeMillis() - pointWrapper.getCk().getPopTime()
- > brokerController.getBrokerConfig().getPopCkStayBufferTime() * 2) {
+ > brokerController.getBrokerConfig().getPopCkStayBufferTime() * 2) {
POP_LOGGER.warn("[PopBuffer] ck offset long time not commit, {}", pointWrapper);
}
break;
@@ -151,7 +156,7 @@ public class PopBufferMergeService extends ServiceThread {
count += qs;
if (qs > 5000 && scanTimes % countOfSecond1 == 0) {
POP_LOGGER.info("[PopBuffer] offset queue size too long, {}, {}",
- entry.getKey(), qs);
+ entry.getKey(), qs);
}
}
return count;
@@ -214,7 +219,7 @@ public class PopBufferMergeService extends ServiceThread {
// just process offset(already stored at pull thread), or buffer ck(not stored and ack finish)
if ((pointWrapper.isJustOffset() && pointWrapper.isCkStored()) || isCkDone(pointWrapper)
- || (isCkDoneForFinish(pointWrapper) && pointWrapper.isCkStored())) {
+ || (isCkDoneForFinish(pointWrapper) && pointWrapper.isCkStored())) {
if (brokerController.getBrokerConfig().isEnablePopLog()) {
POP_LOGGER.info("[PopBuffer]ck done, {}", pointWrapper);
}
@@ -226,7 +231,7 @@ public class PopBufferMergeService extends ServiceThread {
PopCheckPoint point = pointWrapper.getCk();
long now = System.currentTimeMillis();
- boolean removeCk = !this.serving;
+ boolean removeCk = this.serving ? false : true;
// ck will be timeout
if (point.getReviveTime() - now < brokerController.getBrokerConfig().getPopCkStayBufferTimeOut()) {
removeCk = true;
@@ -265,7 +270,7 @@ public class PopBufferMergeService extends ServiceThread {
for (byte i = 0; i < point.getNum(); i++) {
// reput buffer ak to store
if (DataConverter.getBit(pointWrapper.getBits().get(), i)
- && !DataConverter.getBit(pointWrapper.getToStoreBits().get(), i)) {
+ && !DataConverter.getBit(pointWrapper.getToStoreBits().get(), i)) {
if (putAckToStore(pointWrapper, i)) {
count++;
markBitCAS(pointWrapper.getToStoreBits(), i);
@@ -289,14 +294,14 @@ public class PopBufferMergeService extends ServiceThread {
long eclipse = System.currentTimeMillis() - startTime;
if (eclipse > brokerController.getBrokerConfig().getPopCkStayBufferTimeOut() - 1000) {
POP_LOGGER.warn("[PopBuffer]scan stop, because eclipse too long, PopBufferEclipse={}, " +
- "PopBufferToStoreAck={}, PopBufferToStoreCk={}, PopBufferSize={}, PopBufferOffsetSize={}",
- eclipse, count, countCk, counter.get(), offsetBufferSize);
+ "PopBufferToStoreAck={}, PopBufferToStoreCk={}, PopBufferSize={}, PopBufferOffsetSize={}",
+ eclipse, count, countCk, counter.get(), offsetBufferSize);
this.serving = false;
} else {
if (scanTimes % countOfSecond1 == 0) {
POP_LOGGER.info("[PopBuffer]scan, PopBufferEclipse={}, " +
- "PopBufferToStoreAck={}, PopBufferToStoreCk={}, PopBufferSize={}, PopBufferOffsetSize={}",
- eclipse, count, countCk, counter.get(), offsetBufferSize);
+ "PopBufferToStoreAck={}, PopBufferToStoreCk={}, PopBufferSize={}, PopBufferOffsetSize={}",
+ eclipse, count, countCk, counter.get(), offsetBufferSize);
}
}
scanTimes++;
@@ -354,7 +359,7 @@ public class PopBufferMergeService extends ServiceThread {
POP_LOGGER.warn("Commit offset, consumer offset less than store, {}, {}", wrapper, offset);
}
brokerController.getConsumerOffsetManager().commitOffset(getServiceName(),
- popCheckPoint.getCId(), popCheckPoint.getTopic(), popCheckPoint.getQueueId(), wrapper.getNextBeginOffset());
+ popCheckPoint.getCId(), popCheckPoint.getTopic(), popCheckPoint.getQueueId(), wrapper.getNextBeginOffset());
} finally {
queueLockManager.unLock(lockKey);
}
@@ -384,6 +389,7 @@ public class PopBufferMergeService extends ServiceThread {
/**
* put to store && add to buffer.
+ *
* @param point
* @param reviveQueueId
* @param reviveQueueOffset
@@ -404,7 +410,7 @@ public class PopBufferMergeService extends ServiceThread {
}
public void addCkMock(String group, String topic, int queueId, long startOffset, long invisibleTime,
- long popTime, int reviveQueueId, long nextBeginOffset) {
+ long popTime, int reviveQueueId, long nextBeginOffset, String brokerName) {
final PopCheckPoint ck = new PopCheckPoint();
ck.setBitMap(0);
ck.setNum((byte) 0);
@@ -414,6 +420,7 @@ public class PopBufferMergeService extends ServiceThread {
ck.setCId(group);
ck.setTopic(topic);
ck.setQueueId((byte) queueId);
+ ck.setBrokerName(brokerName);
PopCheckPointWrapper pointWrapper = new PopCheckPointWrapper(reviveQueueId, Long.MAX_VALUE, ck, nextBeginOffset, true);
pointWrapper.setCkStored(true);
@@ -469,7 +476,7 @@ public class PopBufferMergeService extends ServiceThread {
return false;
}
try {
- PopCheckPointWrapper pointWrapper = this.buffer.get(ackMsg.getTopic() + ackMsg.getConsumerGroup() + ackMsg.getQueueId() + ackMsg.getStartOffset() + ackMsg.getPopTime());
+ PopCheckPointWrapper pointWrapper = this.buffer.get(ackMsg.getTopic() + ackMsg.getConsumerGroup() + ackMsg.getQueueId() + ackMsg.getStartOffset() + ackMsg.getPopTime() + ackMsg.getBrokerName());
if (pointWrapper == null) {
if (brokerController.getBrokerConfig().isEnablePopLog()) {
POP_LOGGER.warn("[PopBuffer]add ack fail, rqId={}, no ck, {}", reviveQid, ackMsg);
@@ -523,6 +530,10 @@ public class PopBufferMergeService extends ServiceThread {
return false;
}
+ public void clearOffsetQueue(String lockKey) {
+ this.commitOffsets.remove(lockKey);
+ }
+
private void putCkToStore(final PopCheckPointWrapper pointWrapper, final boolean runInCurrent) {
if (pointWrapper.getReviveQueueOffset() >= 0) {
return;
@@ -530,9 +541,9 @@ public class PopBufferMergeService extends ServiceThread {
MessageExtBrokerInner msgInner = popMessageProcessor.buildCkMsg(pointWrapper.getCk(), pointWrapper.getReviveQueueId());
PutMessageResult putMessageResult = brokerController.getMessageStore().putMessage(msgInner);
if (putMessageResult.getPutMessageStatus() != PutMessageStatus.PUT_OK
- && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_DISK_TIMEOUT
- && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_SLAVE_TIMEOUT
- && putMessageResult.getPutMessageStatus() != PutMessageStatus.SLAVE_NOT_AVAILABLE) {
+ && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_DISK_TIMEOUT
+ && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_SLAVE_TIMEOUT
+ && putMessageResult.getPutMessageStatus() != PutMessageStatus.SLAVE_NOT_AVAILABLE) {
POP_LOGGER.error("[PopBuffer]put ck to store fail: {}, {}", pointWrapper, putMessageResult);
return;
}
@@ -568,9 +579,9 @@ public class PopBufferMergeService extends ServiceThread {
msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgInner.getProperties()));
PutMessageResult putMessageResult = brokerController.getMessageStore().putMessage(msgInner);
if (putMessageResult.getPutMessageStatus() != PutMessageStatus.PUT_OK
- && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_DISK_TIMEOUT
- && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_SLAVE_TIMEOUT
- && putMessageResult.getPutMessageStatus() != PutMessageStatus.SLAVE_NOT_AVAILABLE) {
+ && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_DISK_TIMEOUT
+ && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_SLAVE_TIMEOUT
+ && putMessageResult.getPutMessageStatus() != PutMessageStatus.SLAVE_NOT_AVAILABLE) {
POP_LOGGER.error("[PopBuffer]put ack to store fail: {}, {}, {}", pointWrapper, ackMsg, putMessageResult);
return false;
}
@@ -581,6 +592,38 @@ public class PopBufferMergeService extends ServiceThread {
return true;
}
+ private boolean cancelCkTimer(final PopCheckPointWrapper pointWrapper) {
+ // not stored, no need cancel
+ if (pointWrapper.getReviveQueueOffset() < 0) {
+ return true;
+ }
+ PopCheckPoint point = pointWrapper.getCk();
+ MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
+ msgInner.setTopic(popMessageProcessor.reviveTopic);
+ msgInner.setBody((pointWrapper.getReviveQueueId() + "-" + pointWrapper.getReviveQueueOffset()).getBytes());
+ msgInner.setQueueId(pointWrapper.getReviveQueueId());
+ msgInner.setTags(PopAckConstants.CK_TAG);
+ msgInner.setBornTimestamp(System.currentTimeMillis());
+ msgInner.setBornHost(brokerController.getStoreHost());
+ msgInner.setStoreHost(brokerController.getStoreHost());
+
+ MsgUtil.setMessageDeliverTime(brokerController, msgInner, point.getReviveTime() - PopAckConstants.ackTimeInterval);
+
+ msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgInner.getProperties()));
+ PutMessageResult putMessageResult = brokerController.getEscapeBridge().putMessageToSpecificQueue(msgInner);
+ if (putMessageResult.getPutMessageStatus() != PutMessageStatus.PUT_OK
+ && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_DISK_TIMEOUT
+ && putMessageResult.getPutMessageStatus() != PutMessageStatus.FLUSH_SLAVE_TIMEOUT
+ && putMessageResult.getPutMessageStatus() != PutMessageStatus.SLAVE_NOT_AVAILABLE) {
+ POP_LOGGER.error("[PopBuffer]PutMessageCallback cancelCheckPoint fail, {}, {}", pointWrapper, putMessageResult);
+ return false;
+ }
+ if (brokerController.getBrokerConfig().isEnablePopLog()) {
+ POP_LOGGER.info("[PopBuffer]cancelCheckPoint, {}", pointWrapper);
+ }
+ return true;
+ }
+
private boolean isCkDone(PopCheckPointWrapper pointWrapper) {
byte num = pointWrapper.getCk().getNum();
for (byte i = 0; i < num; i++) {
@@ -639,7 +682,8 @@ public class PopBufferMergeService extends ServiceThread {
private final boolean justOffset;
private volatile boolean ckStored = false;
- public PopCheckPointWrapper(int reviveQueueId, long reviveQueueOffset, PopCheckPoint point, long nextBeginOffset) {
+ public PopCheckPointWrapper(int reviveQueueId, long reviveQueueOffset, PopCheckPoint point,
+ long nextBeginOffset) {
this.reviveQueueId = reviveQueueId;
this.reviveQueueOffset = reviveQueueOffset;
this.ck = point;
@@ -647,12 +691,13 @@ public class PopBufferMergeService extends ServiceThread {
this.toStoreBits = new AtomicInteger(0);
this.nextBeginOffset = nextBeginOffset;
this.lockKey = ck.getTopic() + PopAckConstants.SPLIT + ck.getCId() + PopAckConstants.SPLIT + ck.getQueueId();
- this.mergeKey = point.getTopic() + point.getCId() + point.getQueueId() + point.getStartOffset() + point.getPopTime();
+ this.mergeKey = point.getTopic() + point.getCId() + point.getQueueId() + point.getStartOffset() + point.getPopTime() + point.getBrokerName();
this.justOffset = false;
}
- public PopCheckPointWrapper(int reviveQueueId, long reviveQueueOffset, PopCheckPoint point, long nextBeginOffset,
- boolean justOffset) {
+ public PopCheckPointWrapper(int reviveQueueId, long reviveQueueOffset, PopCheckPoint point,
+ long nextBeginOffset,
+ boolean justOffset) {
this.reviveQueueId = reviveQueueId;
this.reviveQueueOffset = reviveQueueOffset;
this.ck = point;
@@ -660,7 +705,7 @@ public class PopBufferMergeService extends ServiceThread {
this.toStoreBits = new AtomicInteger(0);
this.nextBeginOffset = nextBeginOffset;
this.lockKey = ck.getTopic() + PopAckConstants.SPLIT + ck.getCId() + PopAckConstants.SPLIT + ck.getQueueId();
- this.mergeKey = point.getTopic() + point.getCId() + point.getQueueId() + point.getStartOffset() + point.getPopTime();
+ this.mergeKey = point.getTopic() + point.getCId() + point.getQueueId() + point.getStartOffset() + point.getPopTime() + point.getBrokerName();
this.justOffset = justOffset;
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/PopMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/PopMessageProcessor.java
index fcc972d..c9f4485 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/PopMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/PopMessageProcessor.java
@@ -68,14 +68,14 @@ import org.apache.rocketmq.remoting.netty.RequestTask;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.apache.rocketmq.store.GetMessageResult;
import org.apache.rocketmq.store.GetMessageStatus;
-import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
import org.apache.rocketmq.store.SelectMappedBufferResult;
import org.apache.rocketmq.store.pop.AckMsg;
import org.apache.rocketmq.store.pop.PopCheckPoint;
public class PopMessageProcessor implements NettyRequestProcessor {
private static final InternalLogger POP_LOGGER =
- InternalLoggerFactory.getLogger(LoggerName.ROCKETMQ_POP_LOGGER_NAME);
+ InternalLoggerFactory.getLogger(LoggerName.ROCKETMQ_POP_LOGGER_NAME);
private final BrokerController brokerController;
private Random random = new Random(System.currentTimeMillis());
String reviveTopic;
@@ -96,12 +96,11 @@ public class PopMessageProcessor implements NettyRequestProcessor {
public PopMessageProcessor(final BrokerController brokerController) {
this.brokerController = brokerController;
- this.reviveTopic =
- PopAckConstants.REVIVE_TOPIC + this.brokerController.getBrokerConfig().getBrokerClusterName();
- // 100000 topic default, 100000 lru topic + cid + qid
+ this.reviveTopic = PopAckConstants.buildClusterReviveTopic(this.brokerController.getBrokerConfig().getBrokerClusterName());
+ // 100000 topic default, 100000 lru topic + cid + qid
this.topicCidMap = new ConcurrentHashMap<>(this.brokerController.getBrokerConfig().getPopPollingMapSize());
this.pollingMap = new ConcurrentLinkedHashMap.Builder<String, ConcurrentSkipListSet<PopRequest>>()
- .maximumWeightedCapacity(this.brokerController.getBrokerConfig().getPopPollingMapSize()).build();
+ .maximumWeightedCapacity(this.brokerController.getBrokerConfig().getPopPollingMapSize()).build();
this.popLongPollingService = new PopLongPollingService();
this.queueLockManager = new QueueLockManager();
this.popBufferMergeService = new PopBufferMergeService(this.brokerController, this);
@@ -122,24 +121,27 @@ public class PopMessageProcessor implements NettyRequestProcessor {
public static String genAckUniqueId(AckMsg ackMsg) {
return ackMsg.getTopic()
- + PopAckConstants.SPLIT + ackMsg.getQueueId()
- + PopAckConstants.SPLIT + ackMsg.getAckOffset()
- + PopAckConstants.SPLIT + ackMsg.getConsumerGroup()
- + PopAckConstants.SPLIT + ackMsg.getPopTime()
- + PopAckConstants.SPLIT + PopAckConstants.ACK_TAG;
+ + PopAckConstants.SPLIT + ackMsg.getQueueId()
+ + PopAckConstants.SPLIT + ackMsg.getAckOffset()
+ + PopAckConstants.SPLIT + ackMsg.getConsumerGroup()
+ + PopAckConstants.SPLIT + ackMsg.getPopTime()
+ + PopAckConstants.SPLIT + ackMsg.getBrokerName()
+ + PopAckConstants.SPLIT + PopAckConstants.ACK_TAG;
}
public static String genCkUniqueId(PopCheckPoint ck) {
return ck.getTopic()
- + PopAckConstants.SPLIT + ck.getQueueId()
- + PopAckConstants.SPLIT + ck.getStartOffset()
- + PopAckConstants.SPLIT + ck.getCId()
- + PopAckConstants.SPLIT + ck.getPopTime()
- + PopAckConstants.SPLIT + PopAckConstants.CK_TAG;
+ + PopAckConstants.SPLIT + ck.getQueueId()
+ + PopAckConstants.SPLIT + ck.getStartOffset()
+ + PopAckConstants.SPLIT + ck.getCId()
+ + PopAckConstants.SPLIT + ck.getPopTime()
+ + PopAckConstants.SPLIT + ck.getBrokerName()
+ + PopAckConstants.SPLIT + PopAckConstants.CK_TAG;
}
@Override
- public RemotingCommand processRequest(final ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
+ public RemotingCommand processRequest(final ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
request.addExtField(BORN_TIME, String.valueOf(System.currentTimeMillis()));
return this.processRequest(ctx.channel(), request);
}
@@ -167,8 +169,7 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
public void notifyMessageArriving(final String topic, final String cid, final int queueId) {
- ConcurrentSkipListSet<PopRequest> remotingCommands = pollingMap.get(KeyBuilder.buildPollingKey(topic, cid,
- queueId));
+ ConcurrentSkipListSet<PopRequest> remotingCommands = pollingMap.get(KeyBuilder.buildPollingKey(topic, cid, queueId));
if (remotingCommands == null || remotingCommands.isEmpty()) {
return;
}
@@ -192,12 +193,14 @@ public class PopMessageProcessor implements NettyRequestProcessor {
if (request == null || !request.complete()) {
return;
}
+ if (!request.getChannel().isActive()) {
+ return;
+ }
Runnable run = new Runnable() {
@Override
public void run() {
try {
- final RemotingCommand response = PopMessageProcessor.this.processRequest(request.getChannel(),
- request.getRemotingCommand());
+ final RemotingCommand response = PopMessageProcessor.this.processRequest(request.getChannel(), request.getRemotingCommand());
if (response != null) {
response.setOpaque(request.getRemotingCommand().getOpaque());
@@ -207,8 +210,7 @@ public class PopMessageProcessor implements NettyRequestProcessor {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
- POP_LOGGER.error("ProcessRequestWrapper response to {} failed",
- future.channel().remoteAddress(), future.cause());
+ POP_LOGGER.error("ProcessRequestWrapper response to {} failed", future.channel().remoteAddress(), future.cause());
POP_LOGGER.error(request.toString());
POP_LOGGER.error(response.toString());
}
@@ -225,16 +227,15 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
}
};
- this.brokerController.getPullMessageExecutor().submit(new RequestTask(run, request.getChannel(),
- request.getRemotingCommand()));
+ this.brokerController.getPullMessageExecutor().submit(new RequestTask(run, request.getChannel(), request.getRemotingCommand()));
}
private RemotingCommand processRequest(final Channel channel, RemotingCommand request)
- throws RemotingCommandException {
+ throws RemotingCommandException {
RemotingCommand response = RemotingCommand.createResponseCommand(PopMessageResponseHeader.class);
final PopMessageResponseHeader responseHeader = (PopMessageResponseHeader) response.readCustomHeader();
final PopMessageRequestHeader requestHeader =
- (PopMessageRequestHeader) request.decodeCommandCustomHeader(PopMessageRequestHeader.class);
+ (PopMessageRequestHeader) request.decodeCommandCustomHeader(PopMessageRequestHeader.class);
StringBuilder startOffsetInfo = new StringBuilder(64);
StringBuilder msgOffsetInfo = new StringBuilder(64);
StringBuilder orderCountInfo = null;
@@ -251,30 +252,30 @@ public class PopMessageProcessor implements NettyRequestProcessor {
if (requestHeader.isTimeoutTooMuch()) {
response.setCode(POLLING_TIMEOUT);
response.setRemark(String.format("the broker[%s] poping message is timeout too much",
- this.brokerController.getBrokerConfig().getBrokerIP1()));
+ this.brokerController.getBrokerConfig().getBrokerIP1()));
return response;
}
if (!PermName.isReadable(this.brokerController.getBrokerConfig().getBrokerPermission())) {
response.setCode(ResponseCode.NO_PERMISSION);
response.setRemark(String.format("the broker[%s] poping message is forbidden",
- this.brokerController.getBrokerConfig().getBrokerIP1()));
+ this.brokerController.getBrokerConfig().getBrokerIP1()));
return response;
}
if (requestHeader.getMaxMsgNums() > 32) {
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark(String.format("the broker[%s] poping message's num is greater than 32",
- this.brokerController.getBrokerConfig().getBrokerIP1()));
+ this.brokerController.getBrokerConfig().getBrokerIP1()));
return response;
}
TopicConfig topicConfig =
- this.brokerController.getTopicConfigManager().selectTopicConfig(requestHeader.getTopic());
+ this.brokerController.getTopicConfigManager().selectTopicConfig(requestHeader.getTopic());
if (null == topicConfig) {
POP_LOGGER.error("The topic {} not exist, consumer: {} ", requestHeader.getTopic(),
- RemotingHelper.parseChannelRemoteAddr(channel));
+ RemotingHelper.parseChannelRemoteAddr(channel));
response.setCode(ResponseCode.TOPIC_NOT_EXIST);
response.setRemark(String.format("topic[%s] not exist, apply first please! %s", requestHeader.getTopic(),
- FAQUrl.suggestTodo(FAQUrl.APPLY_TOPIC_URL)));
+ FAQUrl.suggestTodo(FAQUrl.APPLY_TOPIC_URL)));
return response;
}
@@ -286,20 +287,20 @@ public class PopMessageProcessor implements NettyRequestProcessor {
if (requestHeader.getQueueId() >= topicConfig.getReadQueueNums()) {
String errorInfo = String.format("queueId[%d] is illegal, topic:[%s] topicConfig.readQueueNums:[%d] " +
- "consumer:[%s]",
- requestHeader.getQueueId(), requestHeader.getTopic(), topicConfig.getReadQueueNums(),
- channel.remoteAddress());
+ "consumer:[%s]",
+ requestHeader.getQueueId(), requestHeader.getTopic(), topicConfig.getReadQueueNums(),
+ channel.remoteAddress());
POP_LOGGER.warn(errorInfo);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark(errorInfo);
return response;
}
SubscriptionGroupConfig subscriptionGroupConfig =
- this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig(requestHeader.getConsumerGroup());
+ this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig(requestHeader.getConsumerGroup());
if (null == subscriptionGroupConfig) {
response.setCode(ResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST);
response.setRemark(String.format("subscription group [%s] does not exist, %s",
- requestHeader.getConsumerGroup(), FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST)));
+ requestHeader.getConsumerGroup(), FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST)));
return response;
}
ConsumerGroupInfo consumerGroupInfo =
@@ -311,7 +312,6 @@ public class PopMessageProcessor implements NettyRequestProcessor {
return response;
}
-
if (!subscriptionGroupConfig.isConsumeEnable()) {
response.setCode(ResponseCode.NO_PERMISSION);
response.setRemark("subscription group no permission, " + requestHeader.getConsumerGroup());
@@ -325,22 +325,22 @@ public class PopMessageProcessor implements NettyRequestProcessor {
ConsumerFilterData consumerFilterData = null;
if (!ExpressionType.isTagType(subscriptionData.getExpressionType())) {
consumerFilterData = ConsumerFilterManager.build(
- requestHeader.getTopic(), requestHeader.getConsumerGroup(), requestHeader.getExp(),
- requestHeader.getExpType(), System.currentTimeMillis()
+ requestHeader.getTopic(), requestHeader.getConsumerGroup(), requestHeader.getExp(),
+ requestHeader.getExpType(), System.currentTimeMillis()
);
if (consumerFilterData == null) {
POP_LOGGER.warn("Parse the consumer's subscription[{}] failed, group: {}",
- requestHeader.getExp(), requestHeader.getConsumerGroup());
+ requestHeader.getExp(), requestHeader.getConsumerGroup());
response.setCode(ResponseCode.SUBSCRIPTION_PARSE_FAILED);
response.setRemark("parse the consumer's subscription failed");
return response;
}
}
messageFilter = new ExpressionMessageFilter(subscriptionData, consumerFilterData,
- brokerController.getConsumerFilterManager());
+ brokerController.getConsumerFilterManager());
} catch (Exception e) {
POP_LOGGER.warn("Parse the consumer's subscription[{}] error, group: {}", requestHeader.getExp(),
- requestHeader.getConsumerGroup());
+ requestHeader.getConsumerGroup());
response.setCode(ResponseCode.SUBSCRIPTION_PARSE_FAILED);
response.setRemark("parse the consumer's subscription failed");
return response;
@@ -355,20 +355,21 @@ public class PopMessageProcessor implements NettyRequestProcessor {
reviveQid = (int) Math.abs(ckMessageNumber.getAndIncrement() % this.brokerController.getBrokerConfig().getReviveQueueNum());
}
- GetMessageResult getMessageResult = new GetMessageResult();
+ int commercialSizePerMsg = this.brokerController.getBrokerConfig().getCommercialSizePerMsg();
+ GetMessageResult getMessageResult = new GetMessageResult(commercialSizePerMsg);
long restNum = 0;
boolean needRetry = randomQ % 5 == 0;
long popTime = System.currentTimeMillis();
if (needRetry && !requestHeader.isOrder()) {
TopicConfig retryTopicConfig =
- this.brokerController.getTopicConfigManager().selectTopicConfig(KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup()));
+ this.brokerController.getTopicConfigManager().selectTopicConfig(KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup()));
if (retryTopicConfig != null) {
for (int i = 0; i < retryTopicConfig.getReadQueueNums(); i++) {
int queueId = (randomQ + i) % retryTopicConfig.getReadQueueNums();
restNum = popMsgFromQueue(true, getMessageResult, requestHeader, queueId, restNum, reviveQid,
- channel, popTime, messageFilter,
- startOffsetInfo, msgOffsetInfo, orderCountInfo);
+ channel, popTime, messageFilter,
+ startOffsetInfo, msgOffsetInfo, orderCountInfo);
}
}
}
@@ -382,19 +383,19 @@ public class PopMessageProcessor implements NettyRequestProcessor {
} else {
int queueId = requestHeader.getQueueId();
restNum = popMsgFromQueue(false, getMessageResult, requestHeader, queueId, restNum, reviveQid, channel,
- popTime, messageFilter,
+ popTime, messageFilter,
startOffsetInfo, msgOffsetInfo, orderCountInfo);
}
// if not full , fetch retry again
if (!needRetry && getMessageResult.getMessageMapedList().size() < requestHeader.getMaxMsgNums() && !requestHeader.isOrder()) {
TopicConfig retryTopicConfig =
- this.brokerController.getTopicConfigManager().selectTopicConfig(KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup()));
+ this.brokerController.getTopicConfigManager().selectTopicConfig(KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(), requestHeader.getConsumerGroup()));
if (retryTopicConfig != null) {
for (int i = 0; i < retryTopicConfig.getReadQueueNums(); i++) {
int queueId = (randomQ + i) % retryTopicConfig.getReadQueueNums();
restNum = popMsgFromQueue(true, getMessageResult, requestHeader, queueId, restNum, reviveQid,
- channel, popTime, messageFilter,
- startOffsetInfo, msgOffsetInfo, orderCountInfo);
+ channel, popTime, messageFilter,
+ startOffsetInfo, msgOffsetInfo, orderCountInfo);
}
}
}
@@ -404,7 +405,7 @@ public class PopMessageProcessor implements NettyRequestProcessor {
if (restNum > 0) {
// all queue pop can not notify specified queue pop, and vice versa
notifyMessageArriving(requestHeader.getTopic(), requestHeader.getConsumerGroup(),
- requestHeader.getQueueId());
+ requestHeader.getQueueId());
}
} else {
int pollingResult = polling(channel, request, requestHeader);
@@ -432,24 +433,24 @@ public class PopMessageProcessor implements NettyRequestProcessor {
if (this.brokerController.getBrokerConfig().isTransferMsgByHeap()) {
final long beginTimeMills = this.brokerController.getMessageStore().now();
final byte[] r = this.readGetMessageResult(getMessageResult, requestHeader.getConsumerGroup(),
- requestHeader.getTopic(), requestHeader.getQueueId());
+ requestHeader.getTopic(), requestHeader.getQueueId());
this.brokerController.getBrokerStatsManager().incGroupGetLatency(requestHeader.getConsumerGroup(),
- requestHeader.getTopic(), requestHeader.getQueueId(),
- (int) (this.brokerController.getMessageStore().now() - beginTimeMills));
+ requestHeader.getTopic(), requestHeader.getQueueId(),
+ (int) (this.brokerController.getMessageStore().now() - beginTimeMills));
response.setBody(r);
} else {
final GetMessageResult tmpGetMessageResult = getMessageResult;
try {
FileRegion fileRegion =
- new ManyMessageTransfer(response.encodeHeader(getMessageResult.getBufferTotalSize()),
- getMessageResult);
+ new ManyMessageTransfer(response.encodeHeader(getMessageResult.getBufferTotalSize()),
+ getMessageResult);
channel.writeAndFlush(fileRegion).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
tmpGetMessageResult.release();
if (!future.isSuccess()) {
POP_LOGGER.error("Fail to transfer messages from page cache to {}",
- channel.remoteAddress(), future.cause());
+ channel.remoteAddress(), future.cause());
}
}
});
@@ -468,14 +469,14 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
private long popMsgFromQueue(boolean isRetry, GetMessageResult getMessageResult,
- PopMessageRequestHeader requestHeader, int queueId, long restNum, int reviveQid,
- Channel channel, long popTime,
- ExpressionMessageFilter messageFilter, StringBuilder startOffsetInfo,
- StringBuilder msgOffsetInfo, StringBuilder orderCountInfo) {
+ PopMessageRequestHeader requestHeader, int queueId, long restNum, int reviveQid,
+ Channel channel, long popTime,
+ ExpressionMessageFilter messageFilter, StringBuilder startOffsetInfo,
+ StringBuilder msgOffsetInfo, StringBuilder orderCountInfo) {
String topic = isRetry ? KeyBuilder.buildPopRetryTopic(requestHeader.getTopic(),
- requestHeader.getConsumerGroup()) : requestHeader.getTopic();
+ requestHeader.getConsumerGroup()) : requestHeader.getTopic();
String lockKey =
- topic + PopAckConstants.SPLIT + requestHeader.getConsumerGroup() + PopAckConstants.SPLIT + queueId;
+ topic + PopAckConstants.SPLIT + requestHeader.getConsumerGroup() + PopAckConstants.SPLIT + queueId;
boolean isOrder = requestHeader.isOrder();
long offset = getPopOffset(topic, requestHeader, queueId, false, lockKey);
if (!queueLockManager.tryLock(lockKey)) {
@@ -486,34 +487,34 @@ public class PopMessageProcessor implements NettyRequestProcessor {
GetMessageResult getMessageTmpResult;
try {
if (isOrder && brokerController.getConsumerOrderInfoManager().checkBlock(topic,
- requestHeader.getConsumerGroup(), queueId, requestHeader.getInvisibleTime())) {
+ requestHeader.getConsumerGroup(), queueId, requestHeader.getInvisibleTime())) {
return this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, queueId) - offset + restNum;
}
if (getMessageResult.getMessageMapedList().size() >= requestHeader.getMaxMsgNums()) {
restNum =
- this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, queueId) - offset + restNum;
+ this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, queueId) - offset + restNum;
return restNum;
}
getMessageTmpResult = this.brokerController.getMessageStore().getMessage(requestHeader.getConsumerGroup()
- , topic, queueId, offset,
- requestHeader.getMaxMsgNums() - getMessageResult.getMessageMapedList().size(), messageFilter);
+ , topic, queueId, offset,
+ requestHeader.getMaxMsgNums() - getMessageResult.getMessageMapedList().size(), messageFilter);
// maybe store offset is not correct.
if (getMessageTmpResult == null
|| GetMessageStatus.OFFSET_TOO_SMALL.equals(getMessageTmpResult.getStatus())
- || GetMessageStatus.OFFSET_OVERFLOW_BADLY.equals(getMessageTmpResult.getStatus())
- || GetMessageStatus.OFFSET_FOUND_NULL.equals(getMessageTmpResult.getStatus())) {
+ || GetMessageStatus.OFFSET_OVERFLOW_BADLY.equals(getMessageTmpResult.getStatus())
+ || GetMessageStatus.OFFSET_FOUND_NULL.equals(getMessageTmpResult.getStatus())) {
// commit offset, because the offset is not correct
// If offset in store is greater than cq offset, it will cause duplicate messages,
// because offset in PopBuffer is not committed.
POP_LOGGER.warn("Pop initial offset, because store is no correct, {}, {}->{}",
- lockKey, offset, getMessageTmpResult != null ? getMessageTmpResult.getNextBeginOffset() : "null");
+ lockKey, offset, getMessageTmpResult != null ? getMessageTmpResult.getNextBeginOffset() : "null");
offset = getMessageTmpResult != null ? getMessageTmpResult.getNextBeginOffset() : 0;
this.brokerController.getConsumerOffsetManager().commitOffset(channel.remoteAddress().toString(), requestHeader.getConsumerGroup(), topic,
- queueId, offset);
+ queueId, offset);
getMessageTmpResult =
- this.brokerController.getMessageStore().getMessage(requestHeader.getConsumerGroup(), topic,
- queueId, offset,
+ this.brokerController.getMessageStore().getMessage(requestHeader.getConsumerGroup(), topic,
+ queueId, offset,
requestHeader.getMaxMsgNums() - getMessageResult.getMessageMapedList().size(), messageFilter);
}
@@ -521,30 +522,32 @@ public class PopMessageProcessor implements NettyRequestProcessor {
if (!getMessageTmpResult.getMessageMapedList().isEmpty()) {
this.brokerController.getBrokerStatsManager().incBrokerGetNums(getMessageTmpResult.getMessageCount());
this.brokerController.getBrokerStatsManager().incGroupGetNums(requestHeader.getConsumerGroup(), topic,
- getMessageTmpResult.getMessageCount());
+ getMessageTmpResult.getMessageCount());
this.brokerController.getBrokerStatsManager().incGroupGetSize(requestHeader.getConsumerGroup(), topic,
- getMessageTmpResult.getBufferTotalSize());
+ getMessageTmpResult.getBufferTotalSize());
if (isOrder) {
int count = brokerController.getConsumerOrderInfoManager().update(topic,
- requestHeader.getConsumerGroup(),
- queueId, getMessageTmpResult.getMessageQueueOffset());
+ requestHeader.getConsumerGroup(),
+ queueId, getMessageTmpResult.getMessageQueueOffset());
this.brokerController.getConsumerOffsetManager().commitOffset(channel.remoteAddress().toString(),
- requestHeader.getConsumerGroup(), topic, queueId, offset);
+ requestHeader.getConsumerGroup(), topic, queueId, offset);
ExtraInfoUtil.buildOrderCountInfo(orderCountInfo, isRetry, queueId, count);
} else {
- appendCheckPoint(requestHeader, topic, reviveQid, queueId, offset, getMessageTmpResult, popTime);
+ appendCheckPoint(requestHeader, topic, reviveQid, queueId, offset, getMessageTmpResult, popTime, this.brokerController.getBrokerConfig().getBrokerName());
}
ExtraInfoUtil.buildStartOffsetInfo(startOffsetInfo, isRetry, queueId, offset);
ExtraInfoUtil.buildMsgOffsetInfo(msgOffsetInfo, isRetry, queueId,
- getMessageTmpResult.getMessageQueueOffset());
+ getMessageTmpResult.getMessageQueueOffset());
} else if ((GetMessageStatus.NO_MATCHED_MESSAGE.equals(getMessageTmpResult.getStatus())
- || GetMessageStatus.OFFSET_FOUND_NULL.equals(getMessageTmpResult.getStatus())
- || GetMessageStatus.MESSAGE_WAS_REMOVING.equals(getMessageTmpResult.getStatus())
- || GetMessageStatus.NO_MATCHED_LOGIC_QUEUE.equals(getMessageTmpResult.getStatus()))
- && getMessageTmpResult.getNextBeginOffset() > -1) {
+ || GetMessageStatus.OFFSET_FOUND_NULL.equals(getMessageTmpResult.getStatus())
+ || GetMessageStatus.MESSAGE_WAS_REMOVING.equals(getMessageTmpResult.getStatus())
+ || GetMessageStatus.NO_MATCHED_LOGIC_QUEUE.equals(getMessageTmpResult.getStatus()))
+ && getMessageTmpResult.getNextBeginOffset() > -1) {
popBufferMergeService.addCkMock(requestHeader.getConsumerGroup(), topic, queueId, offset,
- requestHeader.getInvisibleTime(), popTime, reviveQid, getMessageTmpResult.getNextBeginOffset());
+ requestHeader.getInvisibleTime(), popTime, reviveQid, getMessageTmpResult.getNextBeginOffset(), brokerController.getBrokerConfig().getBrokerName());
+// this.brokerController.getConsumerOffsetManager().commitOffset(channel.remoteAddress().toString(), requestHeader.getConsumerGroup(), topic,
+// queueId, getMessageTmpResult.getNextBeginOffset());
}
} finally {
queueLockManager.unLock(lockKey);
@@ -558,9 +561,9 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
private long getPopOffset(String topic, PopMessageRequestHeader requestHeader, int queueId, boolean init,
- String lockKey) {
+ String lockKey) {
long offset = this.brokerController.getConsumerOffsetManager().queryOffset(requestHeader.getConsumerGroup(),
- topic, queueId);
+ topic, queueId);
if (offset < 0) {
if (ConsumeInitMode.MIN == requestHeader.getInitMode()) {
offset = this.brokerController.getMessageStore().getMinOffsetInQueue(topic, queueId);
@@ -573,8 +576,8 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
if (init) {
this.brokerController.getConsumerOffsetManager().commitOffset("getPopOffset",
- requestHeader.getConsumerGroup(), topic,
- queueId, offset);
+ requestHeader.getConsumerGroup(), topic,
+ queueId, offset);
}
}
}
@@ -593,7 +596,7 @@ public class PopMessageProcessor implements NettyRequestProcessor {
* @return
*/
private int polling(final Channel channel, RemotingCommand remotingCommand,
- final PopMessageRequestHeader requestHeader) {
+ final PopMessageRequestHeader requestHeader) {
if (requestHeader.getPollTime() <= 0 || this.popLongPollingService.isStopped()) {
return NOT_POLLING;
}
@@ -621,7 +624,7 @@ public class PopMessageProcessor implements NettyRequestProcessor {
return POLLING_TIMEOUT;
}
String key = KeyBuilder.buildPollingKey(requestHeader.getTopic(), requestHeader.getConsumerGroup(),
- requestHeader.getQueueId());
+ requestHeader.getQueueId());
ConcurrentSkipListSet<PopRequest> queue = pollingMap.get(key);
if (queue == null) {
queue = new ConcurrentSkipListSet<>(PopRequest.COMPARATOR);
@@ -667,8 +670,8 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
private void appendCheckPoint(final PopMessageRequestHeader requestHeader,
- final String topic, final int reviveQid, final int queueId, final long offset,
- final GetMessageResult getMessageTmpResult, final long popTime) {
+ final String topic, final int reviveQid, final int queueId, final long offset,
+ final GetMessageResult getMessageTmpResult, final long popTime, final String brokerName) {
// add check point msg to revive log
final PopCheckPoint ck = new PopCheckPoint();
ck.setBitMap(0);
@@ -679,12 +682,13 @@ public class PopMessageProcessor implements NettyRequestProcessor {
ck.setCId(requestHeader.getConsumerGroup());
ck.setTopic(topic);
ck.setQueueId((byte) queueId);
+ ck.setBrokerName(brokerName);
for (Long msgQueueOffset : getMessageTmpResult.getMessageQueueOffset()) {
ck.addDiff((int) (msgQueueOffset - offset));
}
final boolean addBufferSuc = this.popBufferMergeService.addCk(
- ck, reviveQid, -1, getMessageTmpResult.getNextBeginOffset()
+ ck, reviveQid, -1, getMessageTmpResult.getNextBeginOffset()
);
if (addBufferSuc) {
@@ -692,12 +696,12 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
this.popBufferMergeService.addCkJustOffset(
- ck, reviveQid, -1, getMessageTmpResult.getNextBeginOffset()
+ ck, reviveQid, -1, getMessageTmpResult.getNextBeginOffset()
);
}
- private byte[] readGetMessageResult(final GetMessageResult getMessageResult, final String group,
- final String topic, final int queueId) {
+ private byte[] readGetMessageResult(final GetMessageResult getMessageResult, final String group, final String topic,
+ final int queueId) {
final ByteBuffer byteBuffer = ByteBuffer.allocate(getMessageResult.getBufferTotalSize());
long storeTimestamp = 0;
@@ -713,7 +717,7 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
this.brokerController.getBrokerStatsManager().recordDiskFallBehindTime(group, topic, queueId,
- this.brokerController.getMessageStore().now() - storeTimestamp);
+ this.brokerController.getMessageStore().now() - storeTimestamp);
return byteBuffer.array();
}
@@ -723,7 +727,10 @@ public class PopMessageProcessor implements NettyRequestProcessor {
@Override
public String getServiceName() {
- return "PopLongPollingService";
+ if (PopMessageProcessor.this.brokerController.getBrokerConfig().isInBrokerContainer()) {
+ return PopMessageProcessor.this.brokerController.getBrokerConfig().getLoggerIdentifier() + PopLongPollingService.class.getName();
+ }
+ return PopLongPollingService.class.getName();
}
private void cleanUnusedResource() {
@@ -819,7 +826,8 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
totalPollingNum.decrementAndGet();
wakeUp(first);
- } while (true);
+ }
+ while (true);
if (i >= 100) {
long tmpPollingNum = popQ.size();
tmpTotalPollingNum = tmpTotalPollingNum + tmpPollingNum;
@@ -831,8 +839,8 @@ public class PopMessageProcessor implements NettyRequestProcessor {
if (i >= 100) {
POP_LOGGER.info("pollingMapSize={},tmpTotalSize={},atomicTotalSize={},diffSize={}",
- pollingMap.size(), tmpTotalPollingNum, totalPollingNum.get(),
- Math.abs(totalPollingNum.get() - tmpTotalPollingNum));
+ pollingMap.size(), tmpTotalPollingNum, totalPollingNum.get(),
+ Math.abs(totalPollingNum.get() - tmpTotalPollingNum));
totalPollingNum.set(tmpTotalPollingNum);
i = 0;
}
@@ -893,7 +901,7 @@ public class PopMessageProcessor implements NettyRequestProcessor {
}
}
- public static class QueueLockManager extends ServiceThread {
+ public class QueueLockManager extends ServiceThread {
private ConcurrentHashMap<String, TimedLock> expiredLocalCache = new ConcurrentHashMap<>(100000);
public boolean tryLock(String key) {
@@ -931,8 +939,8 @@ public class PopMessageProcessor implements NettyRequestProcessor {
if (System.currentTimeMillis() - entry.getValue().getLockTime() > usedExpireMillis) {
iterator.remove();
POP_LOGGER.info("Remove unused queue lock: {}, {}, {}", entry.getKey(),
- entry.getValue().getLockTime(),
- entry.getValue().isLock());
+ entry.getValue().getLockTime(),
+ entry.getValue().isLock());
}
total++;
@@ -950,7 +958,10 @@ public class PopMessageProcessor implements NettyRequestProcessor {
@Override
public String getServiceName() {
- return "QueueLockManager";
+ if (PopMessageProcessor.this.brokerController.getBrokerConfig().isInBrokerContainer()) {
+ return PopMessageProcessor.this.brokerController.getBrokerConfig().getLoggerIdentifier() + QueueLockManager.class.getName();
+ }
+ return QueueLockManager.class.getName();
}
@Override
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/PopReviveService.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/PopReviveService.java
index 6d94a75..858ad61 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/PopReviveService.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/PopReviveService.java
@@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.broker.util.MsgUtil;
import org.apache.rocketmq.client.consumer.PullResult;
@@ -43,9 +44,8 @@ import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.store.AppendMessageStatus;
import org.apache.rocketmq.store.GetMessageResult;
-import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.common.message.MessageExtBrokerInner;
import org.apache.rocketmq.store.PutMessageResult;
-import org.apache.rocketmq.store.config.BrokerRole;
import org.apache.rocketmq.store.pop.AckMsg;
import org.apache.rocketmq.store.pop.PopCheckPoint;
@@ -55,10 +55,9 @@ public class PopReviveService extends ServiceThread {
private int queueId;
private BrokerController brokerController;
private String reviveTopic;
- private static volatile boolean isMaster = false;
+ private volatile boolean shouldRunPopRevive = false;
- public PopReviveService(int queueId, BrokerController brokerController, String reviveTopic) {
- super();
+ public PopReviveService(BrokerController brokerController, String reviveTopic, int queueId) {
this.queueId = queueId;
this.brokerController = brokerController;
this.reviveTopic = reviveTopic;
@@ -66,20 +65,22 @@ public class PopReviveService extends ServiceThread {
@Override
public String getServiceName() {
+ if (brokerController != null && brokerController.getBrokerConfig().isInBrokerContainer()) {
+ return brokerController.getBrokerConfig().getLoggerIdentifier() + "PopReviveService_" + this.queueId;
+ }
return "PopReviveService_" + this.queueId;
}
- private boolean checkMaster() {
- return brokerController.getMessageStoreConfig().getBrokerRole() != BrokerRole.SLAVE;
+ public void setShouldRunPopRevive(final boolean shouldRunPopRevive) {
+ this.shouldRunPopRevive = shouldRunPopRevive;
}
- private boolean checkAndSetMaster() {
- isMaster = checkMaster();
- return isMaster;
+ public boolean isShouldRunPopRevive() {
+ return shouldRunPopRevive;
}
private void reviveRetry(PopCheckPoint popCheckPoint, MessageExt messageExt) throws Exception {
- if (!checkAndSetMaster()) {
+ if (!shouldRunPopRevive) {
POP_LOGGER.info("slave skip retry , revive topic={}, reviveQueueId={}", reviveTopic, queueId);
return;
}
@@ -109,8 +110,8 @@ public class PopReviveService extends ServiceThread {
PutMessageResult putMessageResult = brokerController.getMessageStore().putMessage(msgInner);
if (brokerController.getBrokerConfig().isEnablePopLog()) {
POP_LOGGER.info("reviveQueueId={},retry msg , ck={}, msg queueId {}, offset {}, reviveDelay={}, result is {} ",
- queueId, popCheckPoint, messageExt.getQueueId(), messageExt.getQueueOffset(),
- (System.currentTimeMillis() - popCheckPoint.getReviveTime()) / 1000, putMessageResult);
+ queueId, popCheckPoint, messageExt.getQueueId(), messageExt.getQueueOffset(),
+ (System.currentTimeMillis() - popCheckPoint.getReviveTime()) / 1000, putMessageResult);
}
if (putMessageResult.getAppendMessageResult() == null || putMessageResult.getAppendMessageResult().getStatus() != AppendMessageStatus.PUT_OK) {
throw new Exception("reviveQueueId=" + queueId + ",revive error ,msg is :" + msgInner);
@@ -120,9 +121,9 @@ public class PopReviveService extends ServiceThread {
this.brokerController.getBrokerStatsManager().incTopicPutSize(msgInner.getTopic(), putMessageResult.getAppendMessageResult().getWroteBytes());
if (brokerController.getPopMessageProcessor() != null) {
brokerController.getPopMessageProcessor().notifyMessageArriving(
- KeyBuilder.parseNormalTopic(popCheckPoint.getTopic(), popCheckPoint.getCId()),
- popCheckPoint.getCId(),
- -1
+ KeyBuilder.parseNormalTopic(popCheckPoint.getTopic(), popCheckPoint.getCId()),
+ popCheckPoint.getCId(),
+ -1
);
}
}
@@ -136,19 +137,21 @@ public class PopReviveService extends ServiceThread {
}
private void addRetryTopicIfNoExit(String topic, String consumerGroup) {
- TopicConfig topicConfig = brokerController.getTopicConfigManager().selectTopicConfig(topic);
- if (topicConfig != null) {
- return;
+ if (brokerController != null) {
+ TopicConfig topicConfig = brokerController.getTopicConfigManager().selectTopicConfig(topic);
+ if (topicConfig != null) {
+ return;
+ }
+ topicConfig = new TopicConfig(topic);
+ topicConfig.setReadQueueNums(PopAckConstants.retryQueueNum);
+ topicConfig.setWriteQueueNums(PopAckConstants.retryQueueNum);
+ topicConfig.setTopicFilterType(TopicFilterType.SINGLE_TAG);
+ topicConfig.setPerm(6);
+ topicConfig.setTopicSysFlag(0);
+ brokerController.getTopicConfigManager().updateTopicConfig(topicConfig);
+
+ initPopRetryOffset(topic, consumerGroup);
}
- topicConfig = new TopicConfig(topic);
- topicConfig.setReadQueueNums(PopAckConstants.retryQueueNum);
- topicConfig.setWriteQueueNums(PopAckConstants.retryQueueNum);
- topicConfig.setTopicFilterType(TopicFilterType.SINGLE_TAG);
- topicConfig.setPerm(6);
- topicConfig.setTopicSysFlag(0);
- brokerController.getTopicConfigManager().updateTopicConfig(topicConfig);
-
- initPopRetryOffset(topic, consumerGroup);
}
private List<MessageExt> getReviveMessage(long offset, int queueId) {
@@ -160,33 +163,26 @@ public class PopReviveService extends ServiceThread {
POP_LOGGER.info("reviveQueueId={}, reach tail,offset {}", queueId, offset);
} else if (pullResult.getPullStatus() == PullStatus.OFFSET_ILLEGAL || pullResult.getPullStatus() == PullStatus.NO_MATCHED_MSG) {
POP_LOGGER.error("reviveQueueId={}, OFFSET_ILLEGAL {}, result is {}", queueId, offset, pullResult);
- if (!checkAndSetMaster()) {
+ if (!shouldRunPopRevive) {
POP_LOGGER.info("slave skip offset correct topic={}, reviveQueueId={}", reviveTopic, queueId);
return null;
}
- brokerController.getConsumerOffsetManager().commitOffset(PopAckConstants.LOCAL_HOST, PopAckConstants.REVIVE_GROUP, reviveTopic, queueId, pullResult.getNextBeginOffset() - 1);
+ this.brokerController.getConsumerOffsetManager().commitOffset(PopAckConstants.LOCAL_HOST, PopAckConstants.REVIVE_GROUP, reviveTopic, queueId, pullResult.getNextBeginOffset() - 1);
}
return pullResult.getMsgFoundList();
}
private boolean reachTail(PullResult pullResult, long offset) {
return pullResult.getPullStatus() == PullStatus.NO_NEW_MSG
- || (pullResult.getPullStatus() == PullStatus.OFFSET_ILLEGAL && offset == pullResult.getMaxOffset());
+ || (pullResult.getPullStatus() == PullStatus.OFFSET_ILLEGAL && offset == pullResult.getMaxOffset());
}
- private MessageExt getBizMessage(String topic, long offset, int queueId) {
- final GetMessageResult getMessageTmpResult = brokerController.getMessageStore().getMessage(PopAckConstants.REVIVE_GROUP, topic, queueId, offset, 1, null);
- List<MessageExt> list = decodeMsgList(getMessageTmpResult);
- if (list == null || list.isEmpty()) {
- POP_LOGGER.warn("can not get msg , topic {}, offset {}, queueId {}, result is {}", topic, offset, queueId, getMessageTmpResult);
- return null;
- } else {
- return list.get(0);
- }
+ private MessageExt getBizMessage(String topic, long offset, int queueId, String brokerName) {
+ return this.brokerController.getEscapeBridge().getMessage(topic, offset, queueId, brokerName);
}
public PullResult getMessage(String group, String topic, int queueId, long offset, int nums) {
- GetMessageResult getMessageResult = brokerController.getMessageStore().getMessage(group, topic, queueId, offset, nums, null);
+ GetMessageResult getMessageResult = this.brokerController.getMessageStore().getMessage(group, topic, queueId, offset, nums, null);
if (getMessageResult != null) {
PullStatus pullStatus = PullStatus.NO_NEW_MSG;
@@ -199,17 +195,17 @@ public class PopReviveService extends ServiceThread {
... 6336 lines suppressed ...