【深度挖掘Java性能调优】「底层技术原理体系」深入探索Java服务器性能监控Metrics框架的实现原理分析(Gauge和Histogram篇)

简介: 【深度挖掘Java性能调优】「底层技术原理体系」深入探索Java服务器性能监控Metrics框架的实现原理分析(Gauge和Histogram篇)

承接上文

承接上文中的【深度挖掘Java性能调优】「底层技术原理体系」深入探索Java服务器性能监控Metrics框架的实现原理分析(Counter篇),我们知道和了解了对应的Counter计数器的作用和实现原理,接下来我们需要进行分析和了解计量器(Gauge)和直方图(Histogram)

计量器(Gauge)

计量器(Gauge)是度量和收集指标数据的重要工具之一,是一种用于表示任意可变值的指标。它可以是数字、字符串或其他类型的数据。通过调用已注册的回调方法或读取已注册的变量,计量器能够获取当前值。计量器适用于需要动态监测具体数值或状态的指标,例如,内存使用情况、CPU使用情况等。

使用计量器可以帮助开发人员监测和优化应用程序的性能和资源消耗。通过监测指标的变化,可以及时做出调整和改进,提高应用程序的效率和稳定性。

与Counter一样,计量器也是一个数字类型的指标,但和计数器不同的是,它主要用于收集指标的瞬时值,因此它是可变的。它的常用用法如下所示:

  • 使用Gauge进行记录以统计API的响应时间,因为响应时间是可变的,可能会有高低波动。
  • 统计CPU的负载,可以了解系统的负荷情况。
  • 统计CPU的核心线程数和运行线程数,以了解系统中正在运行的线程数量。
  • 统计操作系统的文件句柄数,以监控文件资源的使用情况。

与Counter的对比分析

相对于Counter来说,因为Gauge记录的只是一个瞬时值,因此也不用考虑多线程下的竞争与冲突问题。下面是一个简单的案例代码:

java

复制代码

private final static class SimpleGauge {
        private volatile double value;
        private SimpleGauge(double value) {
            this.value = value;
        }
        public Double getValue() {
            return this.value;
        }
        public void setValue(double value) {
            this.value = value;
        }
}

直方图(Histogram)

当我们不仅仅关注计数(Counter),或者是瞬时变量(Gauge),而是需要知道最大值,最小值,中位数,平均值以及第99%的值时,我们就需要用到直方图(Histogram)这个统计类型了。

主要作用

Histogram主要的用途是表示分布情况,直方图用于测量和统计数据分布的情况。它会记录值的分布和频率,并提供一些统计计算,如最大值、最小值、平均值、标准差等。直方图适合用于衡量数据集的中心趋势和离散程度,比如响应时间的分布。

数据统计难点分析

为了准确统计一个API的99%响应时间,我们不能简单地记录所有响应时间并进行排序。由于API在不断被调用,新的响应时间会不断产生,因此这个方法无法得到准确的99%响应时间。

源码原理分析

为了解决这个问题,可以使用Reservoir类来收集响应时间等数据。Reservoir实质上是一个数据池,用于保存数据,在进行统计时,可以获取快照 (Snapshot) 来获取统计数据。

Reservoir类

Reservoir类是在codehale库中被使用的,这个类基于蓄水池抽样算法,它可以在固定的容量下持续保留最近的数据样本。每当有新的响应时间数据到来时,Reservoir会根据一定的概率选择保留该数据样本,以保持总体的分布情况。在需要进行统计时,可以基于Reservoir的快照来获取相应的统计数据,例如获取平均响应时间、99%响应时间等。

使用Reservoir类能够实现高效地统计数据,而不需要记录和排序所有数据,同时能够保持近似的分布情况,为后续的数据分析提供准确可靠的结果。

了解了基本原理之后,我们来看一下histogram的源码。

java

复制代码

