ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Agent Substrate 遥测基准测试全解析:用 OTel 场景阶梯量化 telemetry 开销与 Collector 成本

Agent Substrate 遥测基准测试全解析:用 OTel 场景阶梯量化 telemetry 开销与 Collector 成本 人工智能AI AgentAgent 沙箱云原生容器运行时零信任【免费下载链接】substrateAgent Substrate: the core system项目地址https://gitcode.com/GitHub_Trending/substrate7/substrate点击查看免费下载本文是 Agent Substratebenchmarking/observability.md的遥测基准测试实战指南。它回答一个工程上最实际的问题substrate 的控制面与 actor 运行时到底向外发送多少遥测数据这些数据又让 OpenTelemetry Collector 付出多少 CPU、内存与副本代价。读完本文你将掌握如何用 S0–S3 四个场景阶梯scenario ladder一次性跑完空闲基线、用户数扫描、采样率扫描与长时间浸泡四种测量如何部署一个tee 式遥测计量器telemetry meter按服务统计 spans 与 datapoints以及如何用一组 PromQL 查询和通过标准判断一次运行是否有效、Collector 是否还能承受更多负载。1. 遥测基准测试测量什么遥测基准测试回答两个问题volume遥测量substrate 各组件每个服务发送多少 spans 与 metric datapointscost成本这些遥测让承载它们的 OTel Collector 付出多少 CPU、内存和副本数。做一次测量需要三份资料配合测量步骤见 benchmarking/telemetry/README.md它说明如何安装计量器、把控制面与 actor 负载指向它以及如何读取数字体积模型与 Collector 规模指引见 docs/dev/best-practices/otel-collector.md本页benchmarking/observability.md则提供场景阶梯——即跑哪些负载组合、每一步持续多久、通过标准是什么。一个值得注意的设计决定是本仓库的 observability 页面不存放任何测量结果。自动化会把每次运行的值写入 GCS。原因是结果一旦写进仓库任何一次采样率或 instrument 的修改都会让旧结果失效而读者无法分辨哪份拷贝才是正确的。结果以运行产物artifact的形式存在而不是以文档的形式固化。2. 测量前置tee 式遥测计量器telemetry meterGKE 的托管 Collector 只把自己的自指标上报到 Cloud Monitoring不提供按数据源每个 service的拆分数据。因此 benchmarking/telemetry/meter.yaml 部署了第二个 Collector专门按service.name统计 spans 与 datapoints。2.1 meter 是一个 tee不是终点meter 的关键设计是tee分路它统计遥测数据然后把数据原样转发给托管 Collector因此托管 Collector 仍然承担运行的负载它的 CPU、内存与副本数在测量期间保持真实有效。meter 不是托管 Collector 的替代品。kubectl apply -f benchmarking/telemetry/meter.yaml METERhttp://telemetry-meter.benchmarking.svc.cluster.local:4317 ./hack/install-ate.sh --deploy-ate-system --otlp-endpoint ${METER}--otlp-endpoint会 patchate-otel-configConfigMap 并重启读取它的工作负载。因为ateapi、ate-controller、atelet、atenet-router都通过envFrom读取该 ConfigMap所以一次 patch 即可覆盖所有控制面组件ate-controller还会把值复制到它创建的 ateom worker pod。actor 容器则不同substrate 不在 actor 容器里放任何 OTLP 配置它们使用 ActorTemplate 的env./benchmarking/workloads/deploy.sh --deploy不给--otlp-endpoint时benchmarking/workloads/deploy.sh 会从ate-otel-configConfigMap 读取端点resolve_otlp_endpoint()函数上面一步已经改写了该 ConfigMap因此 actor 会跟着控制面一起指向 meter。只有当你想让 actor 与 control plane 发往不同地址时才显式传--otlp-endpoint。重要让负载生成器locust/boomer继续走平时的 Collector。否则 meter 会把负载生成器自身的遥测也计入 substrate 的遥测总量。2.2 meter 的内部结构源码级从 benchmarking/telemetry/meter.yaml 可以看到 meter 的核心管线otlpreceiver 监听 4317gRPC与 4318HTTPcount connector为 spans 和 datapoints 各生成一个计数指标substrate_spans_total/substrate_datapoints_total按service.name缺失时归入unknown聚合connector 声明MutatesDatafalse因此不会改动转发给托管 Collector 的数据deltatocumulativeprocessor 把 connector 产生的 delta 计数转成累积计数——否则 Prometheus exporter 会把每个新 start timestamp 当成一次计数器重置每次抓取只能看到最后一个 batchprometheusexporter 在8889端口暴露计数在8888端口暴露 meter 自身的otelcol_*自指标otlp/managedexporter 把数据转发给托管 Collectoropentelemetry-collector.gke-managed-otel.svc.cluster.local:4317。此外traces/count与metrics/count两条计数管线、traces/forward与metrics/forward两条转发管线共享同一个 receivermemory_limiter在每个读取 receiver 的管线中排在首位但metrics/count-out管线故意不加 limiter——在那里拒绝数据会直接毁掉这次运行的测量。2.3 在 kind 集群上测量不要在 kind 上安装 meter。kind 里的 Collector 是自有的manifests/ate-install/kind/otel-collector.yaml 已经内置了同样的 count connector能给出同样的两个计数。在它前面再加一个 meter 只是多一跳测量不到任何新东西。meter 只服务于 GKE——那里的托管 Collector 无法容纳 connector。hack/install-ate.sh会在 kind 上同时安装 Collector 与 Prometheus因此 kind 集群无需额外步骤kubectl port-forward -n otel-system svc/prometheus 9090:9090查询语句与 GKE 完全相同只有三点差异Prometheus 与 Collector 位于otel-system命名空间而不是benchmarking不传--otlp-endpointkind 的ate-otel-configConfigMap 已指名 Collectorbenchmarking/workloads/deploy.sh会读取它actor 无需任何 flag 即跟随控制面kind 的 ConfigMap 把OTEL_METRIC_EXPORT_INTERVAL设为 10sGKE 为 60s因此 kind 上查询范围[1m]就够用。注意 benchmarking/monitoring.yaml 与 cAdvisor 仅用于 GKEkind 集群只测 volume——它的 Collector 是单副本、无 HPA节点内存就是整台机器的内存成本数字无法外推到真实集群。3. 场景阶梯Scenario LadderS0–S3阶梯定义在 benchmarking/automation/tests.yaml 中是四个名称以observability_开头的测试。每个测试是一个或多个阶梯步的一次运行#测试名时长阶梯步S0observability_s0_idle_floor5m无负载空闲底线S1observability_s1_user_sweep每步 3m用户数 5 → 10 → 15--trace-probability 0.1S2observability_s2_sample_rate_sweep每步 3m10 个用户采样率 0 → 0.1 → 1.0S3observability_s3_soak10m12 个用户S1 最大值的 80%对应的 tests.yaml 条目揭示了每个测试的实际参数。例如 S1- name: observability_s1_user_sweep type: locust file: /app/tests/glutton.py,/app/shapes/ladder_shape.py duration: 9m users: 5 workerCount: 10 flags: - --ladder - 5:3m,10:3m,15:3m - --trace-probability - 0.1S2 的阶梯步带有采样率变化--ladder 10:3m:0,10:3m:0.1,10:3m:1.0S0 是--ladder 0:5m并带--allow-empty-stats因为空闲底线不发任何请求locust 不会产生测量行运行结果只存在于遥测计数中S3 是--ladder 12:10m。3.1 为什么负载必须来自 boomer而不是 Python每个测试都使用GluttonUser因此负载来自boomer workerGo 实现的 locust worker。不要把阶梯放在 Python 用户类上——Python 与 gRPC 在高用户数下会互相钳制此时的延迟是负载生成器自身的延迟运行测到的是生成器而不是 substrate。在 benchmarking/locust/runner.py 中可以看到这一机制needs_boomer()判断测试文件不在PYTHON_TESTS闭集ate_api.py、counter_demo.py、sleep.py、usermem.py、kernelmem.py内时就以--master --expect-workers 1启动 locust并同时以子进程启动 boomer workerBOOMER_BINARY /app/boomer-worker。glutton.py 的阶梯自然落在 boomer 上。3.2--ladder一次运行跑完整个扫描一次运行的步进是--ladder users:duration[:trace_probability]由 benchmarking/locust/shapes/ladder_shape.py 解析。parse_ladder()用正则^(?Pusers\d):(?Pduration\d)(?Punit[smh]?)(?::(?Pprobability[0-9.]))?$解析每个步步长单位支持 s/m/h概率必须落在 0.0–1.0任何解析失败都会直接抛ValueError——因为跑错了场景的阶梯产出的表格读者无法与正确运行区分开。形状shape让每个步保持其时长然后进入下一步因此一次运行即可得到完整的扫描且只有一次部署、一个基线。LadderShape.tick()按累积时间边界推进步进--ladder-spawn-rate默认 5.0 用户/秒控制步进切换时的生成速率。命名了概率的步会在步开始时改变采样率值写入 master 的 parsed optionsboomer 在步切换触发的 spawn 消息时从/boomer-config读取。--trace-probability给出第一个命名概率步之前的值若阶梯所有步都不含概率则全程保持该 flag 的值。3.3 三条硬性规则步长不得小于 3 分钟。指标推送间隔是 60 秒更短的步会让每条序列拿不到三个数据点你就无法区分趋势与噪声。S1 的用户数止步于 15。因为运行的 worker 池是 10 个 workerworkerCount: 10。超过这个数的步测到的是调度器队列而不是工作系统的遥测。想测更高用户数必须同时提高workerCount。locust web UI 只用于人工检查不承载阶梯。且有两个特殊条件boomer-workersidecar 会为你在表单中选择的每个用户类制造自己的负载表单能改 boomer worker 的采样率但改不了 Python worker 的采样率——benchmarking/locust/manifests/locust.yaml 给 boomer 传了--master-web-port8089boomer 在每次 spawn 消息时从 master 读取/boomer-config该端点由benchmarking/locust/common/boomer_config.py在 master 上提供。4. 读取数字Prometheus 查询与通过标准benchmarking/monitoring.yaml 负责抓取 meter对telemetry-meterpod 的 8889 端口做注解自动发现另设telemetry-meter-self任务抓取 8888 的自指标。不要手工比较原始 scrape 结果通过 Prometheus 读取kubectl apply -f benchmarking/monitoring.yaml kubectl port-forward -n benchmarking svc/prometheus 9090:90904.1 核心查询要查什么查询每个服务的 spans/秒sum by (service_name) (rate(substrate_spans_total[5m]))每个服务的 datapoints/分60 * sum by (service_name) (rate(substrate_datapoints_total[5m]))数据是否到达sum(rate(otelcol_receiver_accepted_spans[5m]))Collector 是否拒绝数据sum(rate(otelcol_receiver_refused_spans[5m]))count 是否丢弃序列sum(otelcol_deltatocumulative_datapoints{errorlimit})距 stream 上限有多近otelcol_deltatocumulative_streams_tracked / otelcol_deltatocumulative_streams_limit范围至少取推送间隔的三倍60s 推送下[5m]是不错的默认值小于 3m 的范围只会带来噪声。4.2 正控制positive control零与没来的区别始终读取最后四个计数器。一个零体积的服务本身不产生数据必须在同一窗口内accepted大于零且refused为零。若不然那个零说明的是数据没有到达而不是服务没有发送。不检查正控制一个什么都没发的 exporter 看起来和一次好运行一模一样。后两个计数器覆盖max_streams这种不同的失效模式count connector 把 resource 复制到每个计数上serverboot给每个进程独立的service.instance.id因此一个进程在每种计数上持有一条 stream。超过上限后deltatocumulative会静默丢弃每条新 stream没有日志行序列悄悄离开 scrape——体积读起来偏低却没有任何错误报告。因此丢弃计数必须为零比值在运行全程必须低于 1。4.3 通过标准Pass Criteria一次合格的运行必须同时满足otelcol_receiver_refused_*必须为零otelcol_exporter_enqueue_failed_*必须为零客户端queue_full必须为零Collector 副本数必须保持在maxReplicas之下在 S3 中Collector working set 的斜率与otelcol_exporter_queue_size的斜率必须等价于零即长时间浸泡下不增长。同时检查正控制每个必须发送数据的服务其otelcol_receiver_accepted_*必须大于零。5. meter 的三种边界条件Three Conditions of the Teemeter 是 tee这让测量正确但也引入了三个必须理解的条件① 托管 Collector 会把遥测归因到 meter。它应用k8sattributes且from: connection每个转发项现在都来自 meter pod。体积与 CPU 仍然正确但在托管侧按 pod 分组的查询会失真。应改按 resource 中的service.name分组——该值在跳转后仍然正确。② 负载形状会改变。通常很多进程各自维持一条到托管 Collector 的连接有了 tee 之后变成一个发送方、更大的 batch。因此总量正确但跨副本的分布不再真实连接粘性connection stickiness的效应消失。③ meter 本身可能成为瓶颈。它是单副本。把它的自指标加入通过标准sum(rate(otelcol_receiver_refused_spans[5m])) # 必须为 0 sum(rate(otelcol_exporter_sent_spans[5m])) # 必须大于 0 max_over_time(otelcol_exporter_queue_size[5m]) # 必须保持水平 absent(otelcol_exporter_sent_spans) # 必须无结果 sum(otelcol_deltatocumulative_datapoints{errorlimit}) # 必须为 0 otelcol_deltatocumulative_streams_tracked / otelcol_deltatocumulative_streams_limit # 必须低于 1不要单独使用otelcol_exporter_send_failed_spans默认retry_on_failure.max_elapsed_time是 5 分钟exporter 会先重试那么久才计入失败——一个正在丢数据的 meter 在短步长内看起来完全正常。队列深度变化立即发生因此它才是要盯的信号。absent()捕获另一种情况meter 什么都不上报。如果 meter 丢弃了数据volume 与 cost 会同时错误且两个错误互相掩盖。memory_limiter与GOMEMLIMITmeter.yaml 中GOMEMLIMIT3000MiB让 meter 在到达内存上限时以拒绝数据的方式失败——显式暴露在otelcol_receiver_refused_*里而不是被内核杀死。注意limiter 用百分比会跟随容器上限但GOMEMLIMIT是绝对值扩大容器限制时需要同步更新它。要让 meter 变成终点terminal删除 meter.yaml 中的两条 forward 管线即可计数继续工作。长 soak 测试建议用 terminal meter把遥测挡在 Cloud Monitoring 之外但此时托管 Collector 的资源值变成空闲 Collector 的值不得记录它们。6. 客户端丢弃计数器meter 看不见的丢失meter 只显示到达的数据不显示客户端丢弃的数据。要打开 SDK 里的插桩kubectl set env -n ate-system deployment/ate-api-server OTEL_GO_X_OBSERVABILITYtrue抓取进程上的:9090/metrics——该端点是 Prometheus 读取器不走 OTLP 路径因此在它测量的拥塞期间仍能正常工作。指标说明otel_sdk_span_started_total{otel_span_parent_origin,otel_span_sampling_result}采样决策根 span 与继承 spanotel_sdk_processor_span_processed_total{error_typequeue_full}客户端丢弃的 spansotel_sdk_processor_span_queue_sizevs_capacity丢弃开始前的余量没有这个丢弃计数器客户端侧的丢失看起来和一个稳定的平台期一模一样。该 flag 是实验性的位于sdk/internal/x指标名会随 SDK 升级而变化——每次升级后要重新核对名称。7. 移除 meter测量结束后按原路径恢复./hack/install-ate.sh --deploy-ate-system ./benchmarking/workloads/deploy.sh --deploy kubectl delete -f benchmarking/telemetry/meter.yaml两个脚本在不传--otlp-endpoint时都会回到默认端点。8. 开放事项Open Itemsbenchmarking/observability.md 列出了当前流程尚未覆盖的改进点可作为继续深化该基准测试的路线图把每个服务的 volume 作为每次运行的产物runner.py只写 locust 统计读者仍须自己查询 Prometheus 才能拿到本次运行的substrate_*计数用 working set 测量 Collector 的 CPU 与内存不要用kubectl top它计算的是平均值会掩盖峰值这也呼应了 docs/dev/best-practices/otel-collector.md 中用container_memory_working_set_bytes它是 OOM killer 实际使用的值的结论每张 volume 表都记录otelcol_receiver_accepted_*作为正控制记录副本数记录 CPU 与内存时若不记录副本数一个没有容量的 Collector 和一个容量富余的 Collector 会给出完全相同的表测量 actor volumeglutton模板现在设置了 OTLP endpointactor 遥测第一次真正到达这是 benchmarking/workloads/deploy.sh 中--otlp-endpoint与 ActorTemplateenv机制带来的新能力测量 Collector 规模指引中的 DaemonSet 配置目前所有测量都基于 Deployment 模式DaemonSet 模式的结论仍是外推需要对照实测确认见 docs/dev/best-practices/otel-collector.md 末尾的警告。9. 与 Collector 规模指引的衔接本页面只负责怎么测测得的数据意味着什么由 docs/dev/best-practices/otel-collector.md 解释。两个关键结论直接指导阶梯设计metrics 随组件数量增长datapoints/min ≈ 节点数×atelet_dp ateapi 副本×ateapi_dp router 副本×router_dp worker pod 数×ateom_dp 插桩 actor 数×actor_dp。每个二进制在 SDK 默认 60s 的PeriodicReader上推送且无抖动见 internal/serverboot/serverboot.go因此一起启动的进程也会一起推送请求速率对这个项影响很小。这也是 S0 空闲底线存在的意义——组件数量本身就有遥测成本。traces 随操作速率增长spans/sec ≈ (actor 生命周期操作/秒 actor 请求/秒) × P(根采样) × spans_per_op。自ParentBased(TraceIDRatioBased)成为默认以来ateapi/atelet/ateom-* 为 0.1atenet-router 与 Envoy 为 0.01只有没有 traceparent 到达的操作才由本地采样率决定客户端一旦带traceparent就为整条链路做了决定。这正解释了 S2 为什么要在固定 10 用户下扫描采样率 0 → 0.1 → 1.0它在单独刻画 traces 这个成本轴。因此阶梯的两个维度S1 用户数扫描 S2 采样率扫描分别对应 volume 模型的两个独立驱动轴S0 提供组件基数基线S3 则验证在 80% 峰值负载下长期浸泡时 Collector 资源曲线是否保持水平——这正是判断 Collector 是否需要扩容Deployment 换 DaemonSet、提升副本、降低采样率所必需的证据。赞分享人工智能AI AgentAgent 沙箱云原生容器运行时零信任【免费下载链接】substrateAgent Substrate: the core system项目地址https://gitcode.com/GitHub_Trending/substrate7/substrate点击查看免费下载相关推荐Polly 遥测Telemetry性能开销实测TelemetryBenchmark 基准报告解读与源码剖析Polly 遥测Telemetry性能开销实测TelemetryBenchmark 基准报告解读与源码剖析 本篇文章以仓库中由 BenchmarkDotN后端微服务Agent Substrate 指标链路深度解读Prometheus Bridge 与 OTLP 导出的基准测试开销分析Agent Substrate 指标链路深度解读Prometheus Bridge 与 OTLP 导出的基准测试开销分析 导读 在 Agent Substra人工智能AI AgentAgent 沙箱云原生容器运行时零信任Substrate Benchmarking 实战指南用 Locust 与 OTel 对 Agent Substrate 做规模化压测Substrate Benchmarking 实战指南用 Locust 与 OTel 对 Agent Substrate 做规模化压测 本篇技术指南围绕 Ag人工智能AI AgentAgent 沙箱云原生容器运行时零信任创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表