Posted in

【Go可观测性思维觉醒】:从打log到建信号,4类黄金指标定义法让SRE主动找你合作

第一章:Go可观测性思维觉醒:从日志驱动到信号驱动的范式跃迁

传统日志驱动模式将可观测性等同于“事后翻查文本”,开发者依赖 log.Printf 输出结构化或非结构化字符串,再通过 grep、ELK 或 Loki 拼凑系统状态。这种被动、离散、高噪声的方式难以支撑现代云原生服务的实时诊断需求。信号驱动范式则将日志(Logs)、指标(Metrics)、追踪(Traces)视为统一可观测性三角的三类互补信号——每类信号承载不同维度的真相:日志记录“发生了什么”,指标回答“有多频繁/多严重”,追踪揭示“请求如何流动”。

Go 生态天然支持信号协同:net/http/pprof 提供基础指标端点,go.opentelemetry.io/otel 实现标准化追踪注入,而结构化日志库如 zerologzap 可与上下文绑定 traceID,实现信号自动关联。例如,在 HTTP 处理器中注入 OpenTelemetry 上下文:

import "go.opentelemetry.io/otel/trace"

func handler(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()
    span := trace.SpanFromContext(ctx) // 从传入请求提取当前 span
    span.AddEvent("handler_start")      // 记录事件,无需手动管理生命周期
    defer span.End()                    // 自动结束 span,确保信号完整性

    // 同时向日志注入 traceID 和 spanID
    logger := zerolog.Ctx(ctx).With().
        Str("trace_id", span.SpanContext().TraceID().String()).
        Str("span_id", span.SpanContext().SpanID().String()).
        Logger()
    logger.Info().Msg("request processed")
}

信号驱动要求开发者在编码初期即设计可观测性契约:定义关键业务指标(如 http_request_duration_seconds_bucket)、设置采样策略(如对错误率 > 1% 的请求全量追踪)、规范日志字段(统一 service.nameenvrequest_id)。这不再是运维阶段的补丁,而是与业务逻辑并行的一等公民。

信号类型 Go 标准实践 典型用途
Logs zerolog.With().Str("error").Err() 审计、异常详情、用户行为记录
Metrics prometheus.NewCounterVec() SLO 监控、容量规划、告警触发
Traces otel.Tracer.Start(ctx, "db.query") 延迟瓶颈定位、跨服务链路分析

http.Handler 被包裹在 OpenTelemetry 中间件中,每次请求自动产生可关联的三类信号,可观测性不再依赖人工拼接,而成为系统固有脉搏。

第二章:Go原生可观测性基石构建

2.1 Go runtime指标采集:pprof与runtime/metrics的深度整合实践

Go 1.21+ 提供了 runtime/metrics 包作为轻量、无锁、低开销的指标采集新范式,而 pprof 仍承担运行时剖析核心职责。二者并非替代关系,而是互补协同。

数据同步机制

runtime/metrics.Read 返回快照值,需周期调用;pprof 则通过 HTTP handler 暴露实时 profile 数据。理想实践是统一采集入口:

// 同步采集 runtime 指标并注入 pprof 标签上下文
var m metrics.Metric
m.Name = "/gc/heap/allocs:bytes"
m.Description = "Total bytes allocated in heap"
m.Unit = "bytes"
metrics.Read(&m) // 零分配、无锁读取

该调用直接访问 runtime 内部计数器,无需 goroutine 或 channel,延迟 Name 字段遵循 metrics naming convention,确保与 pprof/debug/pprof/heap 等端点语义对齐。

关键指标映射表

pprof endpoint runtime/metrics Name 采集频率建议
/debug/pprof/heap /gc/heap/allocs:bytes 每秒一次
/debug/pprof/goroutine /goroutines:goroutines 每 5 秒一次
/debug/pprof/sched /sched/goroutines:goroutines 每 10 秒一次

协同采集流程

graph TD
    A[定时 ticker] --> B{runtime/metrics.Read}
    B --> C[结构化指标快照]
    C --> D[写入 Prometheus Exporter]
    A --> E[pprof.Handler.ServeHTTP]
    E --> F[按需生成堆栈 profile]
    D & F --> G[统一监控仪表盘]

