写点什么

HowTo:Pipy 如何统计关键指标

作者:Flomesh
  • 2022 年 9 月 27 日
    北京
  • 本文字数:3125 字

    阅读完需:约 10 分钟

HowTo:Pipy 如何统计关键指标

随着分布式系统的发展,可观测性在系统中扮演着重要的角色,通过可观测性可以展示系统的内部状态。作为可观测性三个方向之一的 metrics,实现了对系统信息的统计聚合。

Pipy 在 2 月发布的版本 0.20.0-3 加入用于监控的指标和统计 API,内置 Prometheus Exposition 格式 支持。以此提供了 metrics 能力,并可以通过编程的方式进行观测内容的扩展。

Metrics 的访问接口是通过 Pipy 的管理端口暴露出来的,即默认的 :6060/metrics,可以通过 --admin-port 参数在启动时指定其他端口。

pipy2022-02-17 14:56:59.750 [INF] [admin] Starting admin service...2022-02-17 14:56:59.751 [INF] [listener] Listening on port 6060 at ::
复制代码

Pipy 默认只输出了自身相关的如下指标,内容与其接收到 SIGTSTP 信号时输出的内容一致。

curl localhost:6060/metrics
pipy_out_cnt 0pipy_inb_cnt 2pipy_inb_cnt{listen="Admin Service"} 2pipy_inb_cnt{listen="Admin Service",peer="::1"} 2pipy_ppl_cnt 2pipy_ppl_cnt{module="",name="Admin Service"} 2pipy_chk_size 20480pipy_chk_size{type="inflate"} 0pipy_chk_size{type="TLS"} 0pipy_chk_size{type="Unknown"} 0pipy_chk_size{type="HTTP2 Codec"} 0pipy_chk_size{type="HTTP Encoder"} 0pipy_chk_size{type="Inbound"} 20480pipy_chk_size{type="Command Line Options"} 0pipy_chk_size{type="MQTT Encoder"} 0pipy_chk_size{type="Message"} 0pipy_chk_size{type="connectSOCKS"} 0pipy_chk_size{type="Script"} 0pipy_obj_cnt 61pipy_obj_cnt{type="pipy::stats::Gauge"} 28pipy_obj_cnt{type="pipy::http::ResponseHead"} 7pipy_obj_cnt{type="pipy::http::RequestHead"} 2pipy_obj_cnt{type="pipy::MessageEnd"} 1pipy_obj_cnt{type="pipy::Message"} 6pipy_obj_cnt{type="pipy::Inbound"} 3pipy_obj_cnt{type="pipy::Data"} 5pipy_obj_cnt{type="Object"} 9
复制代码

有些软件产品动辄输出几百上千条 metrics 不同,而用户真正关心仅仅是其中的部分,并且不同场景下需要关注的也各不相同。Pipy 以可编程的能力为核心,将选择权交给用户,由用户通过简单灵活的编程方式输出所需的内容。

接下来我们就看下如何定制指标的输入,在开始之前我们先了解下指标的种类。

Metrics 类型

既然是支持 Prometheus Exposition 格式,同样也支持 Prometheus 的 metrics 类型。目前 Pipy metrics API 支持 CounterGauge 和 Histogram,未来也会支持 Summary

  • Counter:单调增加的计数器,只有在重启的时候才能重置为 0,例如请求数。

  • Gauge:瞬态,表示一个可上可下的数值,例如上面的 pipy_inb_cnt 表示当前的入站连接数,会跟根据连接的数量上下变化。

  • Histogram:统计学中的直方图,表示的是数据分布的情况,例如请求延迟的分布:5ms、10ms、50ms、100ms,延迟落在各个区间的请求的数量。

Metrics 定义

Metrics 的定义包含两部分:名字和标签(Label)。

Metrics 标签用来区分测量数据的特征。比如请求数,我们可以区分不同 method 和 status 的请求数:

http_requests_count{method="GET",status="200"} 
复制代码

注意: 名字以 pipy_ 为前缀的指标名为 Pipy 内部使用,在定义 metics 的时候要注意一下。

使用

可以参考 Pipy 内置的 API 的参考文档,运行 pipy 命令后,浏览器中打开stats API 查看。

我们在 tutorial/03-proxy 的基础上进行扩展,为代理增加 metrics 的统计,比如请求数、请求的延迟分布。

记录请求数

