找回密码
 立即注册
查看: 259|回复: 0

Envoy & Istio 性能指标与原理初探

[复制链接]
发表于 2022-9-23 12:38 | 显示全部楼层 |阅读模式

(Tower Bridge)伦敦的塔桥的开口跨度

  • Istio 与 Envoy 指标概述
  • Envoy 指标

    • Envoy 指标概述

      • Tag
      • 指标数据类型

    • 指标释义

      • cluster manager
      • http connection manager(HCM)
      • listeners
      • server
      • watch dog
      • Event loop

    • 配置说明

      • config.bootstrap.v3.Bootstrap
      • config.metrics.v3.StatsConfig
      • config.metrics.v3.StatsMatcher


  • Istio 指标

    • Istio 自己的 Metrics

      • 标准指标说明

        • Metrics
        • Prometheus 的 Labels

      • 使用

        • istio-proxy 与应用的 Metrics 整合输出
        • 定制:为 Metrics 增加维度
        • 定制:加入 request / response 元信息维度

      • 工作原理

        • istio stat filter 使用
        • istio stat Plugin 实现


    • Envoy 内置的 Metrics

      • 定制 Envoy 内置的 Metrics
      • 原理

    • 总结:Istio-Proxy 指标地图


  关于封面: 相信很多人听过《London Bridge Is Falling Down》这个儿歌,有人也知道这个是英国传统的儿童游戏歌曲。但很多人和我一样,以为 "London Bridge" 就是封面中的塔桥。直到今天,我才知道,"London Bridge" 并不是 "Tower Bridge"。所以,封面不是 "London Bridge"。无论喜欢与否,一个时代的符号走到了终点,愿安宁。

  摘录说明: 本文摘自一本我在写作中的开源书《Istio & Envoy 内幕》 中 Istio 与 Envoy 指标 一节。如果说你看到的转载图片不清,可回到原书。

Istio 与 Envoy 指标概述

指标监控,可能是 DevOps 监控最重要的一环。但同时也可能是最难的一环。你可以从网上找到各种系统和中间件的 Grafana 监控仪表盘,它们大都设计得很漂亮得体,让人感觉监控已经完美无缺。  
但是,不知道你是否与我有同样的经历:在系统遇到问题时,手头有一大堆指标和监控仪表盘。

  • 却不知道哪个指标才是问题相关的。
  • 或者是,问题已经有个方向定位,却发现这个方向上,根本没有记录指标。
事情终究是要人来解决,再多的数据,如果:

  • 不去理解这些数据背后的意义
  • 不去主动分析自己的应用场景和部署环境需要什么数据,只是系统默认给什么就用什么
那么指标越多,越让人迷失在茫茫指标的海洋中。
作为一个混后端江湖多年的老程(老程序员),总有很多东西不懂,却难以启齿的。其中一个就是一些具体指标的意义。举个两个例子:

  • 我之前定位一个 Linux 下的网络问题,用了一个叫 nstat 的工具,它输出了非常多的指标,但很多会发现,有些指标是死活找不到说明文档的。这也是开源软件一直以来的问题,变化快,文档跟不上,甚至错误或过时未更新。
  • 我之前定位一个 Linux 下的 TCP 连接问题,用了一个叫 ss 的工具,它输出的神指标,也是搜索引擎也无能为力去解释。最后不得不看原码。还好,我把调查结果记录到 Blog 中:《可能是最完整的 TCP 连接健康指标工具 ss 的说明》,希望对后来人有一些参考作用吧。
故事说完了,回到本书的主角 Istio 与 Envoy 上。它们的指标说明文档比上面的老爷车开源软件好一些。起码基本每个指标都有一行文字说明,虽然文字一样非常短且模糊。
Istio 的 istio-proxy 的数据面指标是 基于 Envoy 的指标构架实现的。所以,后面我将先说 Envoy 的指标架构。
如果你和我一样,是个急性子。那么下图就是 Istio & Envoy 的指标地图了。它说明了指标产生在什么地方。后面内容会一步步推导出这个地图。


图:Envoy@Istio的指标。用 Draw.io 打开

Envoy 指标

Envoy 指标概述

