美文网首页
dubbo线程池监控

dubbo线程池监控

作者: GoddyWu | 来源:发表于2023-09-12 20:33 被阅读0次

    之前有遇到dubbo线程池枯竭的问题,但作为服务端不太好监控到自己的线程池已满。基于之前已经打通micrometer+prometheus+grafana来做java服务的实时监控,直接使用metrics实时上报到prometheus,贼方便

    1. 获取到dubbo的线程池

    因为dubbo线程数是一个波动的值,所以采用仪表盘(gauge)来存储数据

    dubbo 2.6.8

    import com.alibaba.dubbo.common.Constants;
    import com.alibaba.dubbo.common.extension.ExtensionLoader;
    import com.alibaba.dubbo.common.store.DataStore;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.Map;
    import java.util.Optional;
    import java.util.concurrent.ThreadPoolExecutor;
    
    @Slf4j
    public class DubboThreadPoolUtil {
    
        private static final String DEFAULT_PORT = "20880";
    
        /**
         * 获取dubbo的线程池
         */
        public static Optional<ThreadPoolExecutor> getThreadPool() {
            return getThreadPool(DEFAULT_PORT);
        }
    
        public static Optional<ThreadPoolExecutor> getThreadPool(String port) {
            DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
            Map<String, Object> executors = dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY);
            return Optional.ofNullable(executors.get(port)).map(executor -> {
                if (executor instanceof ThreadPoolExecutor) {
                    return (ThreadPoolExecutor) executor;
                } else {
                    return null;
                }
            });
        }
    
    }
    

    2. 搭配micrometer+prometheus使用

    import com.alibaba.dubbo.common.Constants;
    import com.alibaba.dubbo.common.extension.ExtensionLoader;
    import com.alibaba.dubbo.common.store.DataStore;
    import com.google.common.util.concurrent.ThreadFactoryBuilder;
    import io.micrometer.core.instrument.Metrics;
    import io.micrometer.core.instrument.Tag;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.Collections;
    import java.util.Map;
    import java.util.Optional;
    import java.util.concurrent.ScheduledThreadPoolExecutor;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    @Slf4j
    public class DubboThreadPoolUtil {
    
        private static final String DEFAULT_PORT = "20880";
    
        private static ScheduledThreadPoolExecutor scheduledExecutor;
        private static ThreadPoolExecutor dubboExecutor;
    
        /**
         * 获取dubbo的线程池
         */
        public static Optional<ThreadPoolExecutor> getThreadPool() {
            return getThreadPool(DEFAULT_PORT);
        }
    
        public static Optional<ThreadPoolExecutor> getThreadPool(String port) {
            DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
            Map<String, Object> executors = dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY);
            return Optional.ofNullable(executors.get(port)).map(executor -> {
                if (executor instanceof ThreadPoolExecutor) {
                    return (ThreadPoolExecutor) executor;
                } else {
                    return null;
                }
            });
        }
    
        public static void addMetricsWatcher() {
            addMetricsWatcher(DEFAULT_PORT);
        }
    
        public static void addMetricsWatcher(String port) {
            if (scheduledExecutor == null) {
                ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("dubbo-threadPool-watcher-%d").build();
                scheduledExecutor = new ScheduledThreadPoolExecutor(1, threadFactory);
            }
            scheduledExecutor.scheduleWithFixedDelay(() -> {
                if (dubboExecutor == null) {
                    Optional<ThreadPoolExecutor> threadPoolOptional = getThreadPool(port);
                    if (!threadPoolOptional.isPresent()) {
                        log.info("添加dubbo线程池监控【未成功,等1s重试】");
                        return;
                    }
                    dubboExecutor = threadPoolOptional.get();
                    log.info("添加dubbo线程池监控【完毕】");
                }
    
                Metrics.gauge("dubbo_threadPool", Collections.singletonList(Tag.of("indicator", "活跃线程数")), dubboExecutor, ThreadPoolExecutor::getActiveCount);
                Metrics.gauge("dubbo_threadPool", Collections.singletonList(Tag.of("indicator", "最大线程数")), dubboExecutor, ThreadPoolExecutor::getMaximumPoolSize);
    
            },  0,1, TimeUnit.SECONDS);
        }
    }
    

    3. 配置grafana图

    max(dubbo_threadPool{indicator="活跃线程数"})
    
    max(dubbo_threadPool{indicator="最大线程数"})
    

    效果如下


    值得注意的是,dubbo线程池默认采用的SynchronousQueue

    相关文章

      网友评论

          本文标题:dubbo线程池监控

          本文链接:https://www.haomeiwen.com/subject/zytyvdtx.html