这个很容易想到使用 Counter 来完成,每个请求都进行加 1 的操作。同时我们实现前面提到的标签,区分请求的 method 以及响应码。

要记录请求数,要定义一个 Counter 的全局变量。同时我们统计时需要请求头中的 method 和响应头中的 status,需要在请求进来时保存请求头的内容。

pipy({  _requestCounter: new stats.Counter('http_requests', ['method', 'status']),  _reqHead: null,})
.listen(8000) .demuxHTTP('forward')
.pipeline('forward') .handleMessageStart( msg => _reqHead = msg.head ) .muxHTTP('connection', '') .handleMessageStart( msg => ( _requestCounter.withLabels(_reqHead.method, msg.head.status).increase() ) )
.pipeline('connection') .connect('localhost:8080')
复制代码

stats.Counter 在构造的时候接受两个参数:指标名字和标签的数组。

在记录数据的时候,首先使用 withLabels() 按照构造时定义的顺序传入标签值;然后调用 increase() 方法来将数值加 1,这个方法也接受参数作为增加的值,默认是 1。

Counter 的更多方法,可参考 API 文档。

统计请求延迟分布

统计请求的延迟分布,就要用 Histogram 直方图了。首先来看下其构造方法,其可以接受 3 个参数。其中第一和第三个参数与 Counter 相同,分别是指标名和标签。

它的第二个参数接受一个数组,作为数据分布的桶(bucket)。

在创建 Histogram 类型的全局变量时,我们使用 Math.pow(2, index) 快速填充一个数组来定义桶,同时还要加入全局变量 _reqTime 来记录请求时间。

pipy({  _requestCounter: new stats.Counter('http_requests_count', ['method', 'status']),  _requestLatency: new stats.Histogram('http_request_latency', new Array(16).fill(0).map((_, i) => Math.pow(2, i))),  _reqHead: null,  _reqTime: 0,})
.listen(8000) .demuxHTTP('forward')
.pipeline('forward') .handleMessageStart( msg => ( _reqHead = msg.head, _reqTime = Date.now() ) ) .muxHTTP('connection', '') .handleMessageStart( msg => ( _requestCounter.withLabels(_reqHead.method, msg.head.status).increase(), _requestLatency.observe(Date.now() - _reqTime) ) )
.pipeline('connection') .connect('localhost:8080')
复制代码

从代码上可以看到,我们调用了 Histogram 的 observe() 方法,传入请求的延迟时间。

这次并没有提供了 Gauge 的示例,在这个场景下没有适合 Gauge 的指标,其使用比较简单,可以参考 API 文档。

测试

现在我们发送请求测试一下:


curl localhost:8000/hiHi, there!
curl localhost:6060/metricshttp_request_latency{le="1"} 1http_request_latency{le="2"} 1http_request_latency{le="4"} 1http_request_latency{le="8"} 1http_request_latency{le="16"} 1http_request_latency{le="32"} 1http_request_latency{le="64"} 1http_request_latency{le="128"} 1http_request_latency{le="256"} 1http_request_latency{le="512"} 1http_request_latency{le="1024"} 1http_request_latency{le="2048"} 1http_request_latency{le="4096"} 1http_request_latency{le="8192"} 1http_request_latency{le="16384"} 1http_request_latency{le="32768"} 1http_requests_count{method="GET",status="200"} 1
复制代码

/metrics 的结果中,我们只展示了示例定义的指标。

总结

stats API 进一步丰富了 Pipy 的可观测能力,并以可编程的方式提供了指标定义的灵活性,避免输出无用指标。支持 Prometheus Exposition 格式,方便使用 Prometheus 指标的采集。通过 metrics 的支持,Pipy 也可以为某些不支持 Prometheus 的系统提供兼容性支持,或者在服务治理之Idling场景下,可以通过监控 Pipy 的指标控制业务服务的启动和退出。

Pipy 当前实现了四种类型中的三种,未来会进一步提供 Summary 格式的实现。

还有就是当前 /metrics 端点,需要 Pipy 开启管理端口,而在某些场景下是无法开启管理端口的,后面也会进行优化。

发布于: 56 分钟前阅读数: 4
用户头像

Flomesh

关注

微信订阅号:flomesh 2022.04.07 加入

一站式云原生应用流量管理供应商 官网:https://flomesh.io

评论

发布
暂无评论
HowTo:Pipy 如何统计关键指标_Service Mesh 服务网格_Flomesh_InfoQ写作社区