RocketMQ源码 Broker-FilterServerManager 过滤服务器管理组件源码分析

前言

FilterServerManager 负责维护过滤服务器长连接 与 过滤服务器信息映射关系,并且内部有定时调度线程,不断检查过滤服务器实际数量和配置数量是否一致,如果不一致,就根据配置构建命令行命令,执行命令启动 FilterServer 过滤服务器进程。

过滤服务器实例,是RockerMQ的高级功能,复制支持更复杂的过滤条件。

源码版本:4.9.3

源码架构图

核心数据结构

java 复制代码
// 过滤服务器管理组件
public class FilterServerManager {

    // 过滤服务器最大空闲时间,30秒
    public static final long FILTER_SERVER_MAX_IDLE_TIME_MILLS = 30000;
    private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
    // 过滤服务器长连接 与 过滤服务器信息映射关系
    private final ConcurrentMap<Channel, FilterServerInfo> filterServerTable =
        new ConcurrentHashMap<Channel, FilterServerInfo>(16);
    private final BrokerController brokerController;

    // 过滤服务器定时调度线程池
    private ScheduledExecutorService scheduledExecutorService = Executors
        .newSingleThreadScheduledExecutor(new ThreadFactoryImpl("FilterServerManagerScheduledThread"));
}
java 复制代码
    static class FilterServerInfo {
        // 过滤服务器地址
        private String filterServerAddr;
        // 最后更新时间戳
        private long lastUpdateTimestamp;
    }

核心行为方法

java 复制代码
// 过滤服务器管理组件
public class FilterServerManager {

    // 过滤服务器最大空闲时间,30秒
    public static final long FILTER_SERVER_MAX_IDLE_TIME_MILLS = 30000;
    private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
    // 过滤服务器长连接 与 过滤服务器信息映射关系
    private final ConcurrentMap<Channel, FilterServerInfo> filterServerTable =
        new ConcurrentHashMap<Channel, FilterServerInfo>(16);
    private final BrokerController brokerController;

    // 过滤服务器定时调度线程池
    private ScheduledExecutorService scheduledExecutorService = Executors
        .newSingleThreadScheduledExecutor(new ThreadFactoryImpl("FilterServerManagerScheduledThread"));

    public FilterServerManager(final BrokerController brokerController) {
        this.brokerController = brokerController;
    }

