dubbo源码学习笔记----monitor

本文解析了Dubbo中Monitor的实现原理,包括如何通过监听器获取Monitor信息、使用线程池定时拉取数据以及与注册中心的集成。介绍了Monitor状态跟踪类的创建过程,并展示了如何配置和使用Monitor服务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

核心类

public abstract class AbstractMonitorFactory implements MonitorFactory {
    private static final Logger logger = LoggerFactory.getLogger(AbstractMonitorFactory.class);

    // lock for getting monitor center
    private static final ReentrantLock LOCK = new ReentrantLock();

    // monitor centers Map<RegistryAddress, Registry>
    private static final Map<String, Monitor> MONITORS = new ConcurrentHashMap<String, Monitor>();

    private static final Map<String, ListenableFuture<Monitor>> FUTURES = new ConcurrentHashMap<String, ListenableFuture<Monitor>>();

    private static final ExecutorService executor = new ThreadPoolExecutor(0, 10, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new NamedThreadFactory("DubboMonitorCreator", true));

    public static Collection<Monitor> getMonitors() {
        return Collections.unmodifiableCollection(MONITORS.values());
    }

针对于每个注册进来的URL有个对应的Monitor状态跟踪类,每个Monitor状态跟踪类,通过一个Listener进行绑定。

    class MonitorListener implements Runnable {

        private String key;

        public MonitorListener(String key) {
            this.key = key;
        }

        @Override
        public void run() {
            try {
                ListenableFuture<Monitor> listenableFuture = AbstractMonitorFactory.FUTURES.get(key);
                AbstractMonitorFactory.MONITORS.put(key, listenableFuture.get());
                AbstractMonitorFactory.FUTURES.remove(key);
            } catch (InterruptedException e) {
                logger.warn("Thread was interrupted unexpectedly, monitor will never be got.");
                AbstractMonitorFactory.FUTURES.remove(key);
            } catch (ExecutionException e) {
                logger.warn("Create monitor failed, monitor data will not be collected until you fix this problem. ", e);
            }
        }
    }

将这个Listener交给一个线程池定时拉取Monitor信息。

        LOCK.lock();
        try {
            monitor = MONITORS.get(key);
            future = FUTURES.get(key);
            if (monitor != null || future != null) {
                return monitor;
            }

            final URL monitorUrl = url;
            final ListenableFutureTask<Monitor> listenableFutureTask = ListenableFutureTask.create(new MonitorCreator(monitorUrl));
            listenableFutureTask.addListener(new MonitorListener(key));
            executor.execute(listenableFutureTask);
            FUTURES.put(key, listenableFutureTask);

            return null;
        } finally {
            // unlock
            LOCK.unlock();
        }

Monitor使用

    <bean id="monitorService" class="com.alibaba.dubbo.monitor.simple.SimpleMonitorService">
    </bean>

    <dubbo:application name="${dubbo.application.name}" owner="${dubbo.application.owner}"/>

    <dubbo:registry address="${dubbo.registry.address}"/>

    <dubbo:protocol name="dubbo" port="${dubbo.protocol.port}"/>

    <dubbo:service interface="com.alibaba.dubbo.monitor.MonitorService" ref="monitorService" delay="-1"/>

    <dubbo:reference id="registryService" interface="com.alibaba.dubbo.registry.RegistryService"/>

Monitor信息应该是和注册中心信息放在一起,redis或是zookeeper。

容器container核心方法两个:

public interface Container {

    /**
     * start.
     */
    void start();

    /**
     * stop.
     */
    void stop();

}

代理方式收集monitor信息

    public SimpleMonitorService() {
        queue = new LinkedBlockingQueue<URL>(Integer.parseInt(ConfigUtils.getProperty("dubbo.monitor.queue", "100000")));
        writeThread = new Thread(new Runnable() {
            public void run() {
                while (running) {
                    try {
                        write(); // write statistics
                    } catch (Throwable t) {
                        logger.error("Unexpected error occur at write stat log, cause: " + t.getMessage(), t);
                        try {
                            Thread.sleep(5000); // retry after 5 secs
                        } catch (Throwable t2) {
                        }
                    }
                }
            }
        });
        writeThread.setDaemon(true);
        writeThread.setName("DubboMonitorAsyncWriteLogThread");
        writeThread.start();
        chartFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
            public void run() {
                try {
                    draw(); // draw chart
                } catch (Throwable t) {
                    logger.error("Unexpected error occur at draw stat chart, cause: " + t.getMessage(), t);
                }
            }
        }, 1, 300, TimeUnit.SECONDS);
        statisticsDirectory = ConfigUtils.getProperty("dubbo.statistics.directory");
        chartsDirectory = ConfigUtils.getProperty("dubbo.charts.directory");
    }

起了一个后台线程写信息到本地文件,定时采集Monitor信息同步到统一Monitor中心。

转载于:https://my.oschina.net/u/1000241/blog/1606784

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值