Envoy 的主要目标之一是使网络易于理解。 Envoy 会根据其配置方式产生大量统计信息。一般来说,统计数据(指标)分为三类:

  • Downstream:Downstream 指标与外来的连接/请求有关。它们由 listener、HTTP connection manager(HCM)、TCP proxy filter 等产生。
  • Upstream:Upstream 指标与外向的连接/请求有关。它们由 connection pool、router filter、tcp proxy filter等产生。
  • Server:Server 指标信息描述 Envoy 服务器实例的运作情况。服务器正常运行时间或分配的内存量等统计信息。
在最简单场景下,单个 Envoy Proxy 通常涉及 Downstream 和 Upstream 统计数据。这两种指标反映了取该 网络节点 的运行情况。来自整个网格的统计数据提供了每个网络节点 和整体网络健康状况的非常详细的汇总信息。Envoy 的文档对这些指标有一些简单的说明。

Tag

Envoy 的指标还有两个子概念,支持在指标中使用: 标签(tags)/维度(dimensions) 。这里的 tags 对等于 Prometheus 指标的 label。意义上,可以理解为:分类维度。
Envoy 的 指标 由规范的字符串来标识。这些字符串的动态部分(子字符串)被提取成为 标签(tag)。可以通过指定 tag 提取规则(Tag Specifier configuration.) 来定制 tag 。
举个例子:
### 1. 原始的 Envoy 指标 ###

$ kubectl exec fortio-server -c istio-proxy -- curl 'localhost:15000/stats'

# 返回:
cluster.outbound|8080||fortio-server-l2.mark.svc.cluster.local.external.upstream_rq_2xx: 300

# 其中:
# - `outbound|8080||fortio-server-l2.mark.svc.cluster.local` 部分是 upstream cluster 的名字。可以正则提取作为 tag。
# - `2xx` 部分是 HTTP Status Code 的分类。可以正则提取作为 tag。 下文将有这个提取规则的配置说明。

### 2. 给 Prometheus 的指标 ###
$ kubectl exec fortio-server -c istio-proxy -- curl 'localhost:15000/stats?format=prometheus' | grep 'outbound|8080||fortio-server-l2' | grep 'external.upstream_rq'

# 返回:
envoy_cluster_external_upstream_rq{response_code_class="2xx",cluster_name="outbound|8080||fortio-server-l2.mark.svc.cluster.local"} 300
指标数据类型

Envoy 发出三种类型的值作为统计信息:

  • 计数器(Counters):无符号整数,只会增加而不会减少。例如,总请求。
  • 仪表(Gauges):增加和减少的无符号整数。例如,当前活动的请求。
  • 直方图(Histograms):作为指标流的一部分的无符号整数,然后由收集器聚合以最终产生汇总的百分位值(percentile,即平常说的 P99/P50/Pxx)。例如,Upsteam 响应时间。
在 Envoy 的内部实现中,Counters 和 Gauges 被分批并定期刷新以提高性能。Histograms 在接收时写入。
指标释义

从指标的产出地点来划分,可以分为:

  • cluster manager : 面向 upstream  的 L3/L4/L7 层指标
  • http connection manager(HCM) : 面向 upstream & downstream 的 L7 层指标
  • listeners : 面向 downstream 的 L3/L4 层指标
  • server(全局)
  • watch dog
下面我只选择了部分关键的性能指标来简单说明。
cluster manager

Envoy 文档:cluster manager stats
上面文档已经说得比较详细了。我只补充一些在性能调优时需要关注的方面。那么,一般需要关注什么指标?
我们从著名的 Utilization Saturation and Errors (USE) 方法学来分析。
利用率(Utilization):

  • upstream_cx_total (Counter): 连接数
  • upstream_rq_active
饱和度(Saturation):

  • upstream_rq_time (Histogram): 响应时间
  • upstream_cx_connect_ms (Histogram)
  • upstream_cx_rx_bytes_buffered
  • upstream_cx_tx_bytes_buffered
  • upstream_rq_pending_total
  • upstream_rq_pending_active (Gauge)
错误(Error):

  • upstream_cx_connect_fail (Counter): 连接失败数
  • upstream_cx_connect_timeout (Counter): 连接超时数
  • upstream_cx_overflow (Counter): 集群连接断路器溢出的总次数
  • upstream_cx_pool_overflow
  • upstream_cx_destroy_local_with_active_rq
  • upstream_cx_destroy_remote_with_active_rq
  • upstream_rq_timeout
  • upstream_rq_retry
  • upstream_rq_rx_reset
  • upstream_rq_tx_reset
