news 2026/10/22 15:14:31

WuKongIM 云端仿真可观测性:不部署日志栈的 Prometheus + Analysis MCP 实时聚合面

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
WuKongIM 云端仿真可观测性:不部署日志栈的 Prometheus + Analysis MCP 实时聚合面
  • 即时通讯
  • 后端

【免费下载链接】WuKongIM

More than just IM 不只是即时通讯(IM)

项目地址:https://gitcode.com/gh_mirrors/wu/WuKongIM
点击查看免费下载

本文基于已接受的架构决策 ADR 0022(Aggregate live observability without a log stack),讲解 WuKongIM 云端仿真(Cloud Simulation)场景下的实时可观测性方案:由仿真器(simulator)统一托管 Prometheus 抓取集群与宿主机指标,结构化应用日志保持在各源节点上做有界轮转,再由 Analysis MCP 把 Prometheus 查询与既有私有日志、诊断、任务审计、workqueue、profiling 等面聚合成一个受控的实时诊断入口。读完本文,你将理解这一方案中"不引入 Grafana / Loki / ELK / 跨 Run 存储"的边界划分、各观测面的源码级实现位置,以及 metrics 保留期、日志配额与磁盘预检如何按"工作负载时长 + Analysis Grace"进行容量设定。

一、ADR 0022 的核心决策与适用边界

docs/adr/0022-aggregate-live-observability-without-a-log-stack.md 状态为accepted,其决策要点可以归纳为五条:

  1. 仿真器托管 Prometheus:为 WuKongIM 集群节点提供 host metrics 的抓取与保留;
  2. 应用日志留在源节点:结构化应用日志保持有界(bounded)并在其产生节点上轮转(rotated),不集中采集;
  3. Analysis MCP 做聚合者:它聚合 Prometheus 查询与既有的私有 manager log、diagnostics、task-audit、workqueue、profiling 等多个观测面;
  4. 仿真器服务日志走本地 journald:Analysis MCP 从仿真器本地的 journald 查询其自身托管服务的日志;
  5. Provisioning Workflow 自留引导失败:预置阶段的 bootstrap 失败记录保留在工作流自身的 summary 中,不进入观测面。

同时该 ADR 划定了明确的不做清单:第一版本不部署 Grafana、Loki、ELK,也不做跨 Run(cross-run)的观测数据存储;metrics 保留期、日志配额和磁盘预检均按"工作负载时长 + Analysis Grace"来设定尺寸。

这条决策并非孤立存在,它依赖一组前置决策共同成立:

  • ADR 0014 决定云主机上的 WuKongIM、wkbench、Analysis MCP、Prometheus、host-observation 二进制全部以原生 systemd 服务方式运行,并内建 journald 集成(见 docs/adr/0014-run-cloud-services-as-native-systemd-units.md);正是"服务已原生接入 journald"这一点,让第 4 条决策可以用journalctl直接查本地日志,而无需额外的日志采集器。
  • ADR 0021 把"工作负载时长"与"分析宽限期"分离:可选的30m/2h/24h/48h描述的是就绪后的有效负载时间(默认2h),而 Analysis Grace 为30m/1h/6h(默认30m),用于在负载停止后继续保留存活指标、日志、MCP 与集群供人工诊断(见 docs/adr/0021-separate-workload-duration-from-analysis-grace.md)。这正是 0022 中"按 workload duration + Analysis Grace 设定保留"的时间基准来源。
  • ADR 0017 与 ADR 0028 分别从"限制活动诊断"和"暴露窄而受界的 Run 作用域工具契约"两个角度约束了聚合面本身的行为边界,0022 的聚合入口必须服从这些约束。

值得注意的一点是:仓库中docker/observability/下确实存在 Grafana 仪表盘与数据源 provisioning 文件,但它们服务于本地开发参考拓扑(Docker Compose 场景),与 ADR 0022 所指的"云仿真第一版本不部署 Grafana"并不矛盾——0014 中已说明 Docker Compose 保留为本地开发与拓扑参考。

二、Prometheus 面:仿真器托管的指标保留与抓取