public class Histogram implements Metric, Sampling, Counting {
    private final Reservoir reservoir;
    private final LongAdder count;
    public Histogram(Reservoir reservoir) {
        this.reservoir = reservoir;
        this.count = new LongAdder();
    }
    //向histogram中增加新的数据,实际上就是向数据池中添加数据
    public void update(int value) {
        update((long) value);
    }
    public void update(long value) {
        count.increment();
        reservoir.update(value);
    }
    @Override
    public long getCount() {
        return count.sum();
    }
    //获取Snapshot,实际上也是通过数据池来获取
    @Override
    public Snapshot getSnapshot() {
        return reservoir.getSnapshot();
    }
}

再来看看Snapshot的代码。

java

复制代码

public class Snapshot {
    //最核心的方法,用于获取第n%的值
    public double getValue(double quantile);
    private final long[] values;
    public double getMedian() {
        return getValue(0.5);
    }
    public double get75thPercentile() {
        return getValue(0.75);
    }
    /*
        省略部分getNthPercentile函数
    */
    public long getMax();
    public double getMean();
    public long getMin();
    /*
    ...
    */ 
}

从Snapshot中,我们就基本能够得到我们想要的统计数据了。

来简单地了解一下数据池。定义了数据池以后,我们就需要考虑更多的问题了,比如说,如何保证可以高性能地将数据写入数据池中,以及如何保证数据池中数据量不会过大而占用过多的内存,以及如何快速地取出快照。在Codahale metrics里面,主要定义了三种数据池。

UniformReservoir 默认保存1028条记录,每次进行update操作的时候,首先会依次地将值填入1028条记录中,当记录满了之后,就会使用随机替换0 - 1027中的一条。因为是随机替换,所以也不需要进行加锁和解锁。

markdown

复制代码

- SlidingWindowReservoir **固定大小的数据池**,从0到n-1填入数据,不断循环。也不会进行加锁和解锁。
- SlidingTimeWindowReservoir **非固定大小的数据池**,但是只会存储过去N秒的数据。使用ConcurrentSkipListMap进行存储。
- ExponentiallyDecayingReservoir **固定大小的数据池**。首先会逐个数据填满数据池,随后会将老的数据替换为新的数据,使用ConcurrentSkipListMap进行存储。可以说是SlidingWindowReservoir与SlidingTimeWindowReservoir的结合。

当然还有其他的有效的方法是使用基于概率算法的数据结构,例如,特定数据结构,如TDigest算法,来实时估计99%的响应时间。这些方法基于近似统计的原理,通过维护一个固定容量的滑动窗口或一个特定的数据结构来跟踪最近一段时间的响应时间分布。


总结概括

以上介绍的计数器、量规和直方图是监控数据中常用且基础的数据类型。它们提供了一些基本的功能和计算,让我们能够更好地理解和监控应用程序的关键指标和数据。

在使用 Java 监控库时,我们可以依据具体需求使用这些数据类型,并利用其提供的方法和功能来收集、记录和分析监控数据。这些数据类型的使用有助于帮助我们了解应用程序的状态、性能和行为,进而进行优化和改进。

服务器性能监控的要点和讨论

  1. 我们需要收集的是瞬时值、计数还是统计分布值?
  2. 在进行数据记录时,如何保证高性能的写入/更新?(尽可能减少锁的使用)同时如何确保数据的更新是合理的?
  3. 如何将指标数据汇总到一个地方以便于后续处理?
