Performance Co-Pilot (PCP) 深度详解
一、PCP 的核心理念:为什么它如此特别
Performance Co-Pilot 与其他监控工具的根本区别在于它的抽象层次。多数监控工具要么关注系统层(如 sar、iostat),要么关注应用层(如 JMX、应用内埋点),而 PCP 的设计目标是在这两者之间建立一个统一的性能指标抽象层。
这个抽象层带来的直接好处是:无论指标来自 Linux 内核、PostgreSQL 数据库,还是自定义的 Java 应用,客户端工具(命令行、Grafana、API)都以完全相同的方式访问它们。你不需要为每种数据源学习不同的查询方式。
PCP 于 1990 年代由 SGI(硅谷图形公司)开发,用于监控其高性能图形工作站和超级计算机。后来由 Red Hat 接手维护并开源,如今已成为企业级 Linux 发行版中默认集成的监控框架之一。
二、架构的完整拆解
2.1 采集层:PMCD 与 PMDA 的协作机制
pmcd(Performance Metrics Collector Daemon)是 PCP 采集层的调度中枢,但它本身不采集任何指标。真正干活的是 PMDA(Performance Metrics Domain Agent)——每个 PMDA 负责一个特定“域”的指标提取。
PMDA 有两种实现形态:DSO(动态共享对象) 和守护进程。DSO 形态的 PMDA 被直接加载进 pmcd 进程空间,调用开销极低,适合内核指标这类高频采集场景。守护进程形态的 PMDA 独立运行,通过 PDU 协议与 pmcd 通信,适合需要隔离风险或使用不同编程语言实现的场景(如 Python 或 Perl 编写的自定义 PMDA)。
pmcd 内部维护着一个性能指标命名空间(PMNS,Performance Metrics Name Space)。这是一个层级化的树状结构,所有指标都有唯一的路径名,例如 kernel.all.load、disk.partitions.write、postgresql.connections。当客户端请求一个指标时,pmcd 解析路径名,确定它属于哪个 PMDA 域,然后路由请求并聚合结果。
2.2 PMDA 生态的实际规模
PCP 随发行版提供的 PMDA 数量远超一般用户的预期。仅 Red Hat 企业版中启用的核心 PMDA 就涵盖了以下领域:
- 内核与系统:
linux(CPU、内存、磁盘、网络、文件系统)、kernel(负载、上下文切换、中断) - 数据库:
postgresql、mysql、redis - Web 与中间件:
apache、nginx、activemq - 存储与网络:
gluster、bonding、named(DNS) - 可观测性集成:
bcc(eBPF)、bpftrace - 应用特定:Foreman 的
fm_rails_*指标、Ansible 自动化平台的自定义指标
这意味着在许多场景下,你不需要编写任何代码就能获得应用层的监控数据——只要安装并配置对应的 PMDA 即可。
2.3 PMDA 的两种数据流模式
PMDA 不只有“拉取”(pull)一种模式。pmstore 机制允许指标值被推送到 PMDA 中。这为以下场景打开了可能性:
- 外部系统(如作业调度器)将状态指标写入 PCP,供后续监控和归档
- 管理员通过
pmstore动态调整某些 PMDA 的采集行为 - 应用将运行时事件以指标形式注入 PCP
pmcd.conf 中的 store 操作权限可以精确控制哪些客户端被允许写入指标值。由于 store 操作可能成为安全漏洞,默认配置通常只允许本地连接执行。
三、归档系统:PCP 的“时间机器”
3.1 归档文件的内部结构
pmlogger 创建的归档不是单个文件,而是一组至少三个文件的集合:
| 文件 | 内容 |
|---|---|
archive.0、archive.1… | 指标值的时序数据,按卷分割 |
archive.meta | 指标元数据:描述、单位、实例域 |
archive.index | 时间索引,支持快速定位任意时间点 |
这种分离设计的关键优势是:元数据只存一次。无论归档跨越多长时间,客户端都能快速获取指标的定义和语义,而无需在每个数据点中重复存储。
归档文件支持双向时间游标——你可以从归档末尾向前回放,也可以从中间任意点开始。这对于故障排查极其有用:你可以定位到故障发生前的几分钟,逐秒回放系统状态的变化。
3.2 自动归档管理
pmlogger_daily 服务每天午夜后运行,执行以下操作:
- 将当前归档与前一日的归档聚合
- 压缩归档文件(PCP 归档的压缩比约为 10:1)
- 删除超过保留期限(默认 14 天)的旧归档
pmlogger_check 每半小时运行一次,检查 pmlogger 实例是否存活,必要时重启它。这意味着即使 pmlogger 进程意外终止,系统也能在 30 分钟内自动恢复采集。
四、部署架构的量化选择
4.1 四种架构的适用边界
| 架构 | 适用主机数 | 核心特征 |
|---|---|---|
| Localhost | 1-10 | 所有服务本地运行,无跨节点分析能力 |
| 分散式 | 10-100 | 本地 pmlogger + 本地 pmproxy,指标导出到中央 Redis |
| 集中式(pmlogger farm) | 100-1000 | 单台日志主机运行多个 pmlogger,从远程 pmcd 拉取 |
| 联邦式 | 1000+ | 多个 pmlogger farm,各自向中央 Redis 集群写入 |
4.2 集中式部署的实际配置
在集中式日志记录中,一台“日志主机”通过 /etc/pcp/pmlogger/control.d/remote 文件定义要监控的远程主机列表:
# 格式:主机名 是否本地 是否远程 归档目录 配置名称
192.168.4.13 n n PCP_ARCHIVE_DIR/thel7u4a-r-T24h10m-c config.rhel7u4a
192.168.4.14 n n PCP_ARCHIVE_DIR/thel6u10a-r-T24h10m-c config.rhel6u10a
日志主机上的 pmproxy 服务会发现这些归档文件,并将其中的指标数据加载到 Redis 中,使 Grafana 等工具能够跨主机进行时序查询。
4.3 存储与资源的量化估算
以 60 秒日志间隔为例,PCP 官方提供的参考数据如下:
| 主机数 | 每日归档大小 | pmlogger 内存 | pmproxy 内存 | Redis 每日内存 |
|---|---|---|---|---|
| 10 | 20 MB | 104 MB | 2.67 GB | 0.54 GB |
| 50 | 120 MB | 524 MB | 5.5 GB | 2.65 GB |
| 100 | 271 MB | 1049 MB | 9 GB | 5.3 GB |
一个关键细节:是否记录 proc.* 指标对存储需求影响巨大。标准配置下 10 秒间隔约 11 MB/天,启用进程指标后飙升至 155 MB/天——相差近 15 倍。如果不需要逐进程监控,务必在 pmlogconf 中禁用该指标组。
五、安全模型
5.1 pmcd.conf 的访问控制语法
pmcd 的访问控制配置位于 pmcd.conf 中,语法灵活且粒度精细:
allow hosts babylon, moomba : all ;
disallow user sam : all ;
allow group dev : fetch ;
allow hosts 192.127.4.* : fetch ;
disallow host gate-inet : all ;
支持的操作类型包括 fetch(读取指标)和 store(写入指标值)。allow 语句还可以附加 maximum N connections 来限制单个客户端的并发连接数。
5.2 加密与认证
pmcd(默认端口 44321)和 pmproxy(默认端口 44322)支持同时接受 TLS 和非 TLS 连接,这意味着你无需为了启用加密而中断现有监控。
对于需要远程认证的场景,PCP 支持 SASL(Simple Authentication and Security Layer),可以对接 sasldb、Kerberos 等多种认证后端。对于本地连接,Unix 域套接字支持自动凭证传递——pmdaproc 等敏感 PMDA 只在通过 Unix 套接字连接且凭证验证通过时才返回进程信息,通过 TCP 连接时会返回 PM_ERR_PERMISSION。
六、工具链的完整覆盖
6.1 命令行工具分组
实时查询类:pmval(当前值)、pmprobe(快速探测)、pmrep(格式化报告,支持类似 sar 的输出)。
归档操作类:pmlogextract(提取、合并、拆分归档)、pmlogsummary(统计摘要)、pmdiff(比较两个归档中指标的变化差异)。
格式转换类:iostat2pcp、sar2pcp、collectl2pcp、ganglia2pcp 等工具可以将其他监控系统的历史数据导入 PCP 归档格式,pcp2graphite 和 pcp2pdf 则支持导出到 Graphite 或 PDF 报告。
6.2 推理引擎:pmie
pmie(Performance Metrics Inference Engine)是一个规则驱动的告警和自动化引擎。你可以编写如下的规则:
// 如果 5 分钟负载超过 CPU 数的 2 倍,触发告警
kernel.all.load #'5 minute' > 2 * hinv.ncpu -> alarm "高负载";
// 如果文件系统缓存命中率低于 80%,记录日志
summary.fs.cache_hit < 80 -> log "缓存命中率下降";
规则的动作不限于告警,还可以执行脚本、记录日志,或调用其他系统管理工具。pmie 可以针对实时 pmcd 运行,也可以针对归档运行——这意味着你可以在历史数据上回测告警规则,检查它们在过去的故障场景中是否会正确触发。
七、总结:PCP 的适用场景判断
PCP 最适合以下情况:
- 需要历史回溯分析:不仅是“现在发生了什么”,而是“三天前下午 2 点发生了什么”
- 多源指标统一管理:同时监控系统、数据库、中间件,需要统一的查询和可视化层
- 大规模部署:从几台服务器到数千节点的联邦架构
- 需要自定义指标:通过 PMDA 框架可以灵活接入私有应用
PCP 可能不是最佳选择的场景:
- 只需要最简单的实时告警,没有历史数据需求
- 已经重度依赖 Prometheus 生态,且不需要跨系统统一抽象层
- 资源极度受限的嵌入式环境(虽然集中式部署缓解了这个问题)