其它:

  • upstream_rq_total (Counter): TPS (吞吐)
  • upstream_cx_destroy_local (Counter): Envoy 主动断开的连接计数
  • upstream_cx_destroy_remote (Counter): Envoy 被动断开的连接计数
  • upstream_cx_length_ms (Histogram)

http connection manager(HCM)

Envoy 文档:http connection manager(HCM) stats
可以认为,这是面向 downstream & 部分 upstream 的 L7 层指标
利用率(Utilization):

  • downstream_cx_total
  • downstream_cx_active
  • downstream_cx_http1_active
  • downstream_rq_total
  • downstream_rq_http1_total
  • downstream_rq_active
饱和度(Saturation):

  • downstream_cx_rx_bytes_buffered
  • downstream_cx_tx_bytes_buffered
  • downstream_flow_control_paused_reading_total
  • downstream_flow_control_resumed_reading_total
错误(Error):

  • downstream_cx_destroy_local_active_rq
  • downstream_cx_destroy_remote_active_rq
  • downstream_rq_rx_reset
  • downstream_rq_tx_reset
  • downstream_rq_too_large
  • downstream_rq_max_duration_reached
  • downstream_rq_timeout
  • downstream_rq_overload_close
  • rs_too_large
其它:

  • downstream_cx_destroy_remote
  • downstream_cx_destroy_local
  • downstream_cx_length_ms
listeners

Envoy 文档:listener stats
可以认为,这是 downstream 的 L3/L4 层的指标。
利用率(Utilization):

  • downstream_cx_total
  • downstream_cx_active
饱和度(Saturation):

  • downstream_pre_cx_active
错误(Error):

  • downstream_cx_transport_socket_connect_timeout
  • downstream_cx_overflow
  • no_filter_chain_match
  • downstream_listener_filter_error
  • no_certificate
其它:

  • downstream_cx_length_ms
server

Envoy 基础信息指标
Envoy 文档:server stats
利用率(Utilization):

  • concurrency
错误(Error):

  • days_until_first_cert_expiring
watch dog

Envoy 文档: Watchdog
Envoy 还包括一个可配置的看门狗系统,它可以在 Envoy 没有响应时增加统计数据并选择性地终止服务器。 系统有两个独立的看门狗配置,一个用于主线程,一个用于工作线程; 因为不同的线程有不同的工作负载。 这些统计数据有助于从高层次上理解 Envoy 的事件循环是否因为它正在做太多工作、阻塞或没有被操作系统调度而没有响应。
饱和度(Saturation):

  • watchdog_mega_miss(Counter): mega 未命中数
  • watchdog_miss(Counter): 未命中数
如果你对 watchdog 机制的兴趣,可以参考:
https://github.com/envoyproxy/envoy/issues/11391 https://github.com/envoyproxy/envoy/issues/11388
Event loop

Envoy 文档: Event loop
Envoy 架构旨在通过在少量线程上运行事件循环来优化可扩展性和资源利用率。 “main” 线程负责控制面处理,每个 “worker” 线程分担数据面的一部分任务。 Envoy 公开了两个统计信息来监控所有这些线程事件循环的性能。
跑一轮循环的耗时:事件循环的每次迭代都会执行一些任务。任务数量会随着负载的变化而变化。但是,如果一个或多个线程具有异常长尾循环执行耗时,则可能存在性能问题。例如,负责可能在工作线程之间分配不均,或者插件中可能存在长时间阻塞操作阻碍了任务进度。
轮询延迟:在事件循环的每次迭代中,事件调度程序都会轮询 I/O 事件,并在某些 I/O 事件就绪 或 发生 超时 时 “唤醒” 线程,以先发生者为准。在 超时 的情况下,我们可以测量轮询后预期唤醒时间与实际唤醒时间的差值;这种差异称为 “轮询延迟”。看到一些小的 轮询延迟 是正常的,通常等于内核调度程序的 “时间片(time slice”)” 或 “量子(quantum)” ——这取决于运行 Envoy 的操作系统 —— 但如果这个数字大大高于其正常观察到的基线,它表示内核调度程序可能发生延迟。
可以通过将 enable_dispatcher_stats 设置为 true 来启用这些统计信息。

  • main 线程的事件调度器有一个以 server.dispatcher. 为根的统计树。
  • 每个 worker 线程的事件调度器都有一个以 listener_manager.worker_<id>.dispatcher. 为根的统计树。
