Dubbo metrics学习总结

Dubbo metrics学习总结

1 简介

metrics为微服务的监控提供数据基础;是一个标准度量库,对监控对象的数据采集进行了统一封装。

2 特性与功能

在这里插入图片描述在这里插入图片描述

3 实现原理

在这里插入图片描述

4 Metric注册与定义

在这里插入图片描述在这里插入图片描述
监控数据采集逻辑的实现取决于具体的指标类型

4.1 支持的指标类型

4.1.1 操作系统

支持Linux/Windows/Mac,包含cpu, load, disk, nettraffic, tcp。
对应的实现模块:metrics-os

4.1.2 Jvm

支持classload, gc次数和时间, 文件句柄,young/old区占用,线程状态, 堆外内存,编译时间,部分指标支持自动差值计算
实现模块:metrics-jvm

4.1.3 中间件

4.1.3.1 Tomcat

请求数,失败次数,处理时间,发送接收字节数,线程池活跃线程数等。
实现模块:metrics-tomcat

4.1.3.2 Druid

sql执行次数,错误数,执行时间,影响行数等;
实现模块:metrics-druid.

4.1.3.3 Nginx

接受,活跃连接数,读,写请求数,排队数,请求qps,平均rt等;
实现模块:metrics-nginx.

4.1.4 应用层

需要使用相关api去应用层埋点实现;如qps等。

4.2 度量器

用于指标的统计,监控数据的结构和特征会有所不同,所以根据不同的需求会对应一种度量器
在这里插入图片描述在这里插入图片描述

4.2.1 Counter

在这里插入图片描述
counter统计基于时间滑动窗口算法实现。
Bucket类提供分桶计数功能,统计一定时间间隔内的计数
BucketDeque类可以理解为一个时间窗口,用于保存最近N个时间间隔内的计数
统计值的修改逻辑,如下:

/**
 * update the counter to the given bucket
 */
public void update(long n) {
    if (updateTotalCount) {
        totalCount.inc(n);
    }
    // align current timestamp
    long curTs = TimeUnit.MILLISECONDS.toSeconds(clock.getTime()) / interval * interval;
    Bucket oldBucket = latestBucket.get();
    if (curTs > latestBucket.get().timestamp) {
        // create a new bucket and evict the oldest one
        Bucket newBucket = new Bucket();
        newBucket.timestamp = curTs;
        if (latestBucket.compareAndSet(oldBucket, newBucket)) {
            // this is a single thread operation
            buckets.addLast(newBucket);
            oldBucket = newBucket;
        } else {
            oldBucket = latestBucket.get();
        }
    }
    // reduce the call to latestBucket.get() to avoid cache line invalidation
    // because internally latestBucket is a volatile object
    oldBucket.count.add(n);
}

获取整个时间窗口的统计值实现,如下:

/**
 * Return the bucket count, keyed by timestamp
 * @return the bucket count, keyed by timestamp
 */
public Map<Long, Long> getBucketCounts(long startTime) {
    Map<Long, Long> counts = new LinkedHashMap<Long, Long>();
    long curTs = calculateCurrentTimestamp(clock.getTime());
    for (Bucket bucket: buckets.getBucketList()) {
        if (1000L * bucket.timestamp >= startTime && bucket.timestamp <= curTs) {
            counts.put(1000L * bucket.timestamp, bucket.count.sum());
        }
    }
    return counts;
}

备注:至于其它度量器的底层实现大多是基于BucketCounter。可以理解为也是通过时间滑动窗口算法实现的。

4.2.2 Meter(吞吐率度量器)

在这里插入图片描述EWMA类是对指数加权移动平均值算法的实现,指数移动加权平均较传统的平均法来说,一是不需要保存过去所有的数值;二是计算量显著减小。

EWMA 的表达式如下:
    vt=βθt +(1−β)vt−1
  上式中 θt
为时刻 t 的实际温度;系数 β 表示加权下降的速率,其值越小下降的越快;vt 为 t
时刻 EWMA 的值。
  在上图中有两条不同颜色的线,分别对应着不同的 β
值。
β值为0<β<1区间;
当β=0.9,是最接近实际数据的;
β的取值可以指定一个常量,也可以受其它因素的影响来取值,比如时间范围,β=aT,T为1分钟、5分钟等。