2.1 本地参考配置:抓取三节点与告警规则

仓库中 docker/observability/prometheus/prometheus.yml 展示了 Prometheus 的基础配置形态:

global: scrape_interval: 15s evaluation_interval: 15s rule_files: - alerts/*.yml scrape_configs: - job_name: wukongim metrics_path: /metrics static_configs: - targets: - wk-node1:5001 - wk-node2:5001 - wk-node3:5001 labels: cluster: local-dev

三个 WuKongIM 节点统一暴露在:5001/metrics,抓取间隔 15 秒,并按cluster与节点维度打标签。配套告警规则位于 docker/observability/prometheus/alerts/wukongim-channel-runtime.yml,定义了三级 channel 运行时容量告警:

告警名触发条件for时长级别
WKChannelRuntimeCapacityHigh节点wukongim_channel_active_channels占wukongim_channel_max_channels比例 > 0.810mwarning
WKChannelRuntimeCapacityCritical同上比例 > 0.95mcritical
WKChannelRuntimeActivationRejected5 分钟内出现wukongim_channel_activation_rejected_total{reason="too_many_channels"}增量 > 02mwarning

这类容量告警与 ADR 0046(将资源饱和报告为容量告警而非故障)的思路一致:高利用率是有效观测信号,用于分析归因而不是直接判负。

2.2 云端部署形态:systemd 单元与保留参数

云端场景中,Prometheus 的 systemd 单元由部署模板生成。internal/usecase/clouddeploy/templates.go 中的渲染结果为:

/opt/wukongim/bin/prometheus --config.file=/etc/wukongim/prometheus.yml \ --storage.tsdb.path=/var/lib/wukongim-cloud/prometheus \ --storage.tsdb.retention.time=96h \ --storage.tsdb.retention.size=150GB

即 TSDB 数据落在/var/lib/wukongim-cloud/prometheus,时间保留 96 小时、大小上限 150GB。另一套云仿真模板 internal/infra/cloudsim/deploy/templates.go 则把--storage.tsdb.retention.time参数化(%s占位由场景时长推导),并在启动参数中附带--web.external-url与--web.route-prefix=/,从源码结构看这是为了配合公共查看入口(public view)的 URL 前缀路由。

部署包渲染入口在 internal/infra/cloudsim/deploy/bundle.go 的Render方法:它校验静态二进制(wukongim、wkcli、wkanalysis、prometheus、node_exporter,启用 public view 时再加wkcloudview)齐备后,写出确定性的角色配置、config/prometheus.yml、config/target.yaml、worker 配置以及一组 systemd 单元,其中还包括scripts/wukongim-cgroup-metrics.sh这个 cgroup 指标采集脚本——与 0014 中"host-observation 二进制以原生服务运行"的描述吻合。宿主机指标侧则由node_exporter提供,其单元在 internal/usecase/clouddeploy/templates.go 中监听0.0.0.0:9100并启用 textfile collector 目录。

设计与实现的一致性还可从internal/usecase/clouddeploy/bundle_test.go中确认:测试显式断言了systemd/prometheus.service、systemd/node-exporter.service、systemd/wkanalysis.service、systemd/wkbench-host-metrics.service等单元的存在(见 internal/usecase/clouddeploy/bundle_test.go)。

三、日志策略:源节点有界轮转 + 本地 journald

3.1 应用日志:zap + lumberjack 的有界轮转

ADR 0022 的第一条实现落点是"结构化应用日志在源节点保持有界并轮转"。WuKongIM 的日志架构设计见 docs/raw/logging-architecture.md:日志在应用入口(internal/app/build.go)一处初始化,支持按级别分文件(INFO 主日志 / ERROR 错误日志 / DEBUG 调试日志),底层基于 zap + lumberjack。

轮转参数默认值在 internal/log/config.go 中定义并做了归一化:

参数默认值含义
MaxSize100单个日志文件达到多少 MB 后轮转
MaxAge30轮转文件最多保留多少天
MaxBackups10每类日志最多保留多少个轮转文件

写出器封装在 internal/log/writer.go,直接构造lumberjack.Logger并传入上述三项。接口层定义在pkg/wklog/(Logger接口、Field类型、NopLogger),业务包如pkg/cluster、pkg/slot只依赖接口而非 zap 实现。这套"接口层 + 实现层"的分层,使得各节点上日志天然只落本地磁盘、尺寸有界,无需任何集中式日志管道——这正是 0022 决策得以成立的前提。

3.2 任务审计与诊断事件:内存中的配额保留

"有界"不只体现在文件日志上。Controller 的任务审计历史由internal/observability/taskaudit包实现,其保留策略在 internal/observability/taskaudit/retention.go 中:

  • enforceEventRetentionLocked:当单任务事件数超过MaxEventsPerTask时,按事件时间升序丢弃最旧的事件,并把对应快照标记Truncated = true;
  • enforceTaskRetentionLocked:当快照总数超过MaxTasks时,按LastAppliedRaftIndex(相同则按 TaskID)排序,整体淘汰最旧的任务及其全部事件。

即每一类审计数据都带有明确的"每任务事件上限 + 全局任务数上限"双配额。诊断事件侧的internal/observability/diagnostics包则提供事件存储、索引与采样器(store.go、index.go、sampler.go),共同构成 Analysis MCPdiagnostics_query工具背后的"bounded retained"数据源。

3.3 仿真器服务日志与引导失败的归属

ADR 0022 还划分了两类"非应用日志"的归属:

  • 仿真器自身托管的服务(wkbench、Analysis MCP、Prometheus 等 systemd 单元):其日志通过 systemd 集成进入仿真器本机 journald,Analysis MCP 直接从本地 journald 查询。由于这些服务都跑在仿真器一台主机上,"本地 journald 查询"不需要任何跨主机日志网络。
  • Provisioning(预置)阶段的 bootstrap 失败:保留在 Provisioning Workflow 自身的 summary 中。这意味着"环境没起来"这一类失败不需要进入观测面就能被定位——观测面只服务"环境已起来之后的负载诊断",这与 ADR 0047(跨部署修复保留同一个 lease)中"引导/部署失败先于负载诊断"的阶段划分相互衔接。

这一设计在 docs/superpowers/specs/2026-07-14-cloud-simulation-github-actions-design.md 的 "Live Observability Plane" 一节中有对应的成文描述,与本 ADR 一一对应:仿真器托管 Prometheus 并抓取全部三个 WuKongIM 节点加四台宿主机指标导出器;WuKongIM 结构化日志在原节点轮转;Run 释放后不再支持进一步诊断。

四、聚合入口:Analysis MCP 的受界工具面

ADR 0022 的中心动作是"Analysis MCP 聚合多个观测面"。其 HTTP 端点实现于 internal/access/cloudanalysismcp/handler.go:以 run-scoped bearer token(≥32 字节随机凭据、带过期时间)做认证,绑定唯一的 Run Identity,并通过严格工具白名单注册工具。工具清单(与 ADR 0028 的窄契约一致)为:

工具作用标注
run_inspect证明精确的 Run 身份与当前 live / released 清单状态只读
cluster_snapshot读取有界的集群节点与 workqueue 聚合快照只读
workload_inspect运行中读有界 worker 连接诊断;完成后读最终 wkbench 汇总、阶段窗口与结构化失败只读
metrics_query_range按服务器白名单的query_id查询一个低基数 Prometheus 信号的时间范围只读
logs_search/logs_context在单个白名单集群节点上检索有界应用日志 / 围绕不透明游标读一页只读
diagnostics_query/task_audits_query查询有界保留的诊断事件 / Controller 任务审计只读
trace_start/trace_query安装一条会过期的单节点诊断跟踪规则(TTL 1–900s)/ 读取某条精确 trace 的有界事件活动
profile_capture/profile_top/profile_list在单个白名单节点抓一次有界 CPU/heap/goroutine profile / 符号化 top 行摘要 / 列出 gateway 拥有的 profile 元数据活动/只读
config_read_redacted读取单节点白名单且已脱敏的生效配置只读

其中与 0022 直接相关的两个细节:

  1. metrics_query_range不暴露任意 PromQL:请求体(见 internal/access/cloudanalysismcp/handler.go)要求提供服务器白名单标识符query_id(如投递管道的delivery_recipient_authority_resolve_rate及其有界的 item / target / group / shard / rejected / rollback / P99 伴随指标),外加 RFC3339 起止时间与step_seconds。也就是说"聚合 Prometheus 查询"落在服务器侧预定义的低基数信号集上,调用方无法构造任意查询——这与 ADR 0017 "在 Analysis MCP 内限制活动诊断" 的精神一致。
  2. 每个 Observation 都带统一信封:RunID、Node、Source、ObservedAt、Window、Completeness、Warnings、Data(见 internal/access/cloudanalysismcp/handler.go)。这保证了无论数据来自 Prometheus、应用日志、journald、诊断事件还是 task-audit,聚合结果都携带来源、时间窗与完整性标注,Agent 可以判断"这个证据是全量还是被截断的"。

需要区分的是,仓库里另有一套本地运维用的 Ops MCP(pkg/metrics/opsmcp.go 为其提供低基数请求/并发指标,如wukongim_ops_mcp_requests_total、wukongim_ops_mcp_request_duration_seconds),其工具集(cluster_health、slot_inspect、pprof_analyze等)与云端 Analysis MCP 不同。从源码结构看,两者是同一"受界 MCP 工具 + 结果指标化"模式在本地运维与云端仿真两个入口上的分别落地。

五、容量设定:保留期、日志配额与磁盘预检

ADR 0022 的最后一句规定了尺寸设定的方法:metrics 保留期、日志配额与磁盘预检按"工作负载时长 + Analysis Grace"取定。结合仓库证据可以把它拆开看:

  1. metrics 保留期。Prometheus TSDB 的retention.time由场景推导(internal/infra/cloudsim/deploy/templates.go 中参数化渲染),云端部署模板中另设置了retention.size=150GB的硬性大小上限兜底。结合 ADR 0021 的时长档位(最长 48h 负载 + 最长 6h Grace,另有有界的 bootstrap 允许时间),可以推断保留窗口需覆盖最坏情况下的完整 Run 区间,同时受大小上限约束;仓库中 96h 的固定值出现在另一部署模板(internal/usecase/clouddeploy/templates.go),对应 chat-lifecycle 流的 96 小时正式 Cloud Lease 上限(ADR 0041)。
  2. 日志配额。即第三节所述的有界机制:文件日志由MaxSize/MaxAge/MaxBackups限定(默认 100MB / 30 天 / 10 份),task-audit 由MaxEventsPerTask/MaxTasks双配额限定,诊断事件由diagnostics包的有界存储与采样器限定。
  3. 磁盘预检。部署侧把磁盘健康作为一等失败类别:internal/usecase/clouddeploy/deployment.go 定义了MinimumSystemDiskBytes = 40_000_000_000(40GB 系统盘下限),并定义了FailureDiskMount(data_disk_mount_invalid)、FailureDiskCapacity(filesystem_capacity_insufficient)、FailureDiskFree(filesystem_free_space_low)三个磁盘预检失败码;实例规划阶段还会校验每台主机恰好挂载一块与角色匹配的数据盘(见 internal/usecase/clouddeploy/deployment.go)。从源码结构看,这些检查在部署阶段先行拦截"磁盘不够放 Prometheus TSDB 与轮转日志"的情形,使保留期与日志配额不会在运行中被动击穿。

六、小结:为什么这套方案"够用且便宜"

把 ADR 0022 放回整个决策族中看,它的取舍逻辑非常清晰:

  • 观测需求是"单次 Run 内 + Grace 期内的实时诊断",而非长期历史分析,因此不需要 Loki / ELK 这类集中日志栈,也不需要跨 Run 存储——Run 释放后不再支持进一步诊断,证据的"保鲜期"天然有界;
  • 基础设施全部原生 systemd + journald(ADR 0014),使"查服务日志"退化为仿真器本机的journalctl查询,省掉一个采集器组件、一条传输链路和一份部署依赖;
  • 聚合智能放在 Analysis MCP 的窄工具面上:Prometheus 侧只有服务器白名单查询,日志侧只有单节点有界检索,诊断/审计侧只有有界快照,所有 Observation 带完整性与来源标注——聚合的复杂度被封装在服务端,调用方(含 LLM Agent)拿到的始终是受约束、可核验的证据;
  • 容量维度被显式管理:保留期按负载时长 + Grace 推导、日志按配额轮转、磁盘在部署预检中先验拦截,三者共同保证"无集中日志栈"不会以失控的本地磁盘为代价。

对读者而言,如果要在本仓库中继续深入,建议的路径是:先读 docs/adr/0022-aggregate-live-observability-without-a-log-stack.md 及其直接依赖的 docs/adr/0014-run-cloud-services-as-native-systemd-units.md、docs/adr/0021-separate-workload-duration-from-analysis-grace.md、docs/adr/0017-bound-active-diagnostics-in-the-analysis-mcp.md、docs/adr/0028-expose-a-narrow-run-scoped-mcp-tool-contract.md,再看internal/access/cloudanalysismcp/、internal/observability/、internal/usecase/clouddeploy/与docker/observability/中对应的实现、模板与配置,即可完整还原这一观测面从部署渲染到诊断查询的全链路。

  • 即时通讯
  • 后端

【免费下载链接】WuKongIM

More than just IM 不只是即时通讯(IM)

项目地址:https://gitcode.com/gh_mirrors/wu/WuKongIM
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 13:25:25

后台开发面试真题解析:高并发与容灾能力实战

1. 这不是一场“面经复述”,而是一次后台开发能力的现场压力测试2020年夏天,我接到天美工作室群的面试邀约时,心里其实没底。不是因为技术储备不足,而是因为此前接触的后台开发面试,大多聚焦在八股文背诵、算法题速刷和…

作者头像 李华
网站建设 2026/10/21 9:30:03

嵌入式面试必问:UART、I2C、SPI串行协议全解析

1. 三剑客全景概览:为什么面试官总爱问这些做嵌入式开发的,面试时几乎绕不开这三个协议:UART、I2C、SPI。我在技术社区分享过不少招聘面经,发现面试官考串行协议并不是为了刁难人,而是这三兄弟确实是板级通信的基石——…

作者头像 李华
网站建设 2026/10/23 4:25:51

PSE认证菱形和圆形两种标识有什么区别,跨境卖家怎么判断?

PSE菱形和圆形标识的核心区别,不在于外观或“安全等级高低”,而在于产品是否属于日本《电气用品安全法》规定的特定电气用品。菱形通常对应监管要求更严格、需要第三方适合性检查的产品;圆形通常对应非特定电气用品,企业完成规定的…

作者头像 李华
网站建设 2026/10/23 7:26:45

双向放大器BDA从原理到选型:射频盲区覆盖与工程调试实战

1. 从一个让人头疼的信号盲区说起如果你在地下室、隧道、大型商场或者偏远厂区待过,大概率遇到过这种情况:手机信号格数看着还行,但电话打不出去、消息发不出去、刷个网页转半天圈。这不是运营商基站没建,而是信号在传播过程中被建…

作者头像 李华
网站建设 2026/10/22 14:33:46

STM32 SPI寄存器详解:从协议原理到驱动实战

这篇是《STM32寄存器白话手册》的第五章。前四章一路读下来,你应该已经把LED点亮、把系统时钟理清楚、也知道了寄存器操作和中断是怎么回事。这一章我选择讲SPI。它在通信场景里出场率极高,和USART比,它的时序更固定、逻辑更简单,…

作者头像 李华
网站建设 2026/10/17 12:13:55

国产车规芯片如何从OBC/DCDC切入?第一桶金实战指南

做车规芯片这些年,总被人问一个很现实的问题:“国产芯片想上车,第一笔单子该从哪个方向打?”我给的答案一直很一致:OBC/DCDC。车载充电机和隔离DC/DC变换器,听起来都是高压、大功率、强隔离,好像…

作者头像 李华