2.2 HTTP服务信号建模:net/http中间件中嵌入Latency、Error、Request、Saturation四维黄金指标

四维指标的语义锚定

  • Latency:P95端到端延迟(含路由、业务逻辑、I/O)
  • Error:HTTP状态码 ≥400 且非客户端主动取消(context.Canceled 排除)
  • Request:每秒请求数(RPS),按路径与方法维度聚合
  • Saturation:连接池等待队列长度 / 最大并发限制(反映资源压测临界点)

中间件实现示例

func MetricsMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        rw := &responseWriter{ResponseWriter: w, statusCode: 200}

        next.ServeHTTP(rw, r)

        latency := time.Since(start).Seconds()
        labels := prometheus.Labels{"path": r.URL.Path, "method": r.Method}

        httpLatency.With(labels).Observe(latency)
        httpErrors.With(labels).Add(float64(boolToFloat(rw.statusCode >= 400 && !isClientCancel(r))))
        httpRequests.With(labels).Inc()
        httpSaturation.With(labels).Set(float64(getWaitQueueLen())) // 依赖连接池暴露指标
    })
}

该中间件在ServeHTTP前后注入观测钩子:start捕获请求入口时间,responseWriter包装响应以捕获真实状态码;isClientCancel需检查r.Context().Err()是否为context.CanceledgetWaitQueueLen()须对接net/http.ServerConnState或自定义连接池。

指标联动关系

维度 关联行为 预警阈值建议
Latency ↑ 可能触发 Saturation ↑ P95 > 500ms
Error ↑ 常伴随 Latency ↑ 或 Saturation ↑ 错误率 > 1%
Saturation = 1.0 表明连接池已满,Request 将排队 队列长度 > 10
graph TD
A[HTTP Request] --> B[Metrics Middleware]
B --> C{Latency<br>Error<br>Request<br>Saturation}
C --> D[Prometheus Exporter]
D --> E[AlertManager 触发复合规则]

2.3 Goroutine生命周期可观测化:基于trace.Tracer与runtime.GoroutineProfile的主动诊断模式

Goroutine 的隐式调度特性使传统日志难以捕获其真实生命周期。主动诊断需融合事件追踪与快照分析。

追踪 Goroutine 创建与阻塞点

import "runtime/trace"

func instrumentedHandler() {
    trace.StartRegion(context.Background(), "http:handler")
    defer trace.EndRegion(context.Background(), "http:handler")
    // ...业务逻辑
}

trace.StartRegion 在当前 goroutine 中注入结构化事件标签,context.Background() 作为事件上下文载体;EndRegion 自动关联起止时间戳,供 go tool trace 可视化解析。

快照级诊断:Goroutine 状态聚合

状态 含义 典型诱因
runnable 等待 CPU 调度 高并发抢占、P 数不足
syscall 阻塞于系统调用 文件读写、网络等待
sync.Mutex 持有锁但被其他 goroutine 等待 锁粒度粗、临界区过长

生命周期联动分析流程

graph TD
A[trace.StartRegion] --> B[记录 goroutine ID + start time]
C[runtime.GoroutineProfile] --> D[采集状态快照]
B --> E[关联阻塞事件]
D --> E
E --> F[生成生命周期热力图]

2.4 Structured Logging in Go:zerolog/log/slog结构化日志与指标联动的信号增强设计

日志与指标的语义对齐

结构化日志需与 Prometheus 指标共享关键维度(如 service, route, status_code),避免信号割裂。zerolog 与 slog 均支持字段注入,但零分配设计(zerolog)更适合高吞吐场景。

字段标准化实践

// 使用 zerolog 注入可观测性上下文
logger := zerolog.New(os.Stdout).
    With().
    Str("service", "auth-api").
    Str("env", os.Getenv("ENV")).
    Timestamp().
    Logger()
logger.Info().Str("action", "login").Int("attempts", 3).Send()

→ 该日志自动携带 service/env 标签,可被 Loki 通过 | json 提取,并与 Prometheus 中同名 label 关联实现 trace-log-metric 三元联动。

联动信号增强机制