4.3 metric命名规则

metric的名字抽象为MetricName,它由两部分组成,key和tag。

4.3.1 Key

key是一个由.分隔的字符串, 它描述了这个metric的基本含义.

4.3.2 Tag

引入tag是为了实现多维度统计数据。tag由两部分组成, tagKey和tagValue, 形式为{tagKey=tagValue}

  • key和tag只支持:[a-z][A-Z][0-9][-_./], 不能有空格, 大小写敏感, key原则上不包含大写。
  • 格式为app_name.category[.sub_category]*,category和sub_category里面如果有多个单词,用下划线’_‘连接, 不要用’.'连接
  • 需要动态聚合的维度, 放在tag里面, 同时在tagKey也在key中体现。 不需要聚合的维度, 放在key里面。
  • 不要使用太多的tag, 一般而言4-5个已经足够

4.3.3 规则解析

MetricName对象的创建方式有:new MetricName()、MetricName.build()、MetricName.join()
key的解析原理,如下:
在这里插入图片描述

Tag的解析原理,如下:

在这里插入图片描述

举例说明:
Key为dubbo.service.qps;
Tag 为 service=demoService,host=demo

实现方式有多种:

  • 方式一
MetricName name = new
MetricName("dubbo.service.qps").tagged("service", "demoService");
name = name.tagged("host", "demo");
  • 方式二
  MetricName name = MetricName.build("dubbo")
                        .resolve("service.qps")
    .tagged("service", "demoService","host", "demo");

还有其它的方式

5 单机metric数据落盘

数据如果完全存在内存里面,可能会出现因为拉取失败,或者应用本身抖动,导致数据丢失的可能。
为了解决该问题,metrics引入了数据落盘的模块,提供了日志方式和二进制方式两种方式的落盘。
日志方式默认通过JSON方式进行输出,可以通过日志组件进行拉取和聚合,文件的可读性也比较强,但是无法查询历史数据。
二进制方式则提供了一种更加紧凑的存储,同时支持了对历史数据进行查询。

6 metric数据暴露

外部可以通过什么方式查询相关数据,如指标信息、指标实时统计数据等
指标信息:默认的指标、动态新增的指标
代码实现模块:metrics-rest

6.1 HTTP Server实现原理

基于Jersey+ sun Http server的简单实现

6.2 http查询接口

目前查询的是本地内存的数据
详细的接口说明见:https://github.com/dubbo/metrics/wiki/query-from-http

7 metric数据上报

供外部收集数据
代码实现模块:metrics-reporter

7.1 上报类型

7.1.1 SLF4J上报:Slf4jReporter

7.1.1.1 实现原理

在这里插入图片描述

7.1.2 OpenTsdb上报:OpenTsdbReporter

7.1.2.1 实现原理

在这里插入图片描述

7.1.3 jmx上报:JmxReporter

7.1.3.1 实现原理

备注:待完善

7.1.4 控制台上报:ConsoleReporter

7.1.4.1 实现原理

备注:待完善

7.1.5 Csv文件上报:CsvReporter

7.1.5.1 实现原理

备注:待完善

8使用方式

8.1 埋点

定义或注册metric

  • 定义metric

指定指标类型、统计维度、级别、度量器。如下:

Counter hello = MetricManager.getCounter("test", MetricName.build("test.my.counter"));
hello.inc();
  • 注册metric

例如:tomcat、druid、nginx等

MetricsIntegrateUtils.registerAllMetrics();

8.2 metric数据上报

首先根据需要选择你要上报的类型,例如用ConsoleReporter上报到控制台,则:

private final ConsoleReporter reporter = ConsoleReporter.forRegistry(registry)
        .outputTo(output)
        .formattedFor(Locale.US)
        .withClock(clock)
        .formattedFor(TimeZone.getTimeZone("PST"))
        .convertRatesTo(TimeUnit.SECONDS)
        .convertDurationsTo(TimeUnit.MILLISECONDS)
        .filter(MetricFilter.ALL)
        .build();
reporter.report(this.<Gauge>map(),
        map("test.counter", counter),
        this.<Histogram>map(),
        this.<Meter>map(),
        this.<Timer>map());

8.3 Rest http server 启动

metricsHttpServer = new MetricsHttpServer();
metricsHttpServer.start();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值