每棵树都有以下统计信息:
NameTypeDescription
loop_duration_usHistogram以微秒为单位的事件循环持续时间
poll_delay_usHistogram以微秒为单位的轮询延迟
请注意,此处不包括任何辅助(非 main 与 worker)线程。
Watch Dog 和 Event loop 都是解决与监控事件处理延迟与时效的工具,这里有很多细节和故事,甚至可以说到 Linux Kernel。希望本书后面有时间,可以和大家一起学习和分析这些有趣的细节。配置说明

如果你认真看过本书的前言中的 {ref}`index:本书不是什么` ,说好的不是“使用手册”,为何又讲起配置来了?好吧,我只能说,从了解使用方法入手,再学实现,比直接一来就源码的方法更好让人类入门。

本节参考:
[Envoy 文档](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/metrics/v3/stats.proto)config.bootstrap.v3.Bootstrap

Envoy 文档:config.bootstrap.v3.Bootstrap proto
{  "node": {...},  "static_resources": {...},  "dynamic_resources": {...},  "cluster_manager": {...},  "stats_sinks": [],  "stats_config": {...},  "stats_flush_interval": {...},  "stats_flush_on_admin": ...,...}什么是 `stats sink`? 本书不作说明。Istio 默认没定制相关配置。以下只说关注的部分配置。

  • stats_config (config.metrics.v3.StatsConfig) 用于内部处理统计信息的配置。
  • stats_flush_interval (Duration) 刷新 stats sink 的时间间隔。。出于性能原因,Envoy 不会实时刷新 counter ,仅定期刷新 counter 和 gauge 。 如果未指定,则默认值为 5000 毫秒。 stats_flush_interval 或 stats_flush_on_admin 只能设置之一。 Duration 必须至少为 1 毫秒,最多为 5 分钟。
  • stats_flush_on_admin (bool) 仅当在 管理界面(admin interface) 上查询时才将统计信息刷新到 sink。 如果设置,则不会创建刷新计时器。 只能设置 stats_flush_on_admin 或 stats_flush_interval 之一。
config.metrics.v3.StatsConfig

Envoy 文档:config-metrics-v3-statsconfig
{
  "stats_tags": [],
  "use_all_default_tags": {...},
  "stats_matcher": {...},
  "histogram_bucket_settings": []
}

  • stats_tags - 维度提取规则(对应 Prometheus 的 label 提取) (多个 config.metrics.v3.TagSpecifier ) 每个 指标名称字符串 都通过这些标签规则独立处理。 当一个标签匹配时,第一个捕获组不会立即从名称中删除,所以后面的 TagSpecifiers 也可以重复匹配同一部分。在完成所有标签匹配后,再剪裁 指标名称字符串 的匹配部分,并作为 stats sink 的指标名,例如 Prometheus的指标名。
  • use_all_default_tags (BoolValue) 使用 Envoy 中指定的所有默认标签正则表达式。 这些可以与 stats_tags 中指定的自定义标签结合使用。 它们将在自定义标签之前进行处理。Istio 默认为 false.
  • stats_matcher (config.metrics.v3.StatsMatcher) 指定 Envoy 要产出哪些指标。支持 包含/排除 规则指定。 如果未提供,则所有指标都将产出。 阻止某些指标集的统计可以提高一点 Envoy 运行性能。
config.metrics.v3.StatsMatcher

Envoy 文档:config-metrics-v3-statsmatcher
用于禁用/开启统计指标计算与产出的配置。
{
  "reject_all": ...,
  "exclusion_list": {...},
  "inclusion_list": {...}
}

  • reject_all (bool) 如果 reject_all 为 true ,则禁用所有统计信息。 如果 reject_all 为 false,则启用所有统计信息。
  • exclusion_list (type.matcher.v3.ListStringMatcher) 排除列表
  • inclusion_list (type.matcher.v3.ListStringMatcher) 包含列表

本节参考了: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/observability/statistics

下一节,将以 Istio 如何使用上面的配置为例,举例说明。
Istio 指标

Istio 自己的 Metrics

标准指标说明

参考:https://istio.io/latest/docs/reference/config/metrics/
Metrics

对于 HTTP、HTTP/2 和 GRPC 流量,Istio 默认生成以下指标:
<ul><li data-pid="Qy_pJXol">Request Count (istio_requests_total): This is a COUNTER incremented for every request handled by an Istio proxy.<li data-pid="4yY7S93Z">Request Duration (istio_request_duration_milliseconds): This is a DISTRIBUTION which measures the duration of requests.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-25 01:30 , Processed in 0.090595 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表