日志字段 对应指标标签 用途
status_code code HTTP 指标分桶统计
duration_ms quantile 与 Histogram 观测值对齐
error_type kind 错误分类告警聚合
graph TD
    A[HTTP Handler] --> B[zerolog.With().Fields()]
    B --> C[JSON Log Line]
    C --> D{Loki Query}
    C --> E[Prometheus Exporter]
    D & E --> F[统一告警规则]

2.5 Context-aware tracing:通过context.Value与http.Request.Context实现跨goroutine调用链信号透传

在 Go 的 HTTP 服务中,http.Request.Context() 提供了天然的、可继承的上下文载体,是实现跨 goroutine 调用链透传的核心基础设施。

为什么需要 context.Value?

  • 避免函数签名污染(无需显式传递 traceID、userID 等透传字段)
  • 保证生命周期与请求一致(随 Request 创建/取消自动管理)
  • 支持 cancel、timeout、deadline 等信号同步

关键实践模式

func handler(w http.ResponseWriter, r *http.Request) {
    // 从 Request 获取 context,并注入 traceID
    ctx := r.Context()
    ctx = context.WithValue(ctx, "trace_id", generateTraceID())

    go processAsync(ctx) // 子 goroutine 自动继承 ctx
}

context.WithValue 返回新 context,不影响原 request.ctx;
❌ 不应存入结构体指针或可变对象(违反 immutability 原则);
⚠️ key 类型推荐使用私有 unexported 类型,避免 key 冲突。

常见透传字段对照表

字段名 类型 用途 是否建议存储于 context.Value
trace_id string 分布式链路唯一标识
user_id int64 当前请求用户身份 ✅(需脱敏)
deadline time.Time 请求截止时间 ✅(由 WithDeadline 自动注入)
logger *zap.Logger 请求级日志实例 ⚠️(推荐传 interface{},避免强依赖)

调用链透传流程(简化版)

graph TD
    A[HTTP Handler] --> B[ctx.WithValue trace_id]
    B --> C[goroutine 1: DB Query]
    B --> D[goroutine 2: RPC Call]
    C --> E[log.WithContext ctx]
    D --> E

第三章:Go服务黄金指标定义法实战

3.1 RED方法在Go微服务中的落地:Requests、Errors、Duration指标的熔断级采样策略

RED(Requests、Errors、Duration)是微服务可观测性的黄金三角。在高吞吐Go服务中,全量采集会引发性能抖动与存储爆炸,需引入熔断级动态采样——当错误率或延迟突增时,自动提升采样率至100%,平稳期则降至0.1%。

动态采样控制器设计

type Sampler struct {
    baseRate float64 // 基础采样率(如0.001)
    ceiling  float64 // 熔断阈值(如error_rate > 5% → rate=1.0)
    metrics  *prometheus.CounterVec
}

func (s *Sampler) ShouldSample(ctx context.Context, err error, dur time.Duration) bool {
    rate := s.baseRate
    if err != nil || dur > 200*time.Millisecond {
        rate = 1.0 // 触发熔断采样
    }
    return rand.Float64() < rate
}

逻辑分析:ShouldSample 根据实时错误/延迟状态动态切换采样率;baseRate=0.001对应千分之一常规采样,dur > 200ms为P95延迟阈值,确保长尾请求必采。

采样策略对比

场景 采样率 目标
正常流量 0.1% 控制指标体积
错误率 > 5% 100% 完整定位故障根因
P99延迟 > 500ms 10% 平衡诊断精度与资源开销

指标注入流程

graph TD
A[HTTP Handler] --> B{Sampler.ShouldSample?}
B -- true --> C[Record RED metrics]
B -- false --> D[Skip metrics]
C --> E[Push to Prometheus]

3.2 USE方法适配Go运行时:Utilization、Saturation、Errors在GOMAXPROCS与GC Pause场景的量化建模

Utilization:CPU时间片分配与GOMAXPROCS的线性映射

runtime.NumCPU()GOMAXPROCS 共同决定可调度P的数量,直接影响CPU利用率可观测性:

func measureGOMAXPROCSUtil() float64 {
    p := runtime.GOMAXPROCS(0) // 获取当前值
    g := runtime.NumGoroutine()
    return float64(g) / float64(p) // 粗粒度goroutine/P比值,反映调度负载密度
}

该比值>5时往往预示P过载;但需结合/debug/pprof/schedsched.latency验证。

Saturation:GC Pause引发的调度器阻塞链

