当前位置: 首页 > 知识库问答 >
问题:

使用Dropwizard指标报告JVM的CPU使用情况

惠洛华
2023-03-14

我使用Dropwizard指标来衡量应用程序中的各种指标。它们是JVM检测中的几个预定义报告器,但奇怪的是,我找不到任何报告CPU使用情况的报告器。

我可以创建自己的Gauge(使用getThreadCpuTime或类似工具),但我最好的猜测是我错过了一些东西。

我是否在当前的实现中错过了它,或者它比我最初想象的更复杂?

共有1个答案

柯昱
2023-03-14

我对Dropwizard了解不多,但我过去曾使用ThreadMXBean来估计可扩展分布式计算系统中的CPU利用率,因此我将分享我认为与这个问题相关的内容。事情肯定比第一次出现时更复杂:

ThreadMxBean有点误导...

ThreadMxBean。getThreadCpuTime(id)仅返回特定线程自线程启动以来在CPU上执行代码的总时间,以纳秒为单位。它没有提供关于线程被阻塞或等待(Hibernate)多长时间的信息,因此它确实不能让您很好地了解CPU的使用情况。您还需要测量总阻塞/等待时间,然后在程序运行时跟踪这三个值,以跟踪CPU使用情况。奇怪的是,ThreadMXBean没有直接获取阻塞/等待时间的方法,因此您可能会试图放弃。

... 但是你可以用它来获取一个ThreadInfo对象。。。

首先,要启用它,请调用这两行(如果您的JVM不支持它,这可能会引发异常):

ManagementFactory.getThreadMXBean().setThreadCpuTimeEnabled(true);
ManagementFactory.getThreadMXBean().setThreadContentionMonitoringEnabled(true);

现在可以调用ThreadMXBean。getThreadInfo(threadId)获取对应于特定线程的ThreadInfo的实例。此信息对象有两个方法,getBlockedTime()和getWaitedTime(),它们返回线程在这两种状态下花费的总毫秒数。没有getCpuTime()方法(如果你问我,这是这个对象非常愚蠢的缺点),但是如果你知道线程是什么时候启动的,你可以这样做:

//Initialized somewhere else:
ThreadMXBean bean = ...
long threadStartTime = System.currentTimeMillis();
Thread myThread = ...

//Inside your metrics-gathering code:
long now = System.currentTimeMillis();
ThreadInfo info = bean.getThreadInfo(myThread.getId());
long totalCpuTime = now - (info.getBlockedTime()+info.getWaitedTime()+threadStartTime);

现在可以计算线程利用率的百分比。

我们快到了,但还没有完全完成。每次我们浏览我上面发布的代码的最后三行时,我们只收集线程的执行/阻塞/等待状态的总时间。为了计算百分比,我们需要跟踪何时收集这些指标,这样我们就可以知道自上次指标更新以来,线程在每个状态下花费了多少时间。所以,做这样的事情:

class ThreadUsageMetrics{
    long timestamp, totalBlockedTime, totalWaitTime;

    ThreadUsageMetrics(long ts, long blocked, long wait){
        timestamp = ts;
        totalBlockedTime = blocked;
        totalWaitTime = wait;
    }

    double computeCpuUsageSince(ThreadUsageMetrics prev){
        long time = timestamp - prev.timestamp;
        long blocked = totalBlockedTime - prev.totalBlockedTime;
        long waited = totalWaitTime - prev.totalWaitTime;
        return (time-(blocked+waited))/(double)time;
    }
}

这将为我们提供一个从0.0到1.0范围内的双倍值,表示自上次指标更新以来CPU使用率占总时间的百分比。我假设你可以将这个值转换成一个百分比,并每隔5秒左右将其提供给Dropwizard的仪表实例。在我的项目中,这是我们多年来估算CPU使用量的方法,对我们来说效果很好。

关于这一点有几个注意事项——我们实际上不需要在此对象中显式存储总CPU时间,因为任何没有阻塞或等待的时间要么是执行时间,要么是上下文切换期间花费的时间。我们无法知道上下文切换时间,但可以肯定的是,在所有情况下,总上下文切换时间可以忽略不计。

这里有一个警告——我们并没有真正衡量CPU的使用情况。

如果你仔细阅读,你会注意到我说过我们正在“估计”CPU使用率。我这样说的原因是,我们正在测量特定Java线程的总执行时间。Java没有提供实际CPU硬件使用的概念——它只是一个线程执行的总时间。这被诸如超线程之类的事情弄得更加混乱,其中“执行”所花费的时间实际上可能意味着等待另一个线程离开ALU或内存总线所花费的时间。我认为这提供了一个很好的衡量代码何时在物理硬件线程上运行的方法,但如果您想衡量实际的CPU使用情况,那么在纯Java中是无法做到的。

 类似资料:
  • 我正在尝试使用神经节监视我的dropwizard Web服务。我在本地机器上运行了gmond和gmetad。我能够在神经节网络上看到基本指标(eg.cpu、内存使用情况)。 根据这个,我还在我的服务中添加了神经节记者。但是我的神经节网上什么也没有显示。

  • 我已经为dropwizard (codehale)度量注册表配置了一个基本的sl4j reporter。这是报告器配置: 我正在接收的日志不是我所期望的(期望使用metricRegistry注册的计时器、计数器的可解析输出)。这是我每30秒实际看到的内容(与报告器配置相匹配): …… java: 55)org.slf4j.helpers.FormattingTuple@39fda09e 无论如何,

  • 使用指南 - 数据报告 百度统计为您提供网站的流量、来源、页面、访客、转化、SEO等多种网站分析报告,支持多维度细分和自定义查看,帮助您进行SEM、SEO优化,提高转化率。 概述 百度统计提供哪些数据报告 如何全方位地解读数据 如何添加常用报告 为什么有些报告没有权限 数据的下载与发送 报告的时效性及历史数据的存储 安装统计代码前的网站数据能查看吗主页&网站概况 主页介绍 帐户下网站简介 网站概况

  • 我已经在分析模式下成功启动了我的应用程序,但我不确定如何从Jprofiler生成报告或指标。 我可以看到Live内存(所有对象、记录的对象编号。of.实例计数等)、堆遍历器等,但我不确定JProfiler对我的应用程序的结论或建议。 有人能帮忙吗?

  • 使用指南 - 数据报告 - JSApi 百度统计为您提供网站的流量、来源、页面、访客、转化、SEO等多种网站分析报告,支持多维度细分和自定义查看,帮助您进行SEM、SEO优化,提高转化率。 JSApi 单页应用跟踪 JS-API_如何部署JS-API代码 trackPageview说明 trackEvent说明 _setCustomVar说明

  • 我有一个JVM,它报告提交的堆内存约为8GB(其他部分应该在此之上)。但我的操作系统显示内存使用量约为5GB。我理解由于非堆、metaspace等原因,内存使用量可能会超过提交的内存,但是怎么可能使用量比JVM报告的要少呢? 本机内存跟踪器(NMT)的输出显示保留内存为~11 GB OS-Debian 9 爪哇-