码迷,mamicode.com
首页 > 编程语言 > 详细

SpringBoot-技术专区-实战方案-应用监控线程池

时间:2019-12-01 18:41:52      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:tor   end   方法   因此   log   cat   target   背景   set   

背景

  废话不多说,做这个监控的背景很简单,我们的项目都是以spring boot框架为基础开发的,代码里所有的异步线程都是通过@Async标签标注的,并且标注的时候都是指定对应线程池的,如果不知@Async标注的,可以参考@Async异步线程池用法总结, 如果你用的不是spring,就参考上文提到的公众号文章就好。再回到背景,我们当时经常遇到的问题就是这些线程池的队列满了之后,新的异步任务无法添加进去的错误,因此我们想对所有这种类型的线程池进行监控。

监控方式

  再来介绍一下我们最终采用的方式 —— spring boot + statsd, 通过添加以下代码就可以使statd能够读取/metrics接口中所有的指标并发送监控数据到statsd后端,statsd并不是本篇文章的重点,之后有时间再细讲这部分的配置


@Bean
public MetricsEndpointMetricReader metricsEndpointMetricReader(final MetricsEndpoint metricsEndpoint) {
    return new MetricsEndpointMetricReader(metricsEndpoint);
}

代码及效果

  我们所需要做的就是向/metrics接口添加线程池的指标,庆幸的是spring boot提供了良好的扩展机制,只需要实现PublicMetrics接口,实现其中的metrics方法你就能在/metrics中看到你新增的指标,上代码:

@Component
public class AsyncThreadPoolMetrics implements PublicMetrics {
    public static final Logger LOG = LoggerFactory.getLogger(AsyncThreadPoolMetrics.class);
    private Map<String, ThreadPoolTaskExecutor> targetAsyncThreadPool;
    private static final String pattern = "async.task.%s.%s";
    @Autowired
    ApplicationContext context;
    @Override
    public Collection<Metric<?>> metrics() {
        try {
            if(targetAsyncThreadPool == null || targetAsyncThreadPool.size() == 0) {
                targetAsyncThreadPool = context.getBeansOfType(ThreadPoolTaskExecutor.class);
            }
            Collection<Metric<?>> result = new ArrayList<>();
            for (Map.Entry<String, ThreadPoolTaskExecutor> entry: targetAsyncThreadPool.entrySet()) {
                ThreadPoolTaskExecutor executor =  entry.getValue();
                result.add(new Metric<Number>(String.format(pattern, entry.getKey(), "aciveCount"), executor.getActiveCount(), new Date()));
                result.add(new Metric<Number>(String.format(pattern, entry.getKey(), "currentPoolSize"), executor.getPoolSize(), new Date()));
                result.add(new Metric<Number>(String.format(pattern, entry.getKey(), "maxPoolSize"), executor.getMaxPoolSize(), new Date()));
                result.add(new Metric<Number>(String.format(pattern, entry.getKey(), "currentSizeInQueue"),   

      executor.getThreadPoolExecutor().getQueue().size(), new Date()));
            }
            return result;
        } catch (Exception e) {
            LOG.error("Async thread pool monitor exception", e);
        }
        return Collections.emptyList();
    }
}
  从上面的代码可以看出,我们监控的是多个线程池,原因很简单,为了使多种类型异步任务不互相影响,我们配置了多个线程池,多个线程池有不同的名字区分。
  其实代码很简单,首先从容器中找到所有实现ThreadPoolTaskExecutor的bean,也就是我们要监控的线程池对象,取出正在活动的线程数,线程池的大小,配置最大可容纳的线程数以及当前排队的任务,当然还有很多其他指标,大家都可以试试,我只是选出当时我们需要的指标。当我们访问此时应用的/metrics,效果如下,红色框标注的便是我们添加的指标:

SpringBoot-技术专区-实战方案-应用监控线程池

标签:tor   end   方法   因此   log   cat   target   背景   set   

原文地址:https://www.cnblogs.com/liboware/p/11966775.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!