GC STW期间所有P进入_Pgcstop状态,导致goroutine积压:

指标 GC触发阈值 STW典型时长 对Saturation影响
GOGC=100 堆增长100% ~1–5ms 中等积压
GOGC=10(调试) 堆增长10% ~10–50ms 高饱和风险

Errors:GC相关错误信号建模

// 从runtime/metrics中提取GC暂停异常事件
metrics.Read([]metrics.Sample{
    {Name: "/gc/pauses:seconds"},
})

/gc/pauses:seconds第99分位 > 10ms,且伴随/sched/goroutines:goroutines突降,则判定为GC-induced error spike。

graph TD A[GC Start] –> B[STW Phase] B –> C[P State = _Pgcstop] C –> D[Goroutine Queue Growth] D –> E[Scheduler Latency ↑]

3.3 Four Golden Signals的Go语义重定义:Latency(P99/P999分位)、Traffic(QPS+并发连接数)、Errors(errorAsStatus+panic recovery率)、Saturation(goroutine count + memory watermark)

Latency:P99/P999分位精准捕获长尾延迟

Go原生expvar不支持分位统计,需结合github.com/VictoriaMetrics/metrics或自建滑动窗口直方图:

// 使用轻量级直方图(无GC压力)
var latencyHist = metrics.NewHistogram("http_request_duration_seconds", 
    metrics.Buckets{0.01, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0})
// 记录耗时(单位:秒)
latencyHist.Update(float64(dur.Microseconds()) / 1e6)

逻辑分析:Update()自动归入对应bucket;Buckets按对数分布设计,确保P99/P999误差Microseconds()避免浮点精度丢失。

Saturation:双维度水位联动预警

指标 阈值触发线 动态响应策略
runtime.NumGoroutine() > 5000 启动goroutine泄漏检测
runtime.ReadMemStats() Sys > 80% 触发GC强制回收

Errors:panic recovery率量化

func recoverWithStatus(w http.ResponseWriter, r *http.Request) {
    if err := recover(); err != nil {
        metrics.IncrementCounter("http_panic_recovered_total")
        http.Error(w, "Internal Error", http.StatusInternalServerError)
    }
}

逻辑分析:IncrementCounter记录recover成功次数;配合errorAsStatuserrors.Is(err, ErrNotFound)映射为404状态码,统一错误可观测性。

第四章:SRE协同共建可观测体系的Go工程化路径

4.1 Go module可观测性契约:定义go.mod注释规范与/healthz /metrics /debug/pprof端点的标准化注入机制

Go module 可观测性契约要求模块作者在 go.mod 中声明可观测能力,通过标准注释触发自动化端点注入:

// go.mod
module example.com/app

go 1.22

// observability v1
// healthz: true
// metrics: prometheus
// pprof: enabled

