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;
        }
    }
}
相关推荐
YAy1726 分钟前
CC3学习记录
java·开发语言·学习·网络安全·安全威胁分析
代码小鑫27 分钟前
A035-基于Spring Boot的企业内管信息化系统
java·开发语言·spring boot·后端·spring
qq_35323353891 小时前
【原创】java+ssm+mysql校园疫情防控管理系统设计与实现
java·mvc·javaweb·ssm框架·bs·疫情防控
代码调试4 小时前
Springboot校园失物招领平台
java·spring boot
camellias_5 小时前
SpringBoot(二十三)SpringBoot集成JWT
java·spring boot·后端
tebukaopu1485 小时前
springboot如何获取控制层get和Post入参
java·spring boot·后端
昔我往昔5 小时前
SpringBoot 创建对象常见的几种方式
java·spring boot·后端
q567315235 小时前
用 PHP或Python加密字符串,用iOS解密
java·python·ios·缓存·php·命令模式
灭掉c与java6 小时前
第三章springboot数据访问
java·spring boot·后端
啊松同学6 小时前
【Java】设计模式——工厂模式
java·后端·设计模式