背景

  废话不多说,做这个监控的背景很简单,我们的项目都是以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-技术专区-实战方案-应用监控线程池的更多相关文章

  1. 通过micrometer实时监控线程池的各项指标

    通过micrometer实时监控线程池的各项指标 前提 最近的一个项目中涉及到文件上传和下载,使用到JUC的线程池ThreadPoolExecutor,在生产环境中出现了某些时刻线程池满负载运作,由于 ...

  2. 开源动态可监控线程池DynamicTp介绍

    前言 使用线程池 ThreadPoolExecutor 过程中你是否有以下痛点呢? 代码中创建了一个 ThreadPoolExecutor,但是不知道那几个核心参数设置多少比较合适 凭经验设置参数值, ...

  3. Java利用线程工厂监控线程池

    目录 ThreadFactory 监控线程池 扩展线程池 扩展线程池示例 优化线程池大小 线程池死锁 线程池异常信息捕获 ThreadFactory 线程池中的线程从哪里来呢?就是ThreadFoct ...

  4. 使用Spring开发和监控线程池服务

    第1步:添加maven 项目 第2步:添加依赖库 将Spring的依赖添加到Maven的pom.xml文件中. 1 2 3 4 5 6 7 8 9 10 11 <!-- Spring 3 dep ...

  5. 用 ThreadPoolExecutor/ThreadPoolTaskExecutor 线程池技术提高系统吞吐量(附带线程池参数详解和使用注意事项)

    1.概述 在Java中,我们一般通过集成Thread类和实现Runnnable接口,调用线程的start()方法实现线程的启动.但如果并发的数量很多,而且每个线程都是执行很短的时间便结束了,那样频繁的 ...

  6. Java并发编程实战 第8章 线程池的使用

    合理的控制线程池的大小: 下面内容来自网络.不过跟作者说的一致.不想自己敲了.留个记录. 要想合理的配置线程池的大小,首先得分析任务的特性,可以从以下几个角度分析: 任务的性质:CPU密集型任务.IO ...

  7. Java并发编程原理与实战三十七:线程池的原理与使用

    一.简介 线程池在我们的高并发环境下,实际应用是非常多的!!适用频率非常高! 有过使用过Executors框架的朋友,可能不太知道底层的实现,这里就是讲Executors是由ThreadPoolExe ...

  8. java并发编程实战:第八章----线程池的使用

    一.在任务和执行策略之间隐性耦合 Executor框架将任务的提交和它的执行策略解耦开来.虽然Executor框架为制定和修改执行策略提供了相当大的灵活性,但并非所有的任务都能适用所有的执行策略. 依 ...

  9. 《Java并发编程实战》第八章 线程池的使用 读书笔记

    一.在任务与运行策略之间的隐性解耦 有些类型的任务须要明白地指定运行策略,包含: . 依赖性任务.依赖关系对运行策略造成约束.须要注意活跃性问题. 要求线程池足够大,确保任务都能放入. . 使用线程封 ...

随机推荐

  1. resolver - 解析器(resolver) 配置文件

    总览 (SYNOPSIS) /etc/resolv.conf 描述 (DESCRIPTION) 解析器(resolver) 是 C 函数库 中 的 一组 例程, 用于 访问 Internet 域名系统 ...

  2. Matomo(Piwik)安装说明-----------基于LNPM环境

    Matomo(Piwik)安装说明 安装前环境检查 Piwik要求PHP版本高于PHP5.5(选用PHP7.2) Piwik需要pdo和pdo_mysql或mysqli支持(选用mysqli) Piw ...

  3. js代码检测设备问题:为什么在移动端检测设备的时候会出现pc的页面

    为了在手机上也能正常显示页面,所以为之前写的页面又重写了一遍,专门用来在移动端显示,用js代码检测设备,如果是pc就显示pc的页面,如果是移动就显示移动的页面,但遇到一个问题就是在移动端打开会有一个延 ...

  4. java 抽象的概念 抽象类的使用

    package java10; /* 抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束 抽象类:抽象方法所在的类,必须是抽象类才行.在class之前写上abstract即可 如何 ...

  5. LeetCode(力扣)——Search in Rotated Sorted Array2 搜索旋转排序数组 python实现

    题目描述: python实现 Search in Rotated Sorted Array2 搜索旋转排序数组   中文: 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0 ...

  6. 计蒜客NOIP模拟D1T2

    原题: 蒜头君有一棵有根树,树的每一边都有边权,蒜头君想知道任意两点间最短距离之和为多少.另外,由于各种原因,蒜头君的树的边的边权会发生若干次改变,蒜头君想让你告诉他,每一次改变后,任意两点间最短距离 ...

  7. 【leetcode】726. Number of Atoms

    题目如下: 解题思路:我用的是递归的方法,每次找出与第一个')'匹配的'('计算atom的数量后去除括号,只到分子式中没有括号为止.例如 "K4(ON(SO3)2)2" -> ...

  8. shell脚本条件测试与比较

    1.条件测试常用语法 test 测试表达式 利用test命令进行条件测试表达式,test命令与测试表达式之间至少有一个空格 [ 测试表达式 ] 通过[ ]中括号进行条件测试表达式,[]中括号边界与测试 ...

  9. <三剑客> 老大:awk命令用法

    awk是一种编程语言,用于在linux/unix下对文本和数据进行处理.数据可以来自标准输入(stdin).一 个或多个文件,或其它命令的输出.它支持用户自定义函数和动态正则表达式等先进功能,是lin ...

  10. Activity 启动模式总结

    Activity 启动模式: 1. standard: 默认启动模式,每次启动一个Activity都会重新创建一个实例: 2. singleTop: 栈顶复用模式,新Activity位于任务栈的栈顶, ...