    public void start() {

        // 注册调度任务,每隔30秒扫描一次过滤服务器
        this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    FilterServerManager.this.createFilterServer();
                } catch (Exception e) {
                    log.error("", e);
                }
            }
        }, 1000 * 5, 1000 * 30, TimeUnit.MILLISECONDS);
    }

    // 创建过滤服务器
    public void createFilterServer() {
        int more =
            this.brokerController.getBrokerConfig().getFilterServerNums() - this.filterServerTable.size();
        String cmd = this.buildStartCommand();
        for (int i = 0; i < more; i++) {
            // 启动过滤服务器
            FilterServerUtil.callShell(cmd, log);
        }
    }

    // 构建过滤服务器启动命令
    private String buildStartCommand() {
        String config = "";
        if (BrokerStartup.configFile != null) {
            config = String.format("-c %s", BrokerStartup.configFile);
        }

        if (this.brokerController.getBrokerConfig().getNamesrvAddr() != null) {
            config += String.format(" -n %s", this.brokerController.getBrokerConfig().getNamesrvAddr());
        }

        if (RemotingUtil.isWindowsPlatform()) {
            return String.format("start /b %s\\bin\\mqfiltersrv.exe %s",
                this.brokerController.getBrokerConfig().getRocketmqHome(),
                config);
        } else {
            return String.format("sh %s/bin/startfsrv.sh %s",
                this.brokerController.getBrokerConfig().getRocketmqHome(),
                config);
        }
    }

    public void shutdown() {
        this.scheduledExecutorService.shutdown();
    }

    // 注册过滤服务器
    public void registerFilterServer(final Channel channel, final String filterServerAddr) {
        FilterServerInfo filterServerInfo = this.filterServerTable.get(channel);
        if (filterServerInfo != null) {
            filterServerInfo.setLastUpdateTimestamp(System.currentTimeMillis());
        } else {
            filterServerInfo = new FilterServerInfo();
            filterServerInfo.setFilterServerAddr(filterServerAddr);
            filterServerInfo.setLastUpdateTimestamp(System.currentTimeMillis());
            this.filterServerTable.put(channel, filterServerInfo);
            log.info("Receive a New Filter Server<{}>", filterServerAddr);
        }
    }

    // 扫描过期的过滤服务器
    public void scanNotActiveChannel() {

        Iterator<Entry<Channel, FilterServerInfo>> it = this.filterServerTable.entrySet().iterator();
        while (it.hasNext()) {
            Entry<Channel, FilterServerInfo> next = it.next();
            long timestamp = next.getValue().getLastUpdateTimestamp();
            Channel channel = next.getKey();
            // 过滤服务器超过30秒没有更新,则删除
            if ((System.currentTimeMillis() - timestamp) > FILTER_SERVER_MAX_IDLE_TIME_MILLS) {
                log.info("The Filter Server<{}> expired, remove it", next.getKey());
                // 删除内存中的过滤服务器信息
                it.remove();
                // 关闭过滤服务器连接
                RemotingUtil.closeChannel(channel);
            }
        }
    }

    // 过滤服务器连接关闭事件
    public void doChannelCloseEvent(final String remoteAddr, final Channel channel) {
        FilterServerInfo old = this.filterServerTable.remove(channel);
        if (old != null) {
            log.warn("The Filter Server<{}> connection<{}> closed, remove it", old.getFilterServerAddr(),
                remoteAddr);
        }
    }

    // 构建新的过滤服务器列表
    public List<String> buildNewFilterServerList() {
        List<String> addr = new ArrayList<>();
        Iterator<Entry<Channel, FilterServerInfo>> it = this.filterServerTable.entrySet().iterator();
        while (it.hasNext()) {
            Entry<Channel, FilterServerInfo> next = it.next();
            addr.add(next.getValue().getFilterServerAddr());
        }
        return addr;
    }

    static class FilterServerInfo {
        // 过滤服务器地址
        private String filterServerAddr;
        // 最后更新时间戳
        private long lastUpdateTimestamp;

        public String getFilterServerAddr() {
            return filterServerAddr;
        }

        public void setFilterServerAddr(String filterServerAddr) {
            this.filterServerAddr = filterServerAddr;
        }

        public long getLastUpdateTimestamp() {
            return lastUpdateTimestamp;
        }

        public void setLastUpdateTimestamp(long lastUpdateTimestamp) {
            this.lastUpdateTimestamp = lastUpdateTimestamp;
        }
    }
}
相关推荐
天天摸鱼的小学生1 分钟前
【Java Enum枚举】
java·开发语言
爬山算法14 分钟前
Redis(168) 如何使用Redis实现会话管理?
java·数据库·redis
程语有云19 分钟前
生产事故-那些年遇到过的OOM
java·内存·oom·生产事故
雨中飘荡的记忆22 分钟前
Spring Test详解
java·后端·spring
小熊officer25 分钟前
RocketMQ简介
rocketmq
sugar__salt31 分钟前
网络编程套接字(二)——TCP
java·网络·网络协议·tcp/ip·java-ee·javaee
颜颜yan_32 分钟前
跨越x86与ARM:openEuler全架构算力实战评测
java·arm开发·架构
毕设源码-朱学姐33 分钟前
【开题答辩全过程】以 陪诊就医小程序设计与实现为例,包含答辩的问题和答案
java
动感小麦兜43 分钟前
NAS学习
java·开发语言·eureka
小安同学iter1 小时前
天机学堂day05
java·开发语言·spring boot·分布式·后端·spring cloud·微服务