相关文章
|
3月前
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
2月前
|
存储 安全 Java
Java 集合框架中的老炮与新秀:HashTable 和 HashMap 谁更胜一筹?
嗨,大家好,我是技术伙伴小米。今天通过讲故事的方式,详细介绍 Java 中 HashMap 和 HashTable 的区别。从版本、线程安全、null 值支持、性能及迭代器行为等方面对比,帮助你轻松应对面试中的经典问题。HashMap 更高效灵活,适合单线程或需手动处理线程安全的场景;HashTable 较古老,线程安全但性能不佳。现代项目推荐使用 ConcurrentHashMap。关注我的公众号“软件求生”,获取更多技术干货!
48 3
|
23天前
|
并行计算 算法 Java
Java中的Fork/Join框架详解
Fork/Join框架是Java并行计算的强大工具,尤其适用于需要将任务分解为子任务的场景。通过正确使用Fork/Join框架,可以显著提升应用程序的性能和响应速度。在实际应用中,应结合具体需求选择合适的任务拆分策略,以最大化并行计算的效率。
46 23
|
1月前
|
运维 监控 算法
企业局域网监控软件中 Java 优先队列算法的核心优势
企业局域网监控软件是数字化时代企业网络安全与高效运营的基石,犹如一位洞察秋毫的卫士。通过Java实现的优先队列算法,它能依据事件优先级排序,确保关键网络事件如异常流量、数据泄露等被优先处理,保障系统稳定与安全。代码示例展示了如何定义网络事件类并使用PriorityQueue处理高优先级事件,尤其在面对疑似风险时迅速启动应急措施。这一核心技术助力企业在复杂网络环境中稳健前行,护航业务腾飞。
64 32
|
30天前
|
存储 监控 算法
探秘局域网桌面监控:深入剖析 Java 语言核心算法
在数字化办公时代,局域网桌面监控如同企业的“智慧鹰眼”,确保工作效率与数据安全。本文以Java为载体,揭示哈希表在监控中的关键应用。通过高效的数据结构和算法,哈希表能快速索引设备连接信息,大幅提升监控的时效性和响应速度。代码示例展示了如何用Java实现设备网络连接监控,结合未来技术如AI、大数据,展望更智能的监控体系,助力企业在数字化浪潮中稳健前行。
|
3月前
|
存储 缓存 安全
Java 集合框架优化:从基础到高级应用
《Java集合框架优化:从基础到高级应用》深入解析Java集合框架的核心原理与优化技巧,涵盖列表、集合、映射等常用数据结构,结合实际案例,指导开发者高效使用和优化Java集合。
67 4
|
28天前
|
弹性计算 数据挖掘 应用服务中间件
阿里云轻量应用服务器68元与云服务器99元和199元区别及选择参考
目前阿里云有三款特惠云服务器,第一款轻量云服务器2核2G68元一年,第二款经济型云服务器2核2G3M带宽99元1年,第三款通用算力型2核4G5M带宽199元一年。有的新手用户并不是很清楚他们之间的区别,因此不知道如何选择。本文来介绍一下它们之间的区别以及选择参考。
410 87
|
21天前
|
存储 弹性计算 应用服务中间件
阿里云轻量应用服务器出新品通用型实例了,全球26个地域可选
近日,阿里云再度发力,推出了首款全新升级的轻量应用服务器——通用型实例。这款服务器实例不仅标配了200Mbps峰值公网带宽,更在计算、存储、网络等基础资源上进行了全面优化,旨在为中小企业和开发者提供更加轻量、易用、普惠的云计算服务,满足其对于通用计算小算力的迫切需求。目前,这款新品已在全球26个地域正式上线,为全球用户提供了更加便捷、高效的上云选择。
136 27
|
12天前
|
机器学习/深度学习 人工智能 弹性计算
阿里云AI服务器价格表_GPU服务器租赁费用_AI人工智能高性能计算推理
阿里云AI服务器提供多种配置,包括CPU+GPU、FPGA等,适用于人工智能、机器学习和深度学习等计算密集型任务。本文整理了阿里云GPU服务器的优惠价格,涵盖NVIDIA A10、V100、T4等型号,提供1个月、1年和1小时的收费明细。具体规格如A10卡GN7i、V100-16G卡GN6v等,适用于不同业务场景,详情见官方页面。
81 11
|
13天前
|
存储 弹性计算 数据挖掘
阿里云服务器ECS通用算力型u1和ECS经济型e实例性能特点、使用及常见问题解答FAQ
阿里云ECS云服务器的经济型e实例和通用算力型u1实例深受开发者和中小企业青睐。e实例适合中小型网站、开发测试等轻量级应用,采用共享CPU调度模式,性价比高;u1实例则适用于中小型企业级应用,提供更高的性能保障和稳定性,支持固定CPU调度模式,计算性能更稳定。同等配置下,u1实例在网络带宽、IOPS等方面表现更优,价格也相对较高。个人用户可选择e实例,中小企业建议选择u1实例以确保业务稳定性。