/** * 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.client; import io.netty.channel.Channel; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.broker.BrokerController; import com.alibaba.rocketmq.common.constant.LoggerName; import com.alibaba.rocketmq.remoting.ChannelEventListener; /** * 定期检测客户端连接,清除不活动的连接 * * chen.si broker用来管理 producer和consumer 的连接,包括 * <p>1. 定期检测,判断连接是否为僵死连接,以将连接关闭</p> * <p>2. 接入netty,处理连接关闭/空闲/异常的事件,以将连接关闭</p> * * 实际上这里并未找到连接IDLE的事件,需要钻研下netty * * @author shijia.wxr<vintage.wang@gmail.com> * @since 2013-7-26 */ public class ClientHousekeepingService implements ChannelEventListener { private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName); private final BrokerController brokerController; private ScheduledExecutorService scheduledExecutorService = Executors .newSingleThreadScheduledExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r, "ClientHousekeepingScheduledThread"); } }); public ClientHousekeepingService(final BrokerController brokerController) { this.brokerController = brokerController; } public void start() { // 定时刷消费进度 this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { try { ClientHousekeepingService.this.scanExceptionChannel(); } catch (Exception e) { log.error("", e); } } }, 1000 * 10, 1000 * 10, TimeUnit.MILLISECONDS); } private void scanExceptionChannel() { this.brokerController.getProducerManager().scanNotActiveChannel(); this.brokerController.getConsumerManager().scanNotActiveChannel(); } public void shutdown() { this.scheduledExecutorService.shutdown(); } @Override public void onChannelConnect(String remoteAddr, Channel channel) { } @Override public void onChannelClose(String remoteAddr, Channel channel) { this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel); this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel); } @Override public void onChannelException(String remoteAddr, Channel channel) { this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel); this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel); } @Override public void onChannelIdle(String remoteAddr, Channel channel) { this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel); this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel); } }