“Observability”(可观测性)是系统工程中的一个核心概念,尤其在分布式系统、云原生架构和微服务环境中至关重要。Observability 指的是通过系统外部可见的数据(如指标、日志、追踪信息等),推断系统内部状态并理解其运行行为的能力。它能够帮助工程师快速定位问题,优化性能,确保系统的可靠性和稳定性。
传统上,Observability 的三大支柱是 Metrics(指标)、Logs(日志)和 Traces(分布式追踪)。在现代 Observability 中,这一体系已扩展为五大数据类型,涵盖 Events(事件)和 Profiles(性能剖析)。
现代 Observability 的实现得益于 CBPF/eBPF 技术,它们支持高性能、零代码的数据采集,并已催生出多种开源 Agent 工具。
tcpdump
。利用 eBPF 的强大能力,社区开发了多种开源工具,能够实现零代码的深度数据采集。
术语 | 定义 |
---|---|
Monitoring | 实时监控系统的健康状况和性能,用于快速检测异常。 |
Tracing | 追踪请求在分布式系统中的传播路径,用于依赖关系和性能分析。 |
Logging | 捕获系统运行时的信息,记录详细的事件历史。 |
Instrumentation | 在代码中嵌入可观测性相关逻辑以生成数据,便于调试和监控。 |
CBPF | 经典 BPF,主要用于简单的网络数据包过滤操作。 |
eBPF | 扩展 BPF,可挂载到内核多个钩子点,支持复杂的监控和分析任务。 |
XDP | 高性能网络数据包处理框架,运行在网络驱动层。 |
Observability 是现代分布式系统中不可或缺的能力。通过 Metrics、Logs、Traces、Events 和 Profiles 的结合,以及 CBPF/eBPF、XDP 等强大的内核技术支持,我们能够全面了解系统的行为和状态,并快速诊断问题。结合 DeepFlow-Agent、Pixie、Cilium 等开源工具,可以轻松实现零代码、低开销的高效数据采集,保障系统的稳定性和性能。
象限定位(X=APM 强度,Y=NPM 强度)
产品/厂商 | 类型定位 | APM 能力(应用) | NPM 能力(网络) | 亮点 / 差异 |
---|---|---|---|---|
乘云数字 DataBuff | 综合型 | 有(链路追踪、AI 辅助) | 有(依赖/拓扑) | 国产化与行业落地(成本/合规友好) |
DeepFlow | NPM 起家 | 有一定(eBPF 侧采集) | 强(eBPF+流量/拓扑/pcap) | 零侵入、流量级全栈关联 |
科莱 Colasoft | NPM 为主 | 弱 | 强(抓包、协议解析、取证) | 传统网络与取证场景 |
Dynatrace | APM 为主 | 强(OneAgent、因果分析、数据湖仓) | 中(网络依赖/集成) | 自动化一体化强,企业级 |
Datadog | 综合型 | 强(APM/Trace/RUM/Profiler) | 中–强(USM/eBPF) | 模块丰富、生态广 |
New Relic | APM 为主 | 强(全栈 APM) | 中 | 免费层友好、易上手 |
Apache SkyWalking | APM 为主 | 强(Trace/Metrics/Logs) | 中(Rover eBPF Profiling) | 开源可控,国产替代佳 |
OpenTelemetry(OTel) | 采集标准 | N/A(SDK/Collector) | N/A | 统一三信号采集;需搭配后端 |
Grafana Labs(LGTM+Pyroscope) | 平台拼装 | Tempo=Trace(Grafana UI) | Loki/Mimir 为主(可联动 Cilium/Hubble) | 自建成本友好、组件化灵活 |
Rancher(Monitoring 组合) | 多集群集成 | 接 OTel/Tempo/Prometheus | 接 Prom/Loki(非专职 NPM) | 多集群可观测与运维整合 |
SigNoz(开源) | APM 为主 | 强(OTel 原生) | 中(应用侧为主) | “开源 Datadog 替代”路线 |
Cilium + Hubble(开源) | NPM 为主 | 弱 | 强(L3–L7 拓扑/依赖) | K8s eBPF 网络观测标配 |
Pixie(开源) | NPM/运行时 | 中(运行时剖析) | 强(eBPF 自动采集) | 零代码采集,研发/调试友好 |
公司 | APM(应用观测) | NPM/网络侧 | 主要栈/产品 | 公开亮点(摘) |
---|---|---|---|---|
字节跳动 | 自研/对外产品 APMPlus(火山引擎),内外统一用 OTel 采集;内部有 BytedTrace(统一 Tracing/Logging/Metrics 的平台化方案) | (公开资料以应用侧为主,网络侧细节披露较少) | APMPlus + OTel Collector(自动注入/接入)、CloudWeGo 生态 | APMPlus 是字节内部大规模实践沉淀,对外提供全链路 APM;APMPlus×CloudWeGo 打造“一站式开发与观测”;OTel Collector 组件化部署。volcengine.com+2火山引擎开发者社区+2 另有 BytedTrace 作为内部一体化可观测方案报道。 |
京东 / 京东物流 | 自研 APM(京东云 APM 产品线、金融/物流落地),分布式链路追踪在金融/物流场景大规模推行 | (公开材料更多聚焦业务/链路,不特指 eBPF 网络侧) | 京东云 APM、金融场景分布式追踪实践(SGM 等)、大规模实时监控+AIOps | 金融场景“分批接入、快速见效”,APM 与告警/认证/CMDB 体系打通;物流线 AIOps + APM 保障大促稳定。 |
美团 | CAT(自研开源 APM,日处理百 TB 级数据)+ 终端日志平台 Logan;还有“可视化全链路日志追踪”的体系文章 | (公开文更多在应用/日志/终端侧) | CAT、Logan、可视化链路日志方案(与 ELK 辅助) | CAT 深耕多年、规模化 APM 的代表;终端实时日志 Logan 提升客户端问题定位;对“日志→链路”可视化方法有系统沉淀。 |
滴滴 | 早期自研 DD-Falcon/夜莺(Nightingale) 体系覆盖监控与告警,含分布式调用链、异常检测、压测平台等整体可观测构件 | 有提到“网络/数据通道/日志平台”配合,但细节披露以平台化监控为主 | DD-Falcon/夜莺(Nightingale)+ ES/实时数据通道 + 可观测架构多阶段演进 | 公开演讲/文稿显示:从监控系统到异常检测、压测平台的全链路能力;夜莺作为分布式高可用监控系统在混合云/K8s 场景落地。pic.huodongjia.com+2知乎专栏+2 |
说明:NPM(网络观测)层的公开披露在国内通常更少,不少公司把网络侧能力融合在平台里(如流量证据、依赖拓扑、网格可视化等),但未必单独称“NPM”。如果要专看“网络/eBPF/流量侧”的公开国产案例,DeepFlow 在运营商/银行/云厂商的实践文章较多
公司 | APM(应用观测) | NPM / 网络侧 | 主体技术栈 / 组件 | 亮点与取舍 |
---|---|---|---|---|
Uber | Jaeger(自研并捐赠 CNCF;大规模分布式追踪) jaegertracing.io+1 | Mesh/边车与网络指标结合(公开资料以应用侧为主) | M3(超大规模指标平台)+ Jaeger + 自研采样与告警链路(uMonitor/Neris) Uber+3Uber+3M3+3 | “自研核心 + 开源输出”路线:百万级指标与大规模追踪并行,重采样与告警可扩展性。 |
Netflix | 以 Atlas 为主的运行时遥测,APM 由多组件协同(Tracing 常接 OTel/Jaeger/Tempo) netflix.github.io+2netflix.github.io+2 | Envoy/Istio 等网格遥测配合(公开资料多在指标/平台侧) | Atlas(维度时序、近实时运维洞察)+ Mesh 遥测接 OTel 后端 netflix.github.io+1 | “指标为王”的实时运营视角:极强的在线查询与维度切片能力,Tracing 后端可插拔。 |
以 OTel 标准为采集统一面(Cloud Operations/Stackdriver 体系) | Istio/Envoy 遥测 + 云探针(ThousandEyes 等为行业常见补充) | Monarch 星球级 TSDB(论文)+ OTel 采集 + Mesh 遥测 VLDB+1 | “标准化采集 + 超大规模时序库”:统一三信号语义,后端服务化运营。 | |
Meta(Facebook) | 内部一体化观测(公开论文偏指标) | 网络侧细节对外较少 | Gorilla 内存 TSDB(论文)作为核心指标基座 VLDB+1 | “指标压缩与近线价值”理念:高压缩、低延迟,强调近期数据的重要性。 |
Lyft | 基于 OTel/Jaeger 等开源链路 | Envoy(自研,后捐开源) 提供 L7 遥测/依赖拓扑 | Envoy + OTel/Jaeger(或 Tempo)链路后端 envoyproxy.io+1 | “以网格为基础设施”的观测:网络/应用边界自然打通。 |
Airbnb | 大量采用 Datadog(APM/告警/仪表) Datadog+1 | Datadog NPM/合规探针配合(公开分享以 APM/告警为主) | Datadog SaaS 平台(监控即代码、统一告警) Datadog | “SaaS 化省心”路线:工程团队聚焦业务,代价是规模化成本需精算。 |
SaaS 用户如 Slack/Shopify | 常见于 Datadog / New Relic / Dynatrace 组合(厂商公开案例) | NPM / Synthetics 结合 APM 使用 | 商用一体化平台 + OTel 接入 | 快速落地与运营省心,对数据量/留存的成本治理要求高。 |
Grafana 社区路线(Spotify 等) | OTel + Tempo(Trace) | Loki/Mimir + Cilium-Hubble(网络可视) | “开源拼装”:OTel → Tempo/Jaeger;Logs→Loki;Metrics→Mimir/Cortex;NPM→Hubble | “开源优先 + 成本可控”:需要更强的自运维与采样/留存策略。 |
区域 | APM 主线(应用可观测) | NPM 主线(网络/流量可观测) | 一体化趋势 |
---|---|---|---|
国内 | 阿里云 ARMS、自研 + OTel/SkyWalking;部分采用商用平台 | DeepFlow、Cilium/Hubble 在云原生里普及;运营商/金融偏爱流量侧证据链 | 更强调无侵入 eBPF + 统一数据面,兼顾合规与私有化落地。 |
国外 | 自研(Netflix Atlas、Uber M3)+ 开源(Jaeger/OTel)+ 商用(Datadog/Dynatrace/New Relic) | Envoy / Service Mesh + 流量遥测;NPM 与 APM 共同驱动 SLO | OTel 标准化采集成共识,后端/可视化自由拼装。 |
可观测性领域的主要数据类型包括指标、日志、追踪、事件、性能剖析以及网络元组,这些数据为 SLA、SLO 和 SLI 提供量化基础。它们共同构成对系统健康状况的多维度观察。
类型 | 目的 | 优势 | 常用工具 |
---|---|---|---|
指标 | 持续监控系统资源与性能 | 结构化、易聚合、查询高效 | Prometheus, CloudWatch |
日志 | 记录详细事件与错误 | 上下文丰富、可追溯 | ELK Stack, Loki |
追踪 | 展现请求的端到端路径 | 还原调用链路、分析延迟 | Jaeger, Zipkin |
事件 | 捕获状态变更 | 触发实时告警 | Kubernetes Events, PagerDuty |
性能剖析 | 分析代码级资源消耗 | 定位热点与瓶颈 | pprof, eBPF |
网络元组 | 识别网络会话与协议 | 精确流量分类 | NetFlow, DeepFlow |
SLA/SLO/SLI | 度量服务质量 | 统一服务级别标准 | 各类 SLO 平台 |
特性 | CBPF | eBPF |
---|---|---|
用途 | 数据包过滤 | 网络过滤、性能分析、安全监控等 |
指令集 | 简单,功能有限 | 功能强大,支持复杂逻辑 |
运行环境 | 网络数据包 | 多种挂载点(网络、系统调用等) |
验证器 | 无 | 严格的安全验证器 |
扩展性 | 差 | 强,支持用户态交互和多种映射类型 |
性能 | 高 | 接近 CBPF,有优化机制 |
维度 | 传统模式 | 基于 Agent 的采集模式 |
---|---|---|
流量采集方式 | 流量镜像或旁路设备 | eBPF/XDP 内核级采集 |
部署复杂度 | 需要交换机配置或旁路设备 | 只需在主机安装 Agent |
协议解析能力 | 通常仅支持 L3/L4 | 支持全面的 L7 协议解析 |
数据粒度 | 粗粒度流量统计 | 细粒度流日志与性能指标 |
元数据关联 | 需手动关联容器、进程信息 | 自动关联主机、容器与 Kubernetes 元数据 |
性能开销 | 镜像可能带来带宽占用 | 内核级采集开销极低 |
动态环境支持 | 对 Kubernetes 等动态环境支持较弱 | 原生适配动态环境,扩展性强 |
安全性 | 镜像存在数据泄露风险 | 数据在内核空间处理,安全性更高 |
应用系统故障排查需要从应用层到网络层系统性地进行分析。以下是结合应用指标、网络指标和日志分类的详细排查流程:
目标:确定是否有内部错误(服务端异常)或客户端发送无效请求。
步骤:
查看应用日志是否有错误堆栈(如 NullPointerException、SQL 错误)。
排查 HTTP 500 或其他 5xx 错误相关的记录。
示例:
ERROR: Database connection failed for query: SELECT * FROM users WHERE id=123
查看是否有 HTTP 400 错误(如请求格式错误)。
示例:
WARN: Invalid input received: missing field 'username'
排查要点:
数据库、缓存系统、消息队列等外部依赖是否正常:
目标:检查服务间调用是否正常,定位异常的服务节点。
步骤:
查看调用日志是否有 HTTP 503、502 等状态码。
示例:
2024-11-22 10:00:01 GET /api/orders/12345 Status: 503
目标:确认服务的健康状况。
步骤:
curl
或 ping
测试服务接口的可用性。目标:排查网络连接问题,确认流量是否正常到达。
步骤:
连接失败(如大量 RST 包)。
丢包率是否过高。
示例:
SrcIP: 192.168.1.10 DstIP: 10.0.0.5 Protocol: TCP Flags: RST
目标:判断是否为网络问题导致的故障。
步骤:
ping
或 traceroute
确认网络延迟和链路状态。tcpdump
或 Wireshark
捕获数据包,分析是否有丢包、RST 等异常。ERROR: User authentication failed due to missing token.
markdown 复制代码
Service A -> Service B [Timeout]
TCP Retransmissions detected: 10% packets lost.
故障现象 | 可能原因 | 排查方法 |
---|---|---|
页面加载缓慢 | 服务响应时间长、数据库查询慢、网络延迟高 | 检查响应时间指标,分析慢查询日志,验证网络延迟和丢包。 |
HTTP 500 错误 | 服务端代码错误、资源耗尽、依赖服务不可用 | 查看应用日志中的异常堆栈,检查系统资源使用率,验证外部依赖服务状态。 |
HTTP 503 错误 | 服务过载或正在维护 | 检查系统资源使用情况,查看调用日志是否有过载信息,确认流量是否超出服务能力。 |
HTTP 404 错误 | 请求资源不存在 | 查看客户端请求路径是否正确,分析应用日志是否有未处理的资源。 |
无法连接服务 | 网络中断、DNS 解析失败、服务未启动 | 检查网络流日志,测试目标服务连接状态,验证 DNS 解析。 |
请求被中断或取消 | 客户端刷新、网络不稳定 | 查看客户端错误日志,分析网络连接稳定性。 |
通过系统性的排查方法,可以快速定位故障的来源并采取对应的解决措施。
应用请求关联指标可以帮助我们深入了解系统性能、稳定性和用户体验。通过对这些指标的分析,可以快速定位问题并采取相应的改进措施。以下是针对关键指标的详细排查方法。
目标:识别导致应用响应时间过长的原因,优化用户体验。
步骤:
解决方案:
目标:确保应用所依赖的外部服务(如数据库、缓存、第三方 API)运行正常。
步骤:
解决方案:
目标:区分错误来源,以便采取针对性的解决措施。
服务端异常(5xx):
客户端异常(4xx):
排查方法:
解决方案:
目标:通过分析 HTTP 状态码,了解系统运行状况和潜在问题。
常见状态码:
分析步骤:
解决方案:
目标:确保系统有足够的计算和存储资源,防止性能下降或服务中断。
监控内容:
排查步骤:
解决方案:
目标:发现并修复程序中未正确释放的资源,防止长期运行导致的资源耗尽。
常见的资源泄漏类型:
检测方法:
解决方案:
try-finally
或 try-with-resources
)。目标:通过分析用户的使用习惯和行为,提升用户满意度和产品竞争力。
关键指标:
分析步骤:
解决方案:
目标:确保应用的核心功能在任何时候都可用,提升用户满意度。
检查内容:
排查步骤:
解决方案:
目标:评估系统在高并发访问下的性能,找出潜在的瓶颈。
测试流程:
解决方案:
目标:确保系统能够随着业务增长而平滑扩展,满足未来需求。
评估内容:
评估步骤:
解决方案:
通过对上述指标的分析和排查,可以全面了解应用的运行状况,及时发现和解决问题,保障系统的稳定性和用户满意度。定期监控和优化这些关键指标,对于持续提升应用性能和竞争力至关重要。
在网络性能和可靠性方面,关键指标的监控和分析至关重要。通过对这些指标的深入了解和排查,可以有效提升网络服务质量,确保应用系统的稳定运行。以下是优先级最高的网络指标,这些指标直接影响应用的可用性、性能和用户体验,适合在网络性能优化中重点关注:
指标 | 定义 | 重要性 | 优先级 |
---|---|---|---|
延迟 | 数据包从源到目的地传输所需的时间。 | 高延迟会影响实时应用(如视频会议、在线游戏)以及 API 的响应速度。 | 高 |
丢包率 | 传输中丢失数据包的比例。 | 高丢包率会导致重传或数据丢失,影响应用性能和用户体验。 | 高 |
带宽利用率 | 网络已使用带宽占总带宽的百分比。 | 带宽不足可能导致网络拥塞,带宽利用率低可能是资源浪费的信号。 | 中等 |
网络抖动 | 连续数据包之间延迟的变化幅度。 | 高抖动会对实时服务(如 VoIP 和视频流)造成明显影响,可能导致卡顿或失真。 | 中等 |
网络可用性 | 网络在特定时间内可正常运行的比例。 | 网络中断会导致服务不可用,对高可靠性应用影响严重。 | 高 |
重传率 | 因丢包或错误而需要重传的数据包比例。 | 重传增加了网络负载,降低了传输效率,可能进一步加剧延迟和拥塞。 | 中等 |
TCP 连接时间 | 建立 TCP 连接所需的时间。 | 长连接时间会影响首次请求的响应速度,特别是需要频繁建立连接的应用。 | 中等 |
DNS 查询时间 | 域名解析到 IP 地址所需的时间。 | 慢速的 DNS 查询会延长应用的请求启动时间,影响整体性能。 | 中等 |
HTTP 请求成功率 | 成功的 HTTP 请求占总请求的比例。 | HTTP 请求失败会直接导致功能不可用或用户体验下降。 | 高 |
以下是对这些关键网络指标的详细分析和排查方法。
目标:实时监控网络带宽的使用情况,确保网络资源被合理利用,避免带宽瓶颈。
步骤:
解决方案:
目标:及时发现和处理异常流量,防止网络拥塞和安全问题。
步骤:
解决方案:
目标:降低网络延迟,提高数据传输效率,提升用户体验。
步骤:
ping
、traceroute
等工具测量从源到目的地的延迟。解决方案:
目标:理解地理位置对网络延迟的影响,针对性地优化跨地域通信。
分析:
解决方案:
目标:确保网络链路的可靠性,降低数据包丢失率。
步骤:
ping
命令发送多个 ICMP 包,统计丢包率。解决方案:
目标:检查网络设备的健康状况,排除因设备故障导致的丢包。
步骤:
解决方案:
目标:降低网络抖动对实时应用(如 VoIP、视频会议)的影响,保证服务质量。
分析:
检测方法:
解决方案:
目标:通过网络优化,提高整体网络的稳定性,减少抖动。
措施:
目标:通过冗余设计,提升网络的可靠性,防止单点故障。
策略:
实现方法:
目标:确保在故障发生时,系统能够自动切换到备用路径或设备,最小化服务中断。
步骤:
解决方案:
目标:通过拥塞控制,降低数据包重传率,提升网络效率。
分析:
措施:
目标:优化传输协议和参数,减少重传,提升传输性能。
策略:
解决方案:
目标:降低 TCP 连接建立的时间,提升用户访问速度。
分析:
检测方法:
解决方案:
目标:提升服务器处理连接的能力,避免成为瓶颈。
措施:
目标:降低 DNS 查询时间,加快域名解析速度。
措施:
目标:通过缓存机制,加快 DNS 解析,提高查询效率。
策略:
注意事项:
目标:确保服务器运行正常,提升 HTTP 请求的成功率。
措施:
解决方案:
目标:处理网络异常情况,确保 HTTP 请求的可靠传输。
措施:
解决方案:
在 TCP 协议中,300ms内没有收到 ACK 这种情况通常发生在以下两个阶段之一:连接建立阶段 或 数据传输阶段。
这是 TCP 的三次握手过程,用于建立可靠的连接。
SYN
和
ACK
标志来确认连接的进展。SYN
后,等待接收端返回 SYN+ACK
确认。SYN
请求建立连接。SYN+ACK
。ACK
,连接建立完成。SYN
或 SYN+ACK
没有被成功接收或返回,则会进入超时逻辑。在连接建立后,双方通过 TCP 数据包进行数据传输,每个数据段都需要 ACK 确认。
阶段 | ACK 的作用 | 300ms 超时的可能性 |
---|---|---|
连接建立阶段 | 确保三次握手成功建立连接 | 网络延迟、丢包、目标主机不可达。 |
数据传输阶段 | 确认接收数据包,并告知发送端继续发送下一数据段 | 数据包或 ACK 丢失、接收端延迟、网络抖动。 |
通过对网络关键指标的深入分析和有效排查,可以显著提升网络的性能和可靠性。定期监控这些指标,及时发现并解决问题,对于保障应用系统的正常运行和用户满意度至关重要。
TCP 时延相关指标表
指标 | 定义 | 阶段 | 影响因素 | 区别 |
---|---|---|---|---|
TCP 连接时延 | 三次握手所需时间 | 连接建立阶段 | 网络延迟、服务器响应速度 | 测量连接建立效率,不涉及后续数据传输。 |
RTT | 数据包从源到目的地再返回的总时间 | 全过程 | 网络物理距离、拥塞 | 网络底层延迟的综合反映,是其他时延的基础。 |
初始时延 | 从请求到收到首字节的时间(TTFB) | 连接建立 + 数据开始 | TCP 握手时延、服务器响应 | 包括了 TCP 握手和服务器处理时间,反映用户可感知的响应延迟。 |
数据传输时延 | 从开始发送到完全接收数据的时间 | 数据传输阶段 | 带宽、窗口大小、丢包重传 | 强调传输阶段性能,与握手阶段无关。 |
抖动 | 数据包到达时间的波动性(Jitter) | 全过程 | 网络稳定性 | 关注时间一致性,而非单次时延,主要影响实时性要求较高的应用。 |
重传时延 | 因丢包重传导致的额外延迟 | 数据传输阶段 | 丢包率、网络质量 | 表示丢包的代价,直接影响传输性能。 |
慢启动时延 | TCP 连接初期,数据传输受限所需的时间 | 数据传输阶段 | 窗口大小、网络拥塞 | 仅影响传输初期,与稳定阶段性能无关,适用于大文件传输分析。 |
TCP 建连异常相关指标表
指标 | 定义 | 异常阶段 | 常见原因 | 区别 |
---|---|---|---|---|
TCP 连接失败率 | 未完成三次握手的连接比例 | 全过程 | 网络丢包、服务器未监听、超时 | 反映总体连接失败的宏观指标,是性能排查的起点。 |
TCP 超时率 | 建连超时的比例 | 全过程 | 高延迟、丢包重传、服务器过载 | 专注超时问题,通常与网络延迟或服务器负载有关。 |
TCP 重试次数 | 建连中因丢包需要重传的次数 | 全过程 | 丢包率高、拥塞、路由问题 | 表示网络传输可靠性,过高可能导致建连失败或性能下降。 |
SYN 丢包率 | 客户端发送的 SYN 包未收到响应的比例 | 第一步 | 链路丢包、防火墙拦截 | 专注建连的第一步,反映初始连接的成功率。 |
SYN-ACK 失败率 | 服务端返回的 SYN-ACK 包未到达客户端的比例 | 第二步 | 服务端丢包、防火墙或 NAT 问题 | 分析服务端到客户端方向的网络问题。 |
RST 包率 | 建连过程中收到 RST 包的比例 | 全过程 | 服务端拒绝连接、防火墙或策略问题 | 表明服务端主动中断连接,可能涉及配置错误或策略限制。 |
建连延迟 | 完成三次握手的时间 | 全过程 | 高 RTT、丢包重传 | 偏向时延分析,高延迟可能导致连接超时或多次重传。 |
拒绝连接率 | 被服务器拒绝的连接比例 | 全过程 | 服务器端口未监听、超出连接限制 | 表明服务器端主动拒绝连接的情况。 |
防火墙拦截率 | 数据包被防火墙拦截的比例 | 全过程 | 防火墙规则错误或策略限制 | 特指中间设备干预导致的连接失败。 |
NAT 超时率 | 因 NAT 转换失败导致建连异常的比例 | 全过程 | NAT 表溢出、超时配置不当 | 特指 NAT 相关问题,区别于常规的丢包或超时原因。 |
超时类型 (中文) | 状态 (英文) | 默认值(Linux) | 默认值(Windows) | 默认值(macOS) |
---|---|---|---|---|
初始 RTO | Initial RTO (Retransmission Timeout) | 200ms - 1秒 | 300ms | 1秒 |
最大重传超时 | Maximum Retransmission Timeout | 13-30分钟 | 240秒 | 9分钟 |
Keepalive 超时 | Keepalive Timeout | 7200秒(2小时) | 7200秒(2小时) | 7200秒(2小时) |
连接建立超时 | Connection Establishment Timeout | 63秒 | 21秒 | 75秒 |
连接重置超时 | Connection Reset Timeout | 0秒 | 0秒 | 0秒 |
流日志记录网络层的元数据,如源 IP、目标 IP、端口、协议和流量大小,用于分析网络流量和连接问题。
数据包日志捕获网络中的详细数据包信息,包括 MAC 地址、IP 地址、端口和负载内容,用于深入分析网络问题。
记录服务间调用或客户端与服务间的调用详情,包括请求时间、路径、参数和响应时间。
通过调用日志中的响应时间和错误率,监控接口性能,定位瓶颈。
记录应用运行中的详细错误信息,包括异常堆栈和出错时的上下文。
记录应用内部的关键业务事件(如订单状态、用户登录)和逻辑流程。
日志分析的排查思路可以按照以下顺序进行:应用日志 -> 接口调用日志 -> 流日志,逐步深入定位问题。
/api/v1/orders
请求。order-service
超时。大分类 | 日志类型 | 对应层面 | 主要内容 | 用途 | 典型工具或技术 |
---|---|---|---|---|---|
应用日志 | 应用日志 | 应用层(业务逻辑) | - 应用程序内部运行时的详细信息(如业务处理流程、变量状态、异常堆栈)。 | - 排查应用内部逻辑错误。 - 记录业务事件(如订单处理、用户登录)。 - 调试和优化代码。 |
Log4j、SLF4J、ELK Stack、Fluentd |
应用日志 | HTTP 访问日志 | 应用层(HTTP 协议) | - HTTP 请求和响应:方法(GET/POST)、路径、状态码、响应时间、用户代理。 | - 分析网站流量。 - 监控接口性能和错误率。 |
Apache Logs、Nginx Access Logs |
应用日志 | DNS 查询日志 | 应用层(DNS 协议) | - DNS 请求记录:查询域名、查询类型、响应时间。 - 是否缓存命中、查询结果(成功或失败)。 |
- 分析域名解析性能。 - 检测恶意域名访问或 DNS 放大攻击。 |
BIND DNS Logs、DNSCrypt Proxy Logs |
应用日志 | TLS 握手日志 | 会话层(TLS 协议) | - TLS 握手的详细信息:握手阶段、加密算法、证书验证结果。 | - 检测加密通信的失败原因(如证书过期、算法不匹配)。 - 分析加密通道的安全性。 |
OpenSSL Logs、Wireshark、SSL Labs Reports |
服务日志 | 调用日志 | 服务层(接口层) | - 服务间或客户端与服务间的调用详情(如请求时间、参数、状态码、响应时间)。 | - 排查接口错误或调用失败。 - 分析接口性能(如响应时间和错误率)。 - 监控服务健康状况。 |
API Gateway Logs、Nginx Access Logs、Application APM Tools |
网络日志 | 流日志 | 网络层/传输层 | - 网络流量的元数据(如 IP 地址、端口、协议、流量大小)。 - 不包含具体的传输内容(仅元信息)。 |
- 分析网络流量。 - 排查网络连接问题(如丢包、延迟)。 - 安全事件监控(如检测异常访问)。 |
AWS VPC Flow Logs、Azure NSG Flow Logs、NetFlow、sFlow |
网络日志 | 数据包日志 | 链路层/网络层 | - 数据包的详细信息:MAC 地址、IP 地址、端口、协议标识。 - 数据包的头部和负载内容。 |
- 深入分析网络问题(如 MTU 不匹配、路由环路)。 - 网络入侵检测。 |
Wireshark、Tcpdump |
网络日志 | TCP 连接日志 | 传输层 | - TCP 连接的状态:SYN、ACK、FIN、RST。 - 重传次数、握手失败。 |
- 分析连接状态(如建立失败)。 - 排查丢包或重传问题。 |
Wireshark、Nmap |
应用日志 | SMTP 日志 | 应用层(SMTP 协议) | - 邮件发送和接收的状态:邮件来源、目标、传输状态、延迟、错误代码。 | - 分析邮件服务器性能。 - 检测垃圾邮件或邮件服务异常。 |
Postfix Logs、Exim Logs |
应用日志 | VPN 日志 | 会话层/网络层 | - VPN 连接的状态:握手时间、加密方式、连接 IP、断开原因。 |
ping
或 traceroute
检测网络链路状态。场景:用户反馈应用无法访问,测试发现域名解析失败。 解决步骤: 1. 使用
nslookup
或 dig
检查 DNS 配置和解析结果。 2.
排查 DNS 服务器状态,确认是否可用。 3. 更新 DNS 缓存,或临时切换到其他
DNS 服务(如 8.8.8.8)。 4. 检查网络路径中是否存在拦截(如防火墙或 NAT
问题)。
场景:批量处理任务时,应用性能急剧下降,分析发现磁盘 IO 过高。
解决步骤: 1. 使用 iostat
或 iotop
工具查看磁盘 IO 状态,确认读写是否过于频繁。 2.
检查文件系统是否存在碎片,或日志文件是否持续增长。 3. 对 IO
密集型任务进行限速或分批处理,减轻瞬时压力。 4. 升级磁盘性能(如
SSD)或优化数据访问逻辑(如缓存)。
场景:数据库查询速度变慢,影响整体服务响应。 解决步骤: 1. 使用数据库自带的查询分析工具(如 EXPLAIN)定位慢查询。 2. 检查索引是否存在或合理,避免全表扫描。 3. 查看数据库服务器的资源使用情况,是否达到瓶颈。 4. 使用分库分表或读写分离的方式优化查询效率。
场景:消息队列积压严重,消费者处理速度明显下降。 解决步骤: 1. 检查消息队列的队列长度和吞吐量,确认瓶颈点。 2. 查看消费者的消费速率和日志,是否存在逻辑错误或阻塞。 3. 增加消费者实例或优化消费逻辑,提升处理能力。 4. 对非关键消息启用丢弃或延迟消费策略,避免影响核心业务。
场景:用户反馈访问服务延迟明显增加,分析发现网络延迟异常。 解决步骤:
1. 使用 ping
或 traceroute
工具确认延迟节点或链路。 2. 检查网络路由是否发生变更,或是否存在拥塞点。
3. 使用 SD-WAN 或 MPLS 等技术优化网络路径。 4. 针对跨区域访问,启用 CDN
加速或服务节点本地化。
场景:云环境中的服务稳定性下降,监控显示存在高丢包率。 解决步骤: 1. 使用云平台提供的网络监控工具查看丢包位置(如 VPC 内或跨区域)。 2. 排查相关网络设备(如网关、负载均衡器)的日志和健康状态。 3. 检查服务端和客户端的 MTU 设置,避免分片问题。 4. 增加链路冗余,或切换到不同区域的节点降低丢包影响。
通过对这些典型案例的分析和总结,可以为实际问题排查提供清晰的流程和有效的解决方案,同时为提升系统可靠性积累宝贵经验。
结合原有的故障排查章节,本节总结了从客户端请求到服务端响应的完整排查思路,并梳理了应用指标、网络指标和日志分析的要点:
维度 | 关注重点 | 常用工具 | 典型问题示例 |
---|---|---|---|
应用指标 | 响应时间、错误率、资源使用、吞吐量 | APM、监控面板、性能测试工具 | 慢查询、依赖服务超时 |
网络指标 | 延迟、丢包率、带宽利用率、重传率 | NetFlow、ping、traceroute | 链路拥塞、跨区域访问延迟 |
日志分析 | 应用日志、调用日志、网络流/数据包日志 | ELK、Jaeger、Tcpdump | 错误堆栈、HTTP 4xx/5xx 等 |
graph TD
subgraph Client
A[Vector Agent]
end
subgraph Transport
A --> B[Unified API (REST/gRPC/OTel)]
end
subgraph Storage
B --> C1[PostgreSQL (TimescaleDB + JSONB)]
B --> C2[ClickHouse (OLAP 聚合)]
end
subgraph Query
C1 --> D[Grafana / SQL API]
C2 --> D
end
使用 Go / Rust 编写 Ingest 网关: - /write/metrics
→
TimescaleDB - /write/logs
→ ClickHouse -
/schema/register
→ 写入 table_registry
元数据表
CREATE TABLE metrics_events (
time TIMESTAMPTZ NOT NULL,
app TEXT,
host TEXT,
labels JSONB,value DOUBLE PRECISION,
trace_id TEXT,level TEXT
);SELECT create_hypertable('metrics_events', 'time');
CREATE TABLE logs_events (
timestamp DateTime,
app String,
host String,
trace_id String,
message String,Nested(k String, v String)
labels = MergeTree()
) ENGINE PARTITION BY toYYYYMMDD(timestamp)
ORDER BY (timestamp, app);
CREATE TABLE table_registry (
PRIMARY KEY,
table_name TEXT schema JSONB,
DEFAULT now()
created_at TIMESTAMPTZ );
注册示例:
{
"columns": [
{"name": "time", "type": "timestamp"},
{"name": "value", "type": "double"},
{"name": "labels", "type": "jsonb"}
]
}
[sources.prom]
type = "prometheus_scrape"
endpoints = ["http://localhost:9100/metrics"]
[sources.logs]
type = "journald"
[transforms.jsonify_logs]
type = "remap"
inputs = ["logs"]
source = '''
.structured = parse_json!(string!(.message))
'''
[sinks.pg]
type = "postgresql"
inputs = ["prom", "jsonify_logs"]
database = "metrics"
endpoint = "postgresql://user:pass@pg:5432/metrics"
table = "observability_events"
mode = "insert"
compression = "zstd"
[sinks.ch]
type = "clickhouse"
inputs = ["jsonify_logs"]
endpoint = "http://clickhouse:8123"
database = "default"
table = "logs"
compression = "gzip"
SELECT time_bucket('1 minute', event_time) AS ts, COUNT(*)
FROM observability_events
WHERE node = $__variable_node
AND raw->>'source' = $__variable_source_type
AND $__timeFilter(event_time)
GROUP BY ts
ORDER BY ts;
SELECT node, count() AS total
FROM logs
WHERE timestamp >= $__from AND timestamp <= $__to
GROUP BY node
ORDER BY total DESC
LIMIT 5;
阶段 | 特性 | 说明 |
---|---|---|
单节点一体化 | 所有组件运行在一台主机 | 适合 PoC / 开发环境 |
多副本集群 | API、PG、CH 分别部署为独立节点,可接入负载均衡 | 支持横向扩展与高可用 |
存算分离 | 引入 Kafka 等缓冲层,PG/CH 采用分布式与 Replication | 写入与查询解耦,适合大规模场景 |
目标类别 | 说明 |
---|---|
💾 吞吐能力 | 是否能支撑 50K+ IOPS 持续写入并在高峰期达到 100K/s |
🧠 查询能力 | 事件查询/统计分析响应稳定在 100~500ms |
🔁 分层写入正确性 | 标签/类型是否正确路由至 PostgreSQL 与 ClickHouse |
🔐 数据一致性 | PostgreSQL 中 Trace、事件无漏写 |
📈 可观测性 | Vector/PG/CH 与系统资源均可监控 |
数据源模拟
工具 | 用途 |
---|---|
vector generator / log-generator | 模拟高负载日志流 |
OpenTelemetry demo | 生成 Trace 数据 |
prometheus-testgen | 生成 Metrics 样本 |
写入目标部署
系统 | 推荐配置 |
---|---|
PostgreSQL | 16+ + TimescaleDB + pg_partman |
ClickHouse | 24.4+ + ReplicatedMergeTree |
Vector | 支持 transforms 路由、sink 至 PG/CH |
监控组件 | node_exporter、pg_exporter、vector internal、CH monitor |
项目 | 方法 | 期望 |
---|---|---|
最大持续写入 | 持续向 Vector 发送 JSON logs @ 50K/s,观察是否丢包 | ACK latency < 500ms |
高峰瞬时写入 | 峰值 100K/s 持续 1 min,观察 PG/CH 报错情况 | 无错误、吞吐稳定 |
网络抖动模拟 | 通过 tc 注入延迟/丢包,观察重试 |
数据无丢失 |
验证点 | 检查项 |
---|---|
Trace 事件 → PostgreSQL | 是否按时间/traceID 正确分区落表 |
普通日志 → ClickHouse | 是否按标签写入 MergeTree 表 |
异常标签 | 是否触发 fallback/dead-letter |
类型 | 查询目标 | 预期性能 |
---|---|---|
PostgreSQL | 精确事件 → TraceID 查询 | <200ms |
ClickHouse | 日志聚合 → app error rate | <1s |
联合 | Trace + 日志聚合视图 | <1.5s |
组件 | 监控项 | 期望值 |
---|---|---|
Vector | CPU < 300m、Mem < 300MB | ✅ |
PostgreSQL | IOPS < 40K / WAL flush latency | ✅ |
ClickHouse | Merge 负载、后台线程瓶颈 | ✅ |
for i := 0; i < 100000; i++ {
:= map[string]interface{}{
body "app": "auth", "trace_id": fmt.Sprintf("t-%d", i), "message": "log",
"ts": time.Now().UnixNano() / 1e6,
}
, _ := json.Marshal(body)
jsonBody.Post("http://localhost:9000/my-pg-sink", "application/json", bytes.NewBuffer(jsonBody))
http}
验证目标 | 方案 | 期望指标 |
---|---|---|
Vector 重启/崩溃 | 高负载写入时重启 Vector,观察数据补写 | 无重复或漏写 |
PG/CH 停机 | 短暂下线数据库,观察 Vector 缓冲 | 自动重试,恢复后数据一致 |
网络断连恢复 | 使用 netem 模拟断网,检查重连 | 不丢失、不时序异常 |
验证目标 | 方案 | 期望指标 |
---|---|---|
指标完备性 | 检查 Vector、PG、CH、OS 指标 | 覆盖率 > 95% |
告警规则有效性 | 模拟 CPU/延迟异常触发告警 | 告警及时 |
日志追踪 | 通过集中日志跟踪关键事件 | 故障可快速定位 |
维度 | 成功判定 |
---|---|
写入链路 | ≥ 95% 写入无丢失,ACK latency 稳定 |
数据正确性 | PG 与 CH 数据能联查对齐,时间戳正确 |
系统资源 | 单节点 PG/CH/Vector CPU < 50%,无 OOM |
查询性能 | 常用 Trace 查询 <500ms |
异常处理 | 标签异常可自动 fallback 或告警记录 |
通过 PostgreSQL + ClickHouse 的分层写入方案,可以在保证实时查询能力的同时实现高吞吐归档和聚合分析,为可观测性平台提供灵活、可扩展的存储基础。
# 安装目录
/opt/metrics-agent/
├─ node_exporter
├─ process_exporter
└─ process_exporter.yml
# 日志目录
/var/log/atop/
/var/log/sysstat/
# 专用用户
useradd --system --no-create-home --shell /usr/sbin/nologin metrics
cd /opt/metrics-agent
curl -L https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz \
| tar xz --strip-components=1 -C /opt/metrics-agent --wildcards '*/node_exporter'
/etc/systemd/system/node-exporter.service
[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
User=metrics
Group=metrics
ExecStart=/opt/metrics-agent/node_exporter \
--web.listen-address=127.0.0.1:9100 \
--collector.processes \
--collector.filesystem.ignored-mount-points="^/(sys|proc|dev|run|var/lib/docker/.+)($|/)"
Restart=always
[Install]
WantedBy=multi-user.target
绑定 127.0.0.1,避免直接暴露公网,建议 Prometheus 通过内网采集或加反代。
cd /opt/metrics-agent
curl -L https://github.com/ncabatoff/process-exporter/releases/download/v0.7.10/process-exporter-0.7.10.linux-amd64.tar.gz \
| tar xz --strip-components=1 -C /opt/metrics-agent --wildcards '*/process-exporter'
/opt/metrics-agent/process_exporter.yml
process_names:
- name: "nginx"
exe: ["^/usr/local/openresty/nginx/sbin/nginx$"]
comm: ["^nginx$"]
cmdline: ["nginx"]
- name: "redis"
exe: [".*/redis-server$"]
comm: ["^redis-server$"]
cmdline: ["redis-server"]
- name: "postgres"
exe: [".*/postgres$", ".*/postmaster$"]
comm: ["^postgres$", "^postmaster$"]
cmdline: ["postgres", "postmaster"]
- name: "xcontrol-server"
exe: ["^/usr/bin/xcontrol-server$"]
comm: ["^xcontrol-server$"]
cmdline: ["xcontrol-server"]
- name: "other"
cmdline: [".+"]
/etc/systemd/system/process-exporter.service
[Unit]
Description=Prometheus Process Exporter
After=network.target
[Service]
User=metrics
Group=metrics
ExecStart=/opt/metrics-agent/process-exporter \
--config.path=/opt/metrics-agent/process_exporter.yml \
--web.listen-address=127.0.0.1:9256
Restart=always
[Install]
WantedBy=multi-user.target
apt-get update
apt-get install -y atop sysstat
# sysstat: 每分钟采样,保留30天
sed -ri 's/^ENABLED=.*/ENABLED="true"/' /etc/default/sysstat
sed -ri 's/^HISTORY=.*/HISTORY=30/' /etc/default/sysstat
echo '* * * * * root sa1 60 1' > /etc/cron.d/sysstat
systemctl enable --now sysstat
# atop: 每分钟采样,保留30天
sed -ri 's/^LOGINTERVAL=.*/LOGINTERVAL=60/' /etc/default/atop || true
sed -ri 's/^LOGGENERATIONS=.*/LOGGENERATIONS=30/' /etc/default/atop || true
systemctl enable --now atop
回放命令
atop -r /var/log/atop/atop_$(date +%Y%m%d)
sar -u -f /var/log/sysstat/sa16 # 16日的CPU历史
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['<vm-ip>:9100']
- job_name: 'process'
static_configs:
- targets: ['<vm-ip>:9256']
✅ 最终效果: - 在线:Prometheus + Grafana → 时序趋势 & 告警 - 离线/断联:atop/sysstat → 回放事后诊断 - 可扩展:如需应用级指标,可加 redis_exporter、postgres_exporter、nginx-lua-prometheus
Vector 可以作为统一的采集出口,将系统、进程、网络和日志数据汇聚后再转发到不同的可观测性后端。
示例链路:
node_exporter ─┐
process_exporter ─┤
DeepFlow Agent ──▶ Vector Agent ──▶ Loki
journald/syslog ─┘ ├─▶ Prometheus Remote Write
└─▶ Tempo
prometheus_scrape
用于拉取
node_exporter、process-exporter
指标;journald
/file
采集系统与 DeepFlow
日志。remap
统一标签,如把
instance
改为 host
,补充业务标签。Vector 支持将配置拆分为多个文件,主配置通过 includes
统一加载:
/etc/vector/
├── vector.yaml
├── sources/
│ ├── node_exporter.yaml
│ ├── process_exporter.yaml
│ └── journald.yaml
├── sinks/
│ ├── prometheus.yaml
│ └── loki.yaml
└── transforms/
└── tags.yaml
主配置 vector.yaml
data_dir: /var/lib/vector
includes:
- /etc/vector/sources/*.yaml
- /etc/vector/sinks/*.yaml
- /etc/vector/transforms/*.yaml
示例 source/sink 片段
# sources/node_exporter.yaml
sources:
node_exporter:
type: prometheus_scrape
endpoints: ["http://localhost:9100/metrics"]
scrape_interval_secs: 15
# sinks/prometheus.yaml
sinks:
prometheus_out:
type: prometheus_remote_write
inputs: ["add_tags"]
endpoint: "http://vm.example.com/api/v1/write"
拆分后可独立修改某个采集器配置,便于模块化维护和热更新。
Vector 在高负载场景中通过多层保护减少数据丢失:
机制 | 说明 |
---|---|
背压控制 | 当下游拥塞时暂停上游读取,防止爆仓 |
缓冲策略 | 支持内存或磁盘缓冲,when_full = "block"
默认阻塞而非丢弃 |
重试与限流 | 对 Loki、Prometheus 等 sink 内置重试与 backoff,支持
rate_limit |
降级策略 | drop_on_full = false ,尽量保留数据 |
自监控指标 | /metrics 暴露
events_dropped_total 、buffer_overflows_total
等指标供告警 |
特性/组件 | node_exporter | process-exporter | DeepFlow Agent | Vector Agent |
---|---|---|---|---|
安装体积 | <20MB | <20MB | ≈70–100MB | ≈70MB |
资源占用 | 极低 | 低 | 中等(依赖 eBPF) | 低~中,可限内存 |
采集维度 | 主机资源 | 进程资源 | 网络四/七层 | 指标、日志、链路 |
输出能力 | Prometheus | Prometheus | DeepFlow Collector | Prometheus、Loki、Tempo 等 |
可靠性 | 无背压 | 无背压 | 重试有限 | 背压 + 缓冲 + 重试 |
Vector 在可靠性、可扩展性与自观测能力上相较 DeepFlow Agent 更为成熟,后者适合作为网络事件探针。
yaml process_names: - name: "deepflow-agent" cmdline: ["deepflow-agent"] - name: "clickhouse" cmdline: ["clickhouse-server"]
为了在后端构建统一、弹性、低成本的可观测平台,可按数据类型选用以下组件:
vmagent
或 Vector
远程写入,也可通过 otel-collector 接入 OpenTelemetry Metrics。数据类型 | 后端存储 | 采集/转发组件 | 说明 |
---|---|---|---|
Metrics | VictoriaMetrics | vmagent / Vector | 远程写入并归档到对象存储 |
Logs | Loki | Vector | 按小时本地留存,按日归档到 S3 |
Traces | Tempo | otel-collector / Vector | 可按需采样与压缩 |
结构化数据 | PostgreSQL (+Timescale) | 应用或 ETL | 用于业务事件与分析 |
通过 Vector 构建统一采集出口,可在保证稳定性的同时整合指标、日志、链路与结构化数据。DeepFlow Agent 专注网络可观测,结合推荐的后端存储组件,可形成覆盖系统到业务的完整可观测体系。
线 I/O 面交给 OpenObserve(OO),治理/知识面沉到 PostgreSQL 栈(Timescale + AGE + pgvector)。保留明细在 OO,只把聚合、摘要、索引与证据链写回 PG:既省钱、又好查、也好演进。
本文落地一套「全栈可观测」数据库设计:明细进 OO,PG 仅存 12 张核心表(维度、定位符、指标 1m、服务调用 5m、日志指纹/计数、拓扑时态、知识库、事件/证据),并用 AGE 维护“当前服务级调用图”。给出可直接执行的 DDL、保留与压缩策略、典型查询与接入流程。
维度(2):dim_tenant
、dim_resource
定位符(1):oo_locator
(对象存路径 +
时间窗 + 查询 hint)
聚合(3):metric_1m
、service_call_5m
、log_pattern_5m
;
指纹(1):log_pattern
拓扑(1):topo_edge_time
(边 +
有效期)
知识(2):kb_doc
、kb_chunk
(HNSW
向量索引)
事件(2):event_envelope
、evidence_link
图(AGE):仅维护“服务级调用图”的活跃子图(10 分钟窗口)。
注:日志明细、trace span、指标原始点位 不入 PG,统一留在 OO。
dim_tenant
:租户/域;用 code
做业务唯一键。dim_resource
:统一资源 URN(如
urn:k8s:svc:ns/name
),含环境/区域/标签。策略:
type
、labels
建索引(B-Tree +
GIN),支撑过滤与聚合。tenant_id
分片路由。oo_locator
:只存
对象存路径、时间窗、查询
hint,作为“回查线索”。策略:
sample_ref
关联,形成“摘要 →
原文”的证据链。metric_1m
:按资源、指标名保 avg/max/p95
常用统计,Timescale Hypertable。策略:
(resource_id, metric, bucket desc)
+ labels
GIN。service_call_5m
:A→B 的
rps/err_rate/p50/p95
,主键含窗口/租户/边端点。用途:
策略:留存 365 天,适配容量评估与 SLO 分析。
log_pattern
:指纹模板库(去重 + 样例 + 严重级 + 抽取
schema),pg_trgm
支持模糊。log_pattern_5m
:每 5
分钟的计数与错误计数;不存明细。策略:
sample_ref
反查 OO 原文;topo_edge_time
:边 + 有效期
tstzrange
,用于追溯“某时刻的拓扑”。策略:
btree_gist
+ GIST 范围索引,支持按时间窗口查询。kb_doc
:文档元信息(来源、标题、URL、元数据)。kb_chunk
:切片 +
向量(vector(1536)
),USING hnsw
建立近似检索。策略:
tenant_id/资源/时间
作为结构化过滤条件,向量召回后再二次排序。event_envelope
:事件封套(时间/资源/严重级/类型/摘要/标签/指纹)。evidence_link
:多态引用到 PG 记录或
oo_locator
,串起证据链。关键修正:
evidence_link
使用 自增主键 + 唯一索引(基于 ref_pg
的 hash + ref_oo) 实现“幂等去重”。详见附录 DDL。service_call_5m
挑选近 10
分钟活跃边(按租户/边聚合),用 AGE 的 MERGE
同步:
(:Resource {tenant_id, resource_id})
[:CALLS {last_seen, rps, err_rate, p95}]
service_call_5m
& topo_edge_time
)。写入:
metric_1m
、service_call_5m
、log_pattern_5m
;oo_locator
(对象路径 + 时间窗 + hint);读取:
metric_1m
/ log_pattern_5m
/ service_call_5m
;sample_ref
/
evidence_link.ref_oo
反查 OO。默认留存:
metric_1m
:180 天;service_call_5m
:365
天;log_pattern_5m
:180 天;1)过去 30 分钟某服务下游 Top‑5 慢/错依赖
SELECT d.urn AS dst, avg(p95_ms) AS p95, avg(err_rate) AS err
FROM service_call_5m c
JOIN dim_resource s ON s.resource_id = c.src_resource_id
JOIN dim_resource d ON d.resource_id = c.dst_resource_id
WHERE s.urn = $service_urn
AND c.bucket >= now() - interval '30 minutes'
GROUP BY d.urn
ORDER BY p95 DESC, err DESC
LIMIT 5;
2)按事件拉取证据(含 OO 回查线索)
SELECT e.event_id, e.title, e.detected_at, r.urn,
ev.dim, ev.ref_pg, ol.bucket, ol.object_key, ol.query_hintFROM event_envelope e
JOIN dim_resource r ON r.resource_id = e.resource_id
LEFT JOIN evidence_link ev ON ev.event_id = e.event_id
LEFT JOIN oo_locator ol ON ol.id = ev.ref_oo
WHERE e.event_id = $1;
3)恢复“某一时刻”的服务级拓扑
SELECT s.urn AS src, d.urn AS dst, t.relation
FROM topo_edge_time t
JOIN dim_resource s ON s.resource_id = t.src_resource_id
JOIN dim_resource d ON d.resource_id = t.dst_resource_id
WHERE t.tenant_id = $tenant
AND t.valid @> $timestamp::timestamptz;
tenant_id
优先;必要时做 schema‑per‑tenant;ON CONFLICT
;evidence_link
采用哈希唯一索引去重;labels
与 metadata
控敏字段打码。-- 0) 扩展(一次性)
CREATE EXTENSION IF NOT EXISTS timescaledb;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS pgcrypto; -- gen_random_uuid
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS age; -- 图扩展(服务级调用图)
'age';
LOAD CREATE EXTENSION IF NOT EXISTS btree_gist; -- 用于时态拓扑范围索引
-- 1) 维度(2)
CREATE TABLE dim_tenant (
PRIMARY KEY,
tenant_id BIGSERIAL UNIQUE NOT NULL,
code TEXT NOT NULL,
name TEXT DEFAULT '{}'::jsonb,
labels JSONB DEFAULT now()
created_at TIMESTAMPTZ
);
CREATE TABLE dim_resource (
PRIMARY KEY,
resource_id BIGSERIAL REFERENCES dim_tenant(tenant_id),
tenant_id BIGINT UNIQUE NOT NULL,
urn TEXT type TEXT NOT NULL,
NOT NULL,
name TEXT
env TEXT,
region TEXT,zone TEXT,
DEFAULT '{}'::jsonb,
labels JSONB DEFAULT now()
created_at TIMESTAMPTZ
);CREATE INDEX idx_res_type ON dim_resource(type);
CREATE INDEX idx_res_labels_gin ON dim_resource USING GIN(labels);
-- 2) OO 定位符(1)
CREATE TABLE oo_locator (
id BIGSERIAL PRIMARY KEY,
REFERENCES dim_tenant(tenant_id),
tenant_id BIGINT NOT NULL, -- logs / traces / metrics
dataset TEXT NOT NULL,
bucket TEXT NOT NULL,
object_key TEXT NOT NULL,
t_from TIMESTAMPTZ NOT NULL,
t_to TIMESTAMPTZ
query_hint TEXT,attributes JSONB DEFAULT '{}'::jsonb
);CREATE INDEX idx_oo_time ON oo_locator(dataset, t_from, t_to);
-- 3) 指标聚合(1m,Hypertable)
CREATE TABLE metric_1m (
NOT NULL,
bucket TIMESTAMPTZ REFERENCES dim_tenant(tenant_id),
tenant_id BIGINT REFERENCES dim_resource(resource_id),
resource_id BIGINT NOT NULL,
metric TEXT DOUBLE PRECISION,
avg_val DOUBLE PRECISION,
max_val DOUBLE PRECISION,
p95_val DEFAULT '{}'::jsonb
labels JSONB
);SELECT create_hypertable('metric_1m','bucket',chunk_time_interval => interval '7 days');
CREATE INDEX idx_metric_key ON metric_1m(resource_id, metric, bucket DESC);
CREATE INDEX idx_metric_labels ON metric_1m USING GIN(labels);
ALTER TABLE metric_1m SET (
compress,
timescaledb.= 'resource_id, metric',
timescaledb.compress_segmentby = 'bucket'
timescaledb.compress_orderby
);SELECT add_compression_policy('metric_1m', INTERVAL '7 days');
SELECT add_retention_policy ('metric_1m', INTERVAL '180 days');
-- 4) 服务级调用聚合(5m,Hypertable)
CREATE TABLE service_call_5m (
NOT NULL,
bucket TIMESTAMPTZ REFERENCES dim_tenant(tenant_id),
tenant_id BIGINT REFERENCES dim_resource(resource_id),
src_resource_id BIGINT REFERENCES dim_resource(resource_id),
dst_resource_id BIGINT DOUBLE PRECISION,
rps DOUBLE PRECISION,
err_rate DOUBLE PRECISION,
p50_ms DOUBLE PRECISION,
p95_ms REFERENCES oo_locator(id),
sample_ref BIGINT PRIMARY KEY(bucket, tenant_id, src_resource_id, dst_resource_id)
);SELECT create_hypertable('service_call_5m','bucket',chunk_time_interval => interval '30 days');
CREATE INDEX idx_call_src_dst ON service_call_5m(src_resource_id, dst_resource_id, bucket DESC);
SELECT add_retention_policy('service_call_5m', INTERVAL '365 days');
-- 5) 日志指纹(去重)+ 5m 计数(2)
CREATE TABLE log_pattern (
PRIMARY KEY,
fingerprint_id BIGSERIAL REFERENCES dim_tenant(tenant_id),
tenant_id BIGINT NOT NULL,
pattern TEXT
sample_message TEXT,
severity TEXT,DEFAULT '{}'::jsonb,
attrs_schema JSONB
first_seen TIMESTAMPTZ,
last_seen TIMESTAMPTZ
);CREATE INDEX idx_logpat_tenant ON log_pattern(tenant_id);
CREATE INDEX idx_logpat_pattern_trgm ON log_pattern USING GIN (pattern gin_trgm_ops);
CREATE TABLE log_pattern_5m (
NOT NULL,
bucket TIMESTAMPTZ REFERENCES dim_tenant(tenant_id),
tenant_id BIGINT REFERENCES dim_resource(resource_id),
resource_id BIGINT REFERENCES log_pattern(fingerprint_id),
fingerprint_id BIGINT NOT NULL,
count_total BIGINT NOT NULL DEFAULT 0,
count_error BIGINT REFERENCES oo_locator(id),
sample_ref BIGINT PRIMARY KEY(bucket, tenant_id, resource_id, fingerprint_id)
);SELECT create_hypertable('log_pattern_5m','bucket',chunk_time_interval => interval '30 days');
CREATE INDEX idx_logpat5m_res ON log_pattern_5m(resource_id, bucket DESC);
SELECT add_retention_policy('log_pattern_5m', INTERVAL '180 days');
-- 6) 拓扑时态(1)
CREATE TABLE topo_edge_time (
REFERENCES dim_tenant(tenant_id),
tenant_id BIGINT REFERENCES dim_resource(resource_id),
src_resource_id BIGINT REFERENCES dim_resource(resource_id),
dst_resource_id BIGINT NOT NULL,
relation TEXT NOT NULL, -- [from, to)
valid tstzrange DEFAULT '{}'::jsonb,
props JSONB PRIMARY KEY(tenant_id, src_resource_id, dst_resource_id, relation, valid)
);CREATE INDEX idx_topo_valid ON topo_edge_time USING GIST (tenant_id, src_resource_id, dst_resource_id, valid);
-- 7) 知识库 / 向量(2)
CREATE TABLE kb_doc (
PRIMARY KEY,
doc_id BIGSERIAL REFERENCES dim_tenant(tenant_id),
tenant_id BIGINT source TEXT,
title TEXT,
url TEXT,DEFAULT '{}'::jsonb,
metadata JSONB DEFAULT now()
created_at TIMESTAMPTZ
);
CREATE TABLE kb_chunk (
PRIMARY KEY,
chunk_id BIGSERIAL REFERENCES kb_doc(doc_id) ON DELETE CASCADE,
doc_id BIGINT INT NOT NULL,
chunk_idx NOT NULL,
content TEXT 1536) NOT NULL,
embedding vector(DEFAULT '{}'::jsonb
metadata JSONB
);CREATE INDEX idx_kb_chunk_doc ON kb_chunk(doc_id, chunk_idx);
CREATE INDEX idx_kb_chunk_meta ON kb_chunk USING GIN(metadata);
CREATE INDEX idx_kb_vec_hnsw ON kb_chunk USING hnsw (embedding vector_l2_ops);
-- 8) 事件 & 证据链(2)
BEGIN
DO $$ IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'severity') THEN
CREATE TYPE severity AS ENUM ('TRACE','DEBUG','INFO','WARN','ERROR','FATAL');
END IF;
END $$;
CREATE TABLE event_envelope (
PRIMARY KEY DEFAULT gen_random_uuid(),
event_id UUID NOT NULL DEFAULT now(),
detected_at TIMESTAMPTZ REFERENCES dim_tenant(tenant_id),
tenant_id BIGINT REFERENCES dim_resource(resource_id),
resource_id BIGINT NOT NULL,
severity severity NOT NULL, -- anomaly/slo_violation/deploy/incident/...
kind TEXT
title TEXT,summary TEXT,
DEFAULT '{}'::jsonb,
labels JSONB DEFAULT '{}'::jsonb
fingerprints JSONB
);CREATE INDEX idx_event_time ON event_envelope(tenant_id, detected_at DESC);
-- 注意:主键不能用表达式,改为自增 + 唯一索引(ref_pg 哈希 + ref_oo)
CREATE TABLE evidence_link (
PRIMARY KEY,
evidence_id BIGSERIAL NOT NULL REFERENCES event_envelope(event_id) ON DELETE CASCADE,
event_id UUID NOT NULL, -- metric/log/trace/topo/kb
dim TEXT -- {"table":"...","keys":{...}}
ref_pg JSONB, REFERENCES oo_locator(id),
ref_oo BIGINT
note TEXT,GENERATED ALWAYS AS (md5(coalesce(ref_pg::text, ''))) STORED
ref_pg_hash TEXT
);CREATE UNIQUE INDEX ux_evidence_unique
ON evidence_link(event_id, dim, ref_pg_hash, coalesce(ref_oo, 0));
CREATE INDEX idx_evidence_event ON evidence_link(event_id);
-- AGE 图:初始化(一次)
SELECT * FROM create_graph('ops');
SELECT * FROM create_vlabel('ops', 'Resource');
SELECT * FROM create_elabel('ops', 'CALLS');
WITH active AS (
SELECT tenant_id, src_resource_id, dst_resource_id,
max(bucket) AS last_seen,
avg(rps) AS rps, avg(err_rate) AS err_rate, avg(p95_ms) AS p95_ms
FROM service_call_5m
WHERE bucket >= now() - interval '10 minutes'
GROUP BY 1,2,3
)SELECT * FROM cypher('ops', $$
AS row
UNWIND $rows MERGE (s:Resource {tenant_id: row.tenant_id, resource_id: row.src})
MERGE (d:Resource {tenant_id: row.tenant_id, resource_id: row.dst})
MERGE (s)-[e:CALLS]->(d)
ON CREATE SET e.first_seen = row.last_seen
SET e.last_seen = row.last_seen, e.rps = row.rps, e.err_rate = row.err_rate, e.p95 = row.p95
RETURN 1
AS (ok int)
$$) rows := (
PARAMS (SELECT json_agg(json_build_object(
'tenant_id', tenant_id, 'src', src_resource_id, 'dst', dst_resource_id,
'last_seen', last_seen, 'rps', rps, 'err_rate', err_rate, 'p95', p95_ms))
FROM active));
这套「OO 扛明细 + PG 扛治理」的极简方案能把近线排障、影响面分析与知识复用串成闭环:
An overview of how monitoring evolved into modern full-stack observability and the key considerations when choosing diverse data sources.
[exporter] [Vector] [OTel GW] [OpenObserve]
NE ─┐ ┌─────────┐ ┌──────────┐ ┌─────────────┐
PE ─┼── metrics/logs ────> │ Vector │ ───> │ OTel GW │ ──> │ OO │
DF ─┤ └─────────┘ └──────────┘ └─────────────┘
LG ─┘
(近线窗口 ETL: 对齐=1m · 延迟=2m)
│
▼
┌──────────────────────────────────────┐
IaC/Cloud ────────────>│ │
│ ObserveBridge (ETL 任务) │
Ansible ───────────>│ • ETL 窗口聚合 / oo_locator │
│ • 拓扑 (IaC/Ansible) │
OO 明细(OO→OB) ───────>│ • AGE 10 分钟活跃调用图刷新 │
└──────────────────────────────────────┘
┌─────────────────────────────── Postgres 套件 ───────────────────────────────┐
│ PG_JSONB │ PG Aggregates (Timescale) │ PG Vector │ AGE │
│ (oo_locator/events) │ (metric_1m / call_5m / log_5m)│ (pgvector) │ Graph │
└───────────────┬────────┴───────────────┬──────────────┴─────────────┬────────┘
│ │ │
│ │ │
▼ ▼ ▼
[ llm-ops-agent / 应用消费(查询/检索/推理) ]
目标:在单二进制 Go 编排器内,完成三条主干 ETL 闭环:
metric_1m
、service_call_5m
、log_pattern_5m
,维护
log_pattern
指纹库与 oo_locator
回查线索。service_call_5m
为源,刷新 AGE 图中 10 分钟活跃服务级调用边
(:Resource)-[:CALLS]->(:Resource)
。topo_edge_time
(开/关区间),可选同步到 AGE 作为
:STRUCT
边。调度特性:窗口对齐 + 延迟容忍 + DAG 依赖 + 幂等 Upsert + 分片多租户。
可靠性:PG 唯一索引保证一次性;指数退避重试;失败熔断;事件补数回放。
/
etl/etl/ # 二进制入口/CLI
├─ cmd.go
│ └─ main/
├─ pkg/ # 调度器(窗口计算/派发)
│ ├─ scheduler/ # Worker 池 + 执行/重试/回调
│ ├─ runner/ # Job 接口 + 注册中心 + DAG
│ ├─ registry/ # 状态/一次性保证/简易队列(PG)
│ ├─ storewindow/ # 时间对齐/窗口工具
│ ├─ / # 事件入口(HTTP/CloudEvents风格)
│ ├─ events/ # OO 读取(S3 客户端 + 查询 API 适配)
│ ├─ oo/ # 聚合器(指标1m / 调用5m / 指纹5m)
│ ├─ agg/ # 日志指纹挖掘(Drain / RE2)
│ ├─ patterns/ # IaC/Cloud 归一(TF/Pulumi/aws/aliyun…)
│ ├─ iac/ # Playbook/Inventory 解析与依赖抽取
│ ├─ ansible/ # PG 写入器(COPY 批量 + 幂等 upsert)
│ └─ pgw/
├─ jobs.go # OO → metric_1m / call_5m / log_5m / locator
│ ├─ ooagg.go # 近10分钟活跃调用图刷新(依赖 ooagg)
│ ├─ age_refresh.go # IaC/Cloud → topo_edge_time(时态差分)
│ ├─ topo_iac.go # Ansible → topo_edge_time(时态差分)
│ └─ topo_ansible/
├─ sql.sql # AGE 刷新 SQL
│ └─ age_refresh/
└─ configs.yaml # 调度/并发/延迟 配置 └─ etl
下面是模块—接口—数据源/目标—窗口/键—幂等的一览表(开发/联调用)。
模块 | API/入口 | SRC(输入) | DEST(输出) | 窗口/键 | 幂等/唯一约束 | 备注 |
---|---|---|---|---|---|---|
pkg/oo | Stream(ctx, tenant, w, fn) | OO(S3 分区或查询 API)logs/metrics/traces | 回调 oo.Record | w=[From,To) | — | 统一时间/URN;并发读取 |
pkg/agg | Feed(rec) / Drain() | oo.Record | Metrics1m / Calls5m / LogPatterns5m / PatternsUpsert / Locators | 1m/5m | — | 内存桶聚合、指纹抽取 |
pkg/pgw | Flush(ctx, tenant, w, out) | 聚合结果 out | metric_1m、service_call_5m、log_pattern_5m、log_pattern、oo_locator、dim_resource | 1m/5m 主键 | ON CONFLICT DO UPDATE;oo_locator 唯一 | PG 批量 COPY + Upsert |
jobs/ooagg | Run(ctx, tenant, w) | pkg/oo → pkg/agg | pkg/pgw.Flush | Align=1m;Delay=2m | 由目标表主键保证 | 成功后触发 age-refresh |
sql/age_refresh.sql | cypher(‘ops’, …) | service_call_5m 近10分钟 | AGE 图 CALLS 边 | 10 分钟 | MERGE 唯一匹配 | e.last_seen/rps/err/p95 |
jobs/age_refresh | Run(ctx, tenant, w) | service_call_5m | 执行 SQL | Align=5m | — | After()=“oo-agg” |
pkg/iac | Discover(ctx, tenant) | TF/Pulumi/Cloud API | 边集合 []Edge | — | — | 构造 URN、relation |
pkg/ansible | ExtractDeps(ctx, tenant) | inventory/group_vars/roles | 边集合 []Edge | — | — | 解析 upstream/连接串 |
pkg/pgw | UpsertTopoEdges(ctx, tenant, edges) | iac/ansible 边 | topo_edge_time(时态) | valid tstzrange | PK(tenant,src,dst,rel,valid) | 差分开/关区间 |
jobs/topo_iac | Run(ctx, tenant, w) | pkg/iac.Discover | topo_edge_time | Align=15m | — | 结构拓扑 |
jobs/topo_ansible | Run(ctx, tenant, w) | pkg/ansible.ExtractDeps | topo_edge_time | Align=1h | — | 应用依赖拓扑 |
pkg/events | /events/enqueue | CloudEvents/HTTP | etl_job_run 状态置 queued | 任意窗口 | ux_job_once | 手动补数/回放 |
pkg/store | EnqueueOnce/Mark* | — | etl_job_run | job/tenant/window | ux_job_once | 一次性保证/队列 |
pkg/scheduler | Tick() | dim_tenant & etl_job_run | 入队窗口 | Align/Delay/Lookback | — | 动态加载配置 |
相关 PG 表(12 + ETL 元数据)
dim_tenant
、dim_resource
oo_locator
metric_1m
(1m)、service_call_5m
(5m)、log_pattern_5m
(5m)log_pattern
topo_edge_time
kb_doc
、kb_chunk
(向量)event_envelope
、evidence_link
etl_job_run
、etl_job_circuit
ops
图(Resource
、CALLS
)upper = floor(now - Delay, Align)
,从上次成功窗口末尾或
initial_lookback
起步。log_pattern
以 pattern hash 或唯一键 upsert;oo_locator
唯一组合避免重复。urn:k8s:svc:<ns>/<name>
/
urn:host:<host>
/
urn:db:postgres:<cluster>/<db>
,并缓存
resource_id
。service_call_5m
与 topo_edge_time
。tstzrange
开/关区间维护时态;当边消失时关闭上次开区间。每个任务包含:name / 描述 / 测试-验证。可直接拆成 Codex 指令执行(create-or-update-files / patch),或作为 PR checklist。
pkg/pgw.Flush
(COPY + Upsert 批量写)oo_locator
写入并回填
sample_ref
;metric_1m
/service_call_5m
/log_pattern
/log_pattern_5m
批量写入,全部 ON CONFLICT DO UPDATE
。etl_job_run
状态转为 success
;冲突率
< 5%。sql/age_refresh.sql
的程序化执行jobs/age_refresh.go
读取并执行 sql/age_refresh.sql
,或用参数化 SQL
内嵌实现。service_call_5m
行,运行
age-refresh
,检查 AGE 中 CALLS
边的
last_seen/rps/err_rate/p95
。pkg/oo.Stream
的 MOCK 与真实 S3/API 适配- MOCK:生成固定分布的 logs/metrics/traces;支持 `--mock` 开关。
- S3:按 `dataset/yyyy=.../hh=.../mm=...` 列表对象;API:按时间窗查询。
- `--mock` 模式 1m 生成 5k 日志、500 指标点、1k span,端到端落库 < 3s/窗口
- 切换到 S3,验证窗口边界与对象命名正确。
pkg/agg
聚合正确性avg/max/p95
、调用 5m
rps/err/p50/p95
、日志指纹 5m 计数;接入
patterns.MineTemplate
。pkg/patterns
指纹抽取(Drain/RE2)fingerprint
、severity
;可配置忽略字段。count_error
正确累积。pkg/iac.Discover
+
pkg/ansible.ExtractDeps
DEPENDS_ON
边。topo_edge_time
新增开区间;删除节点后再次运行,旧边区间关闭。T7 —
pkg/pgw.UpsertTopoEdges
时态差分
E_now
与当前开区间
E_prev
的集合差;新增插入开区间,消失关闭区间。valid
上界从无穷变为 now()
。pkg/events
事件补数接口POST /events/enqueue
支持
{job, tenant_id, from, to}
回放窗口;写入
etl_job_run
为 queued
并入队。pkg/config
已有;在
scheduler
注入 Cfg
并使用
tenants.initial_lookback.oo-agg
等。etl_job_run
记录后启动,观察从
initial_lookback
开始补跑。/metrics
或写回 OO);记录窗口滞后。window_lag_seconds
<
Delay + Align
;失败重试曲线可见。, count(*), min(bucket), max(bucket)
SELECT metric
FROM metric_1mcount(*) DESC LIMIT 10; GROUP BY metric ORDER BY
AS (
WITH active , dst_resource_id
SELECT src_resource_id
FROM service_call_5m>= now() - interval '10 minutes'
WHERE bucket 1,2
GROUP BY
)count(*) AS edges_in_source FROM active;
SELECT -- 再在 AGE 里查同样规模(CALLS 边数量),两者应近似一致(考虑租户过滤)
-- 当前有效边
count(*) FROM topo_edge_time WHERE upper_inf(valid);
SELECT -- 历史边(已关闭)
count(*) FROM topo_edge_time WHERE NOT upper_inf(valid); SELECT
Illustrates common operational situations that highlight the need for effective monitoring across systems and services.
灰度发布(Canary/Blue-Green) 触发:新版本可用 →
动作:按权重放量/自动回滚 → 校验:service_call_5m
的
p95/err_rate 门槛。
特性开关(Feature Flag)渐进开启 触发:验收通过 → 动作:按租户/地域打开 → 校验:关键路径转化率、错误率对比。
依赖版本对齐(SDK/Sidecar/Agent) 触发:安全公告/CVE → 动作:批量滚更 → 校验:服务健康探针、崩溃率。
配置漂移检测 & 回收 触发:Git 与运行态差异 → 动作:生成 PR/自动修复 → 校验:IaC 合规策略通过。
自动限流/熔断/隔离 触发:err_rate↑ / p95↑ → 动作:在网关/服务级应用限流与熔断 → 校验:下游恢复、全链 p95 回落。
异常回滚 & 一键 Mitigation 触发:SLO 未命中
→ 动作:Plan DSL 的 compensate
执行 → 校验:回滚后 SLO
达标。
降级策略编排(缓存兜底/只读模式) 触发:依赖服务不可用 → 动作:启用降级开关 → 校验:功能可用性≥阈值。
日志噪声抑制 & 指纹提纯
触发:log_pattern_5m
激增 → 动作:更新过滤/聚合规则 →
校验:噪声占比下降。
自动扩缩容(HPA/VPA/KEDA) 触发:RPS/CPU/GPU 利用率门槛 → 动作:扩容/缩容 → 校验:p95/队列长度回稳。
热点定位(Top-K 端点/表/索引) 触发:看板阈值 → 动作:生成优化建议(索引/缓存/批量) → 校验:目标指标改善幅度。
慢查询守护(PostgreSQL/OLAP) 触发:计划回退/代价飙升 → 动作:计划冻结、索引重建、ANALYZE → 校验:执行时间降低。
CDN/缓存命中率调优 触发:MISS 高/回源高 → 动作:规则更新、预热 → 校验:命中率↑、回源↓。
分区/压缩/保留策略执行(Timescale/OO) 触发:窗口到期 → 动作:Timescale 压缩、OO 生命周期转冷 → 校验:存储曲线与查询命中率。
备份与恢复演练(DB/对象存) 触发:季度演练 → 动作:还原到沙箱/校验一致性 → 校验:RTO/RPO 达标。
Schema 变更护栏(DDL 门控) 触发:DDL PR → 动作:影子评估/回放 → 校验:读写延迟无回退。
数据质量监控(ETL/流式) 触发:空值/重复/延迟异常 → 动作:回填/重跑 → 校验:质量指标恢复。
证书与密钥轮换(TLS/KMS/ACME) 触发:到期前 N 天 → 动作:自动签发/分发/热加载 → 校验:握手成功率、无中断。
CVE 修补与内核/容器镜像升级 触发:高危 CVE → 动作:分批滚更 → 校验:漏洞基线清零。
访问评审与最小权限(RBAC/IAM) 触发:月度审计 → 动作:收敛权限/吊销闲置 → 校验:策略命中/拒绝率无异常。
合规窗口/变更冻结 触发:活动/大促/监管窗口 → 动作:Gatekeeper 拒绝非白名单变更 → 校验:变更违规为 0。
入口网关/Ingress 规则变更与回滚 触发:路径/权重调整 → 动作:灰度发布 Nginx/Envoy → 校验:5xx/延迟曲线。
跨区流量调度/健康探测 触发:区域异常 → 动作:权重切换/只读路由 → 校验:丢包/RTT 恢复。
证书/ECH/TLS 指纹更新(Xray/Sing-box) 触发:策略更新 → 动作:节点批量更新 → 校验:连通率、误封率。
Egress/WAF 策略 触发:异常出站/攻击面提示 → 动作:规则下发 → 校验:拦截率与误报率。
K8s 小版本升级 & 节点滚更 触发:版本落后 → 动作:逐组 Cordon/Drain/升级 → 校验:工作负载无中断。
GPU 驱动/Operator 更新(A10/L40/A100)
触发:新特性/修复 → 动作:分池灰度 → 校验:nvidia-smi
/MIG
配置正确、作业吞吐。
容器运行时/镜像仓库镜像切换 触发:镜像拉取慢/失效 → 动作:镜像加速/离线包 → 校验:拉取成功率、构建时长。
Ingress 离线安装包验证(你已有目标) 触发:新离线包 → 动作:沙箱校验/多架构镜像加载 → 校验:可用性与兼容性。
模型上线策略(Shadow→Canary) 触发:新模型评估通过 → 动作:影子对比/小流量灰度 → 校验:质量指标、成本/QPS。
数据/概念漂移监测 触发:分布/性能漂移 → 动作:告警/Retrain 计划 → 校验:OOS 指标回升。
RAG 质量守护(向量库更新/召回评测) 触发:知识变更 → 动作:重嵌入/基准集评测 → 校验:Top-k 命中率/答案自信度。
推理路由与预算控制(多端点) 触发:延迟/价格波动 → 动作:路由切换/配额限流 → 校验:SLO 与成本曲线。
SLO 定义与回归检测 触发:SLO 变更 → 动作:历史重放评估 → 校验:误报/漏报下降。
告警噪声治理 触发:高噪声规则 → 动作:聚合/抑制窗口优化 → 校验:On-call 负担降低。
追踪抽样自适应 触发:流量/成本压力 → 动作:按错误/慢请求倾斜采样 → 校验:诊断覆盖率保持。
多区域演练(GameDay/Chaos) 触发:季度/半年度 → 动作:注入故障/演练切流 → 校验:RTO/RPO/SLO 达标。
对象存储/消息系统灾备切换 触发:主域不可用 → 动作:桶/Topic/镜像切换 → 校验:数据一致性与延迟。
实例规格与副本数 Rightsizing 触发:长期低/高利用 → 动作:规格/副本调整 → 校验:性能不降、成本下降。
Spot/预留/竞价策略编排 触发:价格/回收风险 → 动作:池化/回填 → 校验:业务无损、成本可控。
存储分层(热/温/冷)与清理 触发:访问频次变化 → 动作:生命周期迁移/清理 → 校验:成本下降、命中率合理。
服务目录 + 变更申请自助 触发:团队提变更 → 动作:模板化 Plan、Gatekeeper 审批 → 校验:周期缩短、违规为 0。
合规审计与证据归档 触发:审计周期 → 动作:导出
event_envelope + evidence_link
→
校验:稽核一次通过。
Discusses trade-offs between collecting observability data at the edge and routing through centralized gateways.
Explores architectural patterns and design thoughts for building an OpenTelemetry-based gateway.
Details strategies for persisting collected data at multiple stages and replaying it for analysis or recovery.
Outlines principles for structuring databases that support metric, log, trace, event, and profile storage in one system.
Describes extract-transform-load workflows for moving observability data between hot and cold storage layers.
Covers approaches to deploying observability stacks across regions with failover and disaster recovery in mind.
Reviews the challenges of traditional remote management and outlines factors to evaluate before adopting AI-powered operations agents.
Enumerates the functional requirements and competencies expected from an AI-assisted operations agent.
Highlights how PostgreSQL extensions enable advanced analysis such as vector similarity search, graph traversal, and trend detection for operations data.
Proposes a minimal viable architecture for an AI-powered operations agent integrating data collection, analysis, and automated actions.
关键词:Walking Skeleton/状态机(FSM)/Outbox/Idempotency/事件驱动/LLM 契约化
本文落地一条“最短闭环”(人工触发 → 计划 → 审批 → 执行 → 验证 → 归档),强调:确定性的状态机做“合法性与原子落库”,不确定性的 LLM 做“生成、检索、归纳”,两者以“可验证的契约”交汇。
PATCH /case/{id}/transition
;事务内同时写
ops_case
、case_timeline
、outbox
;所有副作用“先出盒,后投递”。LLM 擅长“生成与归纳”,但不提供事务性与幂等保证。生产级 OPS 需要: 1) 可证明的合法迁移(纯函数 FSM) 2) 原子副作用(状态 + 时间线 + 出盒) 3) 至少一次投递 + 消费幂等(Outbox/Inbox Pattern)
原则:确定性包围不确定性。所有非确定性的 AI 产物都转为结构化契约(JSON/YAML + Schema 校验)后,才允许进入状态机的下一跳。
目标:先打通一条最短闭环,可演示、可观测、可回滚。
实现顺序: 1.
Orchestrator(必须先做):纯函数 FSM +
原子事务(状态/时间线/出盒)+ 幂等/OCC。 2.
Planner(最小可用):模板计划生成,产出
plan_proposed
与 evt.plan.proposed.v1
。 3.
Gatekeeper(自动审批):本地策略阈值,产出
plan_approved
与 evt.plan.approved.v1
。 4.
Executor(Step Runner):先做 echo/script
与 k8s rollout
两个适配器。 5. Verifier(SLO
校验):基于 metric_1m
的阈值判定。 6~8.
Analyst / Sensor /
Librarian:把入口从“人工”扩展到“信号驱动”,把 Planner
从模板升级为基于证据的拟合。
flowchart LR
subgraph UI/API
H[Human/UI]
end
subgraph Core[Core Services]
O[Orchestrator\nFSM+Outbox+Timeline]
P[Planner\n(LLM/模板→ plan_proposed)]
G[Gatekeeper\n(策略/OA判定)]
E[Executor\n(Adapters: script/k8s/...)]
V[Verifier\n(SLO阈值)]
A[Analyst\n(规则/统计→ findings)]
S[Sensor\n(oo_locator / ingest)]
L[Librian\n(pgvector RAG)]
end
EV[(Event Bus\nNATS/Redpanda)]
DB[(PostgreSQL/Timescale)]
OO[(OpenObserve/Logs)]
H -- REST --> O
O -- outbox/cmd.* --> EV
EV -- evt.* --> O
P & G & E & V & A & S & L -- evt./cmd. <--> EV
O -- R/W --> DB
E -- logs/refs --> OO
接口与事件最小集 - REST: -
POST /case/create
,GET /case/{id}
,GET /case/{id}/timeline
-
PATCH /case/{id}/transition
(唯一改状态入口;需
Idempotency-Key
+ 建议 If-Match
) -
POST /plan/generate
,POST /gate/eval
,POST /adapter/exec
,POST /verify/run
- 事件: - evt.case.transition.v1
(任何迁移事实) -
evt.plan.proposed.v1
,evt.plan.approved.v1
-
evt.exec.step_result.v1
,evt.exec.done|failed.v1
-
evt.verify.pass|failed.v1
,evt.analysis.findings.v1
-
cmd.plan.generate / cmd.gate.eval / cmd.exec.run / cmd.verify.run
stateDiagram-v2
[*] --> NEW
NEW --> ANALYZING: start_analysis
ANALYZING --> PLANNING: analysis_done
PLANNING --> WAIT_GATE: plan_ready (guard: complete plan)
WAIT_GATE --> EXECUTING: gate_approved
WAIT_GATE --> PARKED: gate_rejected
EXECUTING --> VERIFYING: exec_done
EXECUTING --> PARKED: exec_failed
VERIFYING --> CLOSED: verify_pass
VERIFYING --> PARKED: verify_failed
PARKED --> PLANNING: resume / fix
守卫示例(plan 完整性) - steps
至少 1
个;每个 step 定义
action
、timeout
、retry
; -
rollback
与 verify
字段必须存在; -
计划大小、危险操作需标识并由 Gatekeeper 评分/审批。
任何守卫失败都不改变状态,仅记录时间线并返回 409/422。
单事务保证: 1) 更新
ops_case.version, status
2) 追加 case_timeline
3) 写入 outbox
(cmd.* 或 evt.* 载荷)
幂等与并发: -
Idempotency-Key
:命中即返回首次结果,不重复写时间线/出盒。
- If-Match
/expected_version
:不匹配 →
409/412
。
伪代码(Go/Pseudocode):
func Transition(ctx, caseID, event, meta) (Case, error) {
return WithTx(ctx, func(tx Tx) (Case, error) {
:= repo.GetForUpdate(tx, caseID)
c , next := workflow.Decide(c.Status, event)
allowedif !allowed { return error(409) }
// guards (schema/plan completeness/risk window etc.)
if err := Guards.Pass(tx, c, event, meta); err != nil { return error(422) }
.Status, c.Version = next, c.Version+1
c.Update(tx, c)
repo
.Append(tx, c.ID, event, meta)
timeline
.Append(tx, BuildMessages(c, event, meta))
outbox
return c, nil
})
}
口号:LLM 只输出“结构化、可验证、可回放”的产物;状态改变永远经 Orchestrator。
evidence_link
)、历史相似案
kb_chunk
、环境约束。{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "ChangePlan",
"type": "object",
"required": ["title","steps","rollback","verify"],
"properties": {
"title": {"type":"string"},
"risk_score": {"type":"number","minimum":0,"maximum":1},
"steps": {
"type":"array","minItems":1,
"items": {"type":"object","required":["action","timeout_s","retry"],
"properties": {
"action": {"enum":["k8s.rollout","script.exec","gateway.flip","noop"]},
"params": {"type":"object"},
"timeout_s": {"type":"integer","minimum":10},
"retry": {"type":"integer","minimum":0,"maximum":3}
}
}
},
"rollback": {"type":"object"},
"verify": {"type":"object"}
}
}
/plan/generate
→ 校验 Schema →
入库 plan_proposed
→ 发
evt.plan.proposed.v1
。Prompt 片段(示意):
System: 你是资深 SRE。产出必须是符合 JSON Schema 的 ChangePlan。不要输出自然语言解释。
User: {问题摘要/证据/限制}
Assistant: {ChangePlan JSON}
event_envelope
)。kb_doc/kb_chunk
(pgvector)做相似案例/Runbook 检索;LLM
用于拟合与注释,生成可执行/可审阅的 Plan。-- 1) 事实源
CREATE TABLE ops_case (
id UUID PRIMARY KEY,
tenant TEXT, title TEXT,NOT NULL,
status TEXT INT NOT NULL,
version DEFAULT now(),
created_at TIMESTAMPTZ DEFAULT now()
updated_at TIMESTAMPTZ
);
CREATE TABLE case_timeline (
id BIGSERIAL PRIMARY KEY,
REFERENCES ops_case(id),
case_id UUID
event TEXT, actor TEXT, reason TEXT,
correlation_id TEXT, meta JSONB,DEFAULT now()
created_at TIMESTAMPTZ
);
CREATE TABLE outbox (
id BIGSERIAL PRIMARY KEY,
key TEXT, payload JSONB,
topic TEXT, DEFAULT now(),
created_at TIMESTAMPTZ
published_at TIMESTAMPTZ
);
CREATE TABLE idempotency (
key TEXT PRIMARY KEY,
response JSONB,DEFAULT now()
created_at TIMESTAMPTZ
);
-- 2) Planner/Exec/Verify(示意)
CREATE TABLE plan_proposed (
id UUID PRIMARY KEY,
REFERENCES ops_case(id),
case_id UUID plan JSONB NOT NULL,
DEFAULT now()
created_at TIMESTAMPTZ
);CREATE TABLE plan_approved (
id UUID PRIMARY KEY,
REFERENCES ops_case(id),
case_id UUID
decision JSONB,DEFAULT now()
created_at TIMESTAMPTZ );
case_transition_total{from,to,event}
conflict_total{reason}
(409/412/422)idempotent_replay_total
outbox_publish_total{topic,status}
/
inbox_dedup_total
adapter_step_latency_seconds
、verify_latency_seconds
trace_id
并写入 case_timeline.meta
。exec_step.*_ref
指向 OO/Loki
的 oo_locator
。# 1) 创建 Case
CASE=$(curl -sX POST /case/create -d '{"title":"p95 spike","tenant":"t-001"}'|jq -r .data.case_id)
# 2) 开始分析
curl -X PATCH /case/$CASE/transition \
-H 'Idempotency-Key:a1' \
-d '{"event":"start_analysis","actor":"analyst@svc"}'
# 3) 生成计划(模板/LLM)
curl -X POST /plan/generate -d '{"case_id":"'$CASE'","template":"k8s.rollout.canary"}'
# Planner 发 evt.plan.proposed.v1 → Orchestrator 判定 plan_ready → WAIT_GATE
# 4) 自动审批
curl -X POST /gate/eval -d '{"case_id":"'$CASE'"}'
# Gatekeeper 发 evt.plan.approved.v1 → EXECUTING
# 5) 执行适配器(示例:script)
curl -X POST /adapter/exec -d '{"case_id":"'$CASE'","adapter":"script","script":"echo ok"}'
# Executor 发 evt.exec.done.v1 → VERIFYING
# 6) 验证通过 → CLOSED
curl -X POST /verify/run -d '{"case_id":"'$CASE'"}'
.
├─ api/ # Gin/Fiber + OpenAPI + 中间件
├─ workflow/ # 纯函数 FSM
├─ plans/ # 纯函数计划生成(模板 + LLM 契约)
├─ gatekeeper/ # 策略引擎(本地规则/OPA/Cedar)
├─ executor/
│ ├─ adapters/ # k8s/script/gateway...
│ └─ runner/ # step 执行/超时/重试
├─ verifier/
├─ analyst/
├─ sensor/
├─ librarian/
├─ internal/pubsub/ # NATS/Redpanda(至少一次 + 去重)
├─ ports/ # Repo/Outbox/Timeline/Idempotency 接口
├─ services/ # Orchestrator 等聚合服务
└─ migrations/ # DDL
case_transition_total / conflict_total / idempotent_replay_total
;Outbox
消费无重复副作用。plan_proposed
入库;DSL 过
schema;守卫挡下不完整计划。exec_failed
并落 PARKED。metric_1m
发现简单异常并自动开 Case。oo_locator
可被
evidence_link
回链;写入 p99 < 2s。Idempotency-Key
;消费者对
message_id
去重。SELECT ... FOR UPDATE
+ 版本控制;冲突返回
409/412。Orchestrator 只做两件事:判定合法迁移(纯函数)+一次事务内记录(状态/时间线/出盒)。其余模块要么被它的命令驱动,要么把“事实事件”交还它,由它来改变世界。LLM 负责提出“更好的方案”,而不是亲自“按下回车”。