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;
        }
    }
}
相关推荐
王廷胡_白嫖帝9 分钟前
Qt文件压缩工具项目开发教程
java·开发语言·qt
渣哥34 分钟前
Java开发必看!序列化与反序列化到底有多重要?
java
仙俊红38 分钟前
使用jwt+redis实现单点登录
java
我是场41 分钟前
Android14内核调试 - boot & vendor_boot
java·开发语言·spring boot
fake_ss1981 小时前
从零开发Java坦克大战Ⅱ (下)-- 从单机到联机(完整架构功能实现)
java·网络·tcp/ip·游戏程序
lssjzmn1 小时前
java中,synchronized 关键字与 ReentrantLock 重入锁的区别以及应用场景,注意事项
java·后端
渣哥1 小时前
Spring循环依赖的终极解密:三级缓存如何拯救Bean创建死锁
java
小厂永远得不到的男人1 小时前
ioc 原理篇
java·后端
小厂永远得不到的男人1 小时前
Aop 原理篇
java
2 小时前
JAVA-15 (2025.08.20学习记录)
java·开发语言·学习