Java tutorial
/** * Copyright (C) 2010-2013 Alibaba Group Holding Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.rocketmq.broker.processor; import io.netty.channel.ChannelHandlerContext; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; import com.alibaba.rocketmq.broker.client.ClientChannelInfo; import com.alibaba.rocketmq.broker.client.ConsumerGroupInfo; import com.alibaba.rocketmq.broker.mqtrace.ConsumeMessageContext; import com.alibaba.rocketmq.broker.mqtrace.ConsumeMessageHook; import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.common.constant.PermName; import com.alibaba.rocketmq.common.protocol.RequestCode; import com.alibaba.rocketmq.common.protocol.ResponseCode; import com.alibaba.rocketmq.common.protocol.header.GetConsumerListByGroupRequestHeader; import com.alibaba.rocketmq.common.protocol.header.GetConsumerListByGroupResponseBody; import com.alibaba.rocketmq.common.protocol.header.GetConsumerListByGroupResponseHeader; import com.alibaba.rocketmq.common.protocol.header.QueryConsumerOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.QueryConsumerOffsetResponseHeader; import com.alibaba.rocketmq.common.protocol.header.UnregisterClientRequestHeader; import com.alibaba.rocketmq.common.protocol.header.UnregisterClientResponseHeader; import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetRequestHeader; import com.alibaba.rocketmq.common.protocol.header.UpdateConsumerOffsetResponseHeader; import com.alibaba.rocketmq.common.protocol.heartbeat.ConsumerData; import com.alibaba.rocketmq.common.protocol.heartbeat.HeartbeatData; import com.alibaba.rocketmq.common.protocol.heartbeat.ProducerData; import com.alibaba.rocketmq.common.subscription.SubscriptionGroupConfig; import com.alibaba.rocketmq.common.sysflag.TopicSysFlag; import com.alibaba.rocketmq.remoting.common.RemotingHelper; import com.alibaba.rocketmq.remoting.exception.RemotingCommandException; import com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; /** * Client? * * @author shijia.wxr<vintage.wang@gmail.com> * @since 2013-7-26 */ public class ClientManageProcessor implements NettyRequestProcessor { private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final BrokerController brokerController; public ClientManageProcessor(final BrokerController brokerController) { this.brokerController = brokerController; } @Override public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { switch (request.getCode()) { case RequestCode.HEART_BEAT: return this.heartBeat(ctx, request); case RequestCode.UNREGISTER_CLIENT: return this.unregisterClient(ctx, request); case RequestCode.GET_CONSUMER_LIST_BY_GROUP: return this.getConsumerListByGroup(ctx, request); // Consumer Offset case RequestCode.UPDATE_CONSUMER_OFFSET: return this.updateConsumerOffset(ctx, request); case RequestCode.QUERY_CONSUMER_OFFSET: return this.queryConsumerOffset(ctx, request); default: break; } return null; } /** * ??? */ private List<ConsumeMessageHook> consumeMessageHookList; public boolean hasConsumeMessageHook() { return consumeMessageHookList != null && !this.consumeMessageHookList.isEmpty(); } public void registerConsumeMessageHook(List<ConsumeMessageHook> consumeMessageHookList) { this.consumeMessageHookList = consumeMessageHookList; } public void executeConsumeMessageHookAfter(final ConsumeMessageContext context) { if (hasConsumeMessageHook()) { for (ConsumeMessageHook hook : this.consumeMessageHookList) { try { hook.consumeMessageAfter(context); } catch (Throwable e) { } } } } private RemotingCommand updateConsumerOffset(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { final RemotingCommand response = RemotingCommand .createResponseCommand(UpdateConsumerOffsetResponseHeader.class); // final UpdateConsumerOffsetResponseHeader responseHeader = // (UpdateConsumerOffsetResponseHeader) response.readCustomHeader(); final UpdateConsumerOffsetRequestHeader requestHeader = (UpdateConsumerOffsetRequestHeader) request .decodeCommandCustomHeader(UpdateConsumerOffsetRequestHeader.class); // ????? offset ? if (this.hasConsumeMessageHook()) { // hook ConsumeMessageContext context = new ConsumeMessageContext(); context.setConsumerGroup(requestHeader.getConsumerGroup()); context.setTopic(requestHeader.getTopic()); context.setClientHost(RemotingHelper.parseChannelRemoteAddr(ctx.channel())); context.setSuccess(true); context.setStatus(ConsumeConcurrentlyStatus.CONSUME_SUCCESS.toString()); final SocketAddress storeHost = new InetSocketAddress(brokerController.getBrokerConfig().getBrokerIP1(), brokerController.getNettyServerConfig().getListenPort()); long preOffset = this.brokerController.getConsumerOffsetManager().queryOffset( requestHeader.getConsumerGroup(), requestHeader.getTopic(), requestHeader.getQueueId()); Map<String, Long> messageIds = this.brokerController.getMessageStore().getMessageIds( requestHeader.getTopic(), requestHeader.getQueueId(), preOffset, requestHeader.getCommitOffset(), storeHost); context.setMessageIds(messageIds); this.executeConsumeMessageHookAfter(context); } this.brokerController.getConsumerOffsetManager().commitOffset(requestHeader.getConsumerGroup(), requestHeader.getTopic(), requestHeader.getQueueId(), requestHeader.getCommitOffset()); response.setCode(ResponseCode.SUCCESS); response.setRemark(null); return response; } private RemotingCommand queryConsumerOffset(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { final RemotingCommand response = RemotingCommand .createResponseCommand(QueryConsumerOffsetResponseHeader.class); final QueryConsumerOffsetResponseHeader responseHeader = (QueryConsumerOffsetResponseHeader) response .readCustomHeader(); final QueryConsumerOffsetRequestHeader requestHeader = (QueryConsumerOffsetRequestHeader) request .decodeCommandCustomHeader(QueryConsumerOffsetRequestHeader.class); long offset = this.brokerController.getConsumerOffsetManager().queryOffset(requestHeader.getConsumerGroup(), requestHeader.getTopic(), requestHeader.getQueueId()); // if (offset >= 0) { responseHeader.setOffset(offset); response.setCode(ResponseCode.SUCCESS); response.setRemark(null); } // ? else { long minOffset = this.brokerController.getMessageStore().getMinOffsetInQuque(requestHeader.getTopic(), requestHeader.getQueueId()); // ???Offset0Topic????0 // Topic??0 if (minOffset <= 0 && !this.brokerController.getMessageStore() .checkInDiskByConsumeOffset(requestHeader.getTopic(), requestHeader.getQueueId(), 0)) { responseHeader.setOffset(0L); response.setCode(ResponseCode.SUCCESS); response.setRemark(null); } // ??? else { response.setCode(ResponseCode.QUERY_NOT_FOUND); response.setRemark("Not found, V3_0_6_SNAPSHOT maybe this group consumer boot first"); } } return response; } public RemotingCommand getConsumerListByGroup(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { final RemotingCommand response = RemotingCommand .createResponseCommand(GetConsumerListByGroupResponseHeader.class); final GetConsumerListByGroupRequestHeader requestHeader = (GetConsumerListByGroupRequestHeader) request .decodeCommandCustomHeader(GetConsumerListByGroupRequestHeader.class); ConsumerGroupInfo consumerGroupInfo = this.brokerController.getConsumerManager() .getConsumerGroupInfo(requestHeader.getConsumerGroup()); if (consumerGroupInfo != null) { List<String> clientIds = consumerGroupInfo.getAllClientId(); if (!clientIds.isEmpty()) { GetConsumerListByGroupResponseBody body = new GetConsumerListByGroupResponseBody(); body.setConsumerIdList(clientIds); response.setBody(body.encode()); response.setCode(ResponseCode.SUCCESS); response.setRemark(null); return response; } else { log.warn("getAllClientId failed, {} {}", requestHeader.getConsumerGroup(), RemotingHelper.parseChannelRemoteAddr(ctx.channel())); } } else { log.warn("getConsumerGroupInfo failed, {} {}", requestHeader.getConsumerGroup(), RemotingHelper.parseChannelRemoteAddr(ctx.channel())); } response.setCode(ResponseCode.SYSTEM_ERROR); response.setRemark("no consumer for this group, " + requestHeader.getConsumerGroup()); return response; } public RemotingCommand unregisterClient(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { final RemotingCommand response = RemotingCommand .createResponseCommand(UnregisterClientResponseHeader.class); final UnregisterClientRequestHeader requestHeader = (UnregisterClientRequestHeader) request .decodeCommandCustomHeader(UnregisterClientRequestHeader.class); ClientChannelInfo clientChannelInfo = new ClientChannelInfo(// ctx.channel(), // requestHeader.getClientID(), // request.getLanguage(), // request.getVersion()// ); // Producer { final String group = requestHeader.getProducerGroup(); if (group != null) { this.brokerController.getProducerManager().unregisterProducer(group, clientChannelInfo); } } // Consumer { final String group = requestHeader.getConsumerGroup(); if (group != null) { this.brokerController.getConsumerManager().unregisterConsumer(group, clientChannelInfo); } } response.setCode(ResponseCode.SUCCESS); response.setRemark(null); return response; } public RemotingCommand heartBeat(ChannelHandlerContext ctx, RemotingCommand request) { RemotingCommand response = RemotingCommand.createResponseCommand(null); HeartbeatData heartbeatData = HeartbeatData.decode(request.getBody(), HeartbeatData.class); ClientChannelInfo clientChannelInfo = new ClientChannelInfo(// ctx.channel(), // heartbeatData.getClientID(), // request.getLanguage(), // request.getVersion()// ); // Consumer for (ConsumerData data : heartbeatData.getConsumerDataSet()) { SubscriptionGroupConfig subscriptionGroupConfig = this.brokerController.getSubscriptionGroupManager() .findSubscriptionGroupConfig(data.getGroupName()); if (null != subscriptionGroupConfig) { // ?? topic int topicSysFlag = 0; if (data.isUnitMode()) { topicSysFlag = TopicSysFlag.buildSysFlag(false, true); } String newTopic = MixAll.getRetryTopic(data.getGroupName()); this.brokerController.getTopicConfigManager().createTopicInSendMessageBackMethod(// newTopic, // subscriptionGroupConfig.getRetryQueueNums(), // PermName.PERM_WRITE | PermName.PERM_READ, topicSysFlag); } boolean changed = this.brokerController.getConsumerManager().registerConsumer(// data.getGroupName(), // clientChannelInfo, // data.getConsumeType(), // data.getMessageModel(), // data.getConsumeFromWhere(), // data.getSubscriptionDataSet()// ); if (changed) { log.info("registerConsumer info changed {} {}", // data.toString(), // RemotingHelper.parseChannelRemoteAddr(ctx.channel())// ); // todo:??? // for (SubscriptionData subscriptionData : // data.getSubscriptionDataSet()) { // this.brokerController.getTopicConfigManager().updateTopicUnitSubFlag( // subscriptionData.getTopic(), data.isUnitMode()); // } } } // Producer for (ProducerData data : heartbeatData.getProducerDataSet()) { this.brokerController.getProducerManager().registerProducer(data.getGroupName(), clientChannelInfo); } response.setCode(ResponseCode.SUCCESS); response.setRemark(null); return response; } }