该注释被构建时解析,驱动可观测中间件自动注册。支持的配置项包括:

  • healthz: 启用 /healthz 健康检查(HTTP 200/503)
  • metrics: 指定指标格式(prometheusopentelemetry
  • pprof: 控制 /debug/pprof/* 是否暴露(enabled/disabled
注释键 取值范围 默认值 作用
healthz true / false false 注入 Liveness 探针端点
metrics prometheus none 注册 /metrics 并初始化 Registry
pprof enabled/disabled disabled 控制 pprof 路由挂载
// 自动生成的可观测路由注入(由 go mod tidy + toolchain 插件完成)
func setupObservability(r *chi.Mux, cfg ObservabilityConfig) {
    if cfg.Healthz { r.Get("/healthz", healthHandler) }
    if cfg.Metrics == "prometheus" { r.Get("/metrics", promhttp.Handler().ServeHTTP) }
    if cfg.Pprof == "enabled" { r.Mount("/debug/pprof", http.HandlerFunc(pprof.Index)) }
}

上述逻辑由 go mod vendor 阶段的可观测性插件解析 go.mod 注释后生成;cfg 结构体由工具链静态推导,避免运行时反射开销。

graph TD
    A[go.mod 注释] --> B[go toolchain 解析]
    B --> C{生成 observability.cfg}
    C --> D[编译期注入路由]
    D --> E[启动时零配置挂载]

4.2 Prometheus Exporter开发范式:使用promauto.NewCounterVec等原子注册器规避goroutine泄漏风险

Prometheus客户端库中,传统prometheus.NewCounterVec()需手动调用MustRegister(),若在热重载或动态指标创建路径中重复注册,会触发panic;更隐蔽的风险是:在goroutine中反复创建未注册/未复用的指标实例,导致底层metricVec持续累积,引发内存与goroutine泄漏。

原子注册优势

  • promauto.With(reg).NewCounterVec(...) 一次性完成构造+注册,线程安全;
  • 内部通过sync.Once与注册器锁保障幂等性;
  • 指标实例全局唯一,避免重复初始化开销。

典型错误模式对比

场景 传统方式 promauto方式
动态标签创建 易重复注册panic 自动复用已有指标
高频goroutine调用 每次新建Vec → goroutine泄漏 复用单例 → 零额外goroutine
// ✅ 推荐:原子注册,安全复用
var (
    httpRequests = promauto.With(promReg).NewCounterVec(
        prometheus.CounterOpts{
            Name: "http_requests_total",
            Help: "Total HTTP requests.",
        },
        []string{"method", "code"},
    )
)

// ❌ 风险:若在handler中多次调用NewCounterVec且未判重,将泄漏
// vec := prometheus.NewCounterVec(...) // → 每次生成新vec,注册器不感知
// promReg.MustRegister(vec)           // → 第二次注册panic,或跳过注册致指标丢失

逻辑分析:promauto.NewCounterVec内部调用reg.GetMetricWithLabelValues()优先查缓存,未命中才构造并原子注册。参数prometheus.CounterOpts定义元数据,[]string{"method","code"}声明标签维度——二者共同决定指标唯一键。

4.3 OpenTelemetry Go SDK集成最佳实践:TracerProvider配置、Span属性注入与Context传播的零侵入封装

初始化高可用 TracerProvider

推荐使用 sdktrace.NewTracerProvider 配合 sdktrace.WithBatchersdktrace.WithSampler,避免默认采样器导致生产环境数据过载:

tp := sdktrace.NewTracerProvider(
    sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(0.01))),
    sdktrace.WithBatcher(exporter, sdktrace.WithMaxExportBatchSize(512)),
)

ParentBased 尊重上游采样决策;TraceIDRatioBased(0.01) 实现 1% 低开销采样;WithMaxExportBatchSize 控制内存压力。

零侵入 Span 属性注入

通过 context.WithValue 封装 Span,结合中间件自动注入业务标签:

场景 推荐注入方式 示例键值
HTTP 请求 http.Request.Context() "http.method", "POST"
数据库调用 context.WithValue() "db.statement", "SELECT *"

Context 透传自动化

func WrapHandler(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()
        span := trace.SpanFromContext(ctx)
        span.SetAttributes(attribute.String("route", "/api/v1/users"))
        h.ServeHTTP(w, r.WithContext(ctx))
    })
}

→ 自动继承父 Span 上下文,无需修改业务逻辑;SetAttributes 替代硬编码 span.AddEvent,提升可观测性语义一致性。

graph TD A[HTTP Handler] –> B[WrapHandler] B –> C[Inject Span Attributes] C –> D[Propagate Context] D –> E[Downstream Service Call]

4.4 可观测性即代码(O11y-as-Code):通过go:generate生成指标注册桩与SLO告警规则模板

传统手动注册指标易遗漏、难同步。go:generate 将可观测性契约前置为编译期契约。

自动生成指标注册桩

//go:generate go run ./cmd/metricsgen -pkg=api
package api

import "github.com/prometheus/client_golang/prometheus"

var (
    // MetricsGen:ignore —— 标记跳过生成
    RequestDuration = prometheus.NewHistogramVec(
        prometheus.HistogramOpts{
            Name: "api_request_duration_seconds",
            Help: "API request latency in seconds",
        },
        []string{"endpoint", "status"},
    )
)

该注释触发 metricsgen 工具扫描全局变量,自动生成 RegisterMetrics() 函数及 OpenMetrics 元数据文件,确保所有指标在 init() 中统一注册。

SLO 告警模板化

SLO 名称 目标值 时间窗口 关键标签
p99_latency 99.9% 30m endpoint="/v1/users"
graph TD
  A[metric.go] -->|go:generate| B(metricsgen)
  B --> C[register.go]
  B --> D[slo_alerts.yaml]
  D --> E[Prometheus Alertmanager]

生成的 slo_alerts.yaml 包含参数化占位符(如 {{ .Target }}),支持 CI 中注入环境特定阈值。

第五章:走向主动式SRE协作:Go可观测性成熟度模型演进

从被动告警到预测性干预的范式迁移

某头部云原生平台在2023年Q3将Go服务的可观测性能力从L2(基础监控)升级至L4(预测协同),关键动作包括:在Gin中间件中嵌入go.opentelemetry.io/otel/sdk/trace自动采样器,结合Prometheus自定义指标go_gc_duration_secondsruntime_memstats_alloc_bytes构建内存泄漏预测模型。该模型上线后,P99延迟尖峰平均提前17分钟被识别,误报率控制在3.2%以内。

工程师协作模式的结构性重构

团队引入基于OpenTelemetry Collector的统一遥测管道,所有Go微服务通过otlphttp exporter上报trace、metrics、logs三类信号,并在Grafana中配置共享仪表盘。当某支付服务出现/v2/transfer路径的HTTP 5xx错误率突增时,SRE、后端开发、测试工程师可同步查看同一Span链路中的db.query.durationredis.get.latencygrpc.client.duration标签维度下钻,无需跨平台切换。

可观测性成熟度四级能力对照表

成熟度等级 核心能力 Go语言落地示例 协作特征
L1 日志聚合 log/slog + Loki日志流过滤 SRE单点排查
L2 基础指标监控 prometheus/client_golang暴露go_info等标准指标 开发提交指标文档
L3 分布式追踪贯通 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp自动注入TraceID 跨服务链路联合分析
L4 异常模式学习与自动归因 使用github.com/grafana/loki/pkg/logql编写LogQL规则检测panic堆栈模式 SRE触发自动化修复流程

基于eBPF的Go运行时深度观测实践

在Kubernetes集群中部署bpftrace脚本实时捕获Go runtime事件:

# 捕获goroutine阻塞超时事件(需启用GODEBUG=gctrace=1)
bpftrace -e '
  uprobe:/usr/local/go/bin/go:runtime.gopark {
    printf("Goroutine %d parked at %s:%d\n", pid, ustack, arg0);
  }
'

该脚本与Jaeger trace ID关联后,在生产环境定位到某订单服务因sync.Mutex.Lock()未释放导致的goroutine堆积问题,平均阻塞时长从8.3s降至0.12s。

主动式协作工作流图示

graph LR
A[OTel Collector接收遥测] --> B{AI异常检测引擎}
B -->|确认为P0级故障| C[自动创建Jira并@SRE+开发]
C --> D[调用Ansible Playbook执行限流]
D --> E[向Slack #oncall频道推送Trace可视化链接]
E --> F[开发者点击链接跳转至Grafana中对应Span详情页]
F --> G[协作编辑根因注释并关联Git Commit]

多语言服务间的可观测性对齐机制

为解决Go服务与Java网关间Trace上下文丢失问题,团队在Go侧实现W3C Trace Context兼容补丁:

// 自定义propagator确保B3与W3C双格式支持
prop := propagation.NewCompositeTextMapPropagator(
  propagation.TraceContext{},
  propagation.B3{},
)
otel.SetTextMapPropagator(prop)

该补丁使跨语言调用链完整率从62%提升至99.8%,支撑了全链路SLI计算闭环。

成熟度跃迁的基础设施依赖项

  • OpenTelemetry Go SDK v1.21+(要求Go 1.20+)
  • Prometheus 2.45+ 的exemplar支持
  • Grafana 10.1+ 的Trace-to-Metrics联动功能
  • Loki 2.9+ 的结构化日志解析能力

实时反馈闭环的建立

在CI/CD流水线中嵌入go run github.com/uber-go/zap/cmd/zapcheck静态扫描,强制要求新提交代码包含slog.With结构化字段;同时在Kubernetes Deployment中配置sidecar.istio.io/rewriteAppHTTPProbers: "true",确保健康检查不干扰OTel采样率。

敏捷如猫,静默编码,偶尔输出技术喵喵叫。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注