3. 资源消耗指标定义:CPU、内存、磁盘IO、网络带宽的关键指标、采集与监控方法
在Loki日志采集Agent的优化工程中,精确度量资源消耗是性能调优的起点。本章定义CPU、内存、磁盘IO、网络带宽四大维度的关键指标,并给出对应的采集与监控方法,确保优化前后有可量化的对比基准。
3.1 CPU关键指标与采集方法
CPU消耗直接影响Agent的吞吐能力和宿主应用的资源争抢程度。核心指标如下:
| 指标名称 | 单位 | 说明 | 采集工具/方法 |
|---|---|---|---|
| user CPU | % | Agent进程在用户态消耗的CPU百分比 | top / pidstat / /proc/[pid]/stat |
| system CPU | % | Agent进程在内核态(系统调用)消耗的CPU百分比 | top / pidstat / /proc/[pid]/stat |
| CPU 使用率峰值 | % | 1秒或5秒窗口内的最大CPU占用,反映突发负载 | prometheus node_exporter + rate() |
| 上下文切换次数 | 次/秒 | 进程主动或被动切换CPU上下文的频率,过高说明锁竞争或IO频繁 | pidstat -w / /proc/[pid]/status |
| CPU 亲和性偏移 | 无 | 进程是否被调度到指定核心,影响缓存命中率 | taskset / htop / /proc/[pid]/status |
优化关注点: 当
system CPU 占比超过 30% 时,说明Agent在内核态(文件读写、网络收发)消耗过高,应优先检查IO模型和缓冲区大小。
3.2 内存关键指标与采集方法
内存泄漏或过度分配会导致Agent被OOM Killer终止,或触发宿主Swap降级。关键指标如下:
| 指标名称 | 单位 | 说明 | 采集工具/方法 |
|---|---|---|---|
| RSS (Resident Set Size) | MB | 进程实际占用的物理内存,不包括Swap | ps aux / /proc/[pid]/status |
| VMS (Virtual Memory Size) | MB | 进程申请的虚拟内存总量,过大可能触发OOM | ps aux / /proc/[pid]/status |
| Heap 分配量 | MB | Go runtime堆内存分配量,反映对象生命周期 | runtime.ReadMemStats / pprof heap |
| GC 暂停时间 | ms | Go GC STW(Stop The World)暂停时长,影响日志处理延迟 | runtime.ReadMemStats / GODEBUG=gctrace=1 |
| 内存增长速率 | MB/小时 | RSS随时间的变化斜率,用于检测内存泄漏 | prometheus + process_resident_memory_bytes |
Go Agent 特别提示: 使用
pprof 采集堆快照,对比两个时间点的 inuse_space 差异,可快速定位未释放的对象类型。
3.3 磁盘IO关键指标与采集方法
磁盘IO是日志采集Agent最核心的瓶颈之一,尤其是日志轮转和批量写入场景。关键指标如下:
| 指标名称 | 单位 | 说明 | 采集工具/方法 |
|---|---|---|---|
| 磁盘读/写吞吐量 | MB/s | Agent进程每秒读取或写入磁盘的数据量 | iostat -x 1 / /proc/[pid]/io |
| IOPS (读写次数) | 次/秒 | 每秒完成的读写IO请求数,小文件场景关键 | iostat -x 1 / fio |
| IO 等待时间 (await) | ms | IO请求从发出到完成的平均等待时间,超过100ms说明磁盘繁忙 | iostat -x 1 |
| IO 队列深度 (avgqu-sz) | 无 | 等待处理的IO请求数量,队列深度持续>1说明磁盘饱和 | iostat -x 1 |
| 日志文件轮转触发频率 | 次/小时 | 日志文件被rename/truncate的频率,影响inotify监控开销 | inotifywait / auditd |
常见陷阱: 仅看磁盘吞吐量容易忽略IOPS瓶颈。当Agent监控大量小日志文件(如容器stdout)时,IOPS可能先于吞吐量达到上限,导致日志采集延迟。
3.4 网络带宽关键指标与采集方法
网络带宽决定Agent向Loki写入日志的吞吐上限,以及是否对宿主业务网络造成干扰。关键指标如下:
| 指标名称 | 单位 | 说明 | 采集工具/方法 |
|---|---|---|---|
| 出站带宽使用率 | Mbps | Agent发送日志到Loki占用的网络带宽 | iftop / nethogs / /proc/[pid]/net/dev |
| TCP 连接数 | 个 | Agent与Loki之间建立的TCP连接数量,过多增加内核开销 | ss -tan / netstat -tan |
| 重传率 | % | TCP数据包重传比例,超过1%说明网络质量差或带宽不足 | ss -i / tcpdump + wireshark |
| 请求延迟 (P99) | ms | 从发送日志到收到Loki ACK的P99延迟 | prometheus histogram + 客户端埋点 |
| 压缩比 | 无 | 原始日志大小 / 压缩后传输大小,影响带宽实际消耗 | Agent内部统计 + prometheus gauge |
3.5 四维指标监控架构图
下图展示Agent资源消耗监控的整体数据流:从操作系统接口采集原始指标,经过聚合、存储、告警,最终呈现到监控面板。
3.6 采集频率与精度权衡
采集频率过高会引入额外开销,过低则无法捕捉瞬时峰值。推荐配置如下:
| 指标维度 | 推荐采集间隔 | 精度说明 | 优化建议 |
|---|---|---|---|
| CPU / 内存 | 10秒 | 足够捕捉99%的突发负载 | 避免短于5秒,否则/proc读取竞争加剧 |
| 磁盘IO | 15秒 | IO等待时间变化较慢 | 配合iostat -x 1做离线诊断 |
| 网络带宽 | 10秒 | 重传率需要窗口统计 | 使用滑动窗口计算,避免单点抖动 |
| Go GC / Heap | 60秒 | GC暂停频率较低 | pprof采样间隔保持120秒以上 |
工程实践: 在Agent内部使用
prometheus.NewHistogram 记录采集操作本身的耗时,如果采集耗时超过间隔的 20%,则自动降低采集频率,防止监控反噬业务。
3.7 指标采集代码示例(Go)
以下代码展示如何在Go Agent中采集CPU和内存指标,并暴露为Prometheus格式:
package metrics
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/shirou/gopsutil/v3/process"
)
var (
cpuPercent = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "agent_cpu_percent",
Help: "Agent process CPU usage percentage.",
})
rssBytes = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "agent_memory_rss_bytes",
Help: "Agent process resident set size in bytes.",
})
)
func init() {
prometheus.MustRegister(cpuPercent, rssBytes)
}
// CollectProcessMetrics 每10秒采集一次进程指标
func CollectProcessMetrics(pid int32) {
p, err := process.NewProcess(pid)
if err != nil {
return
}
for {
cpu, _ := p.CPUPercent()
mem, _ := p.MemoryInfo()
cpuPercent.Set(cpu)
if mem != nil {
rssBytes.Set(float64(mem.RSS))
}
time.Sleep(10 * time.Second)
}
}
采集开销控制: 使用
gopsutil 库时,每次调用 CPUPercent() 会读取 /proc/[pid]/stat,建议在采集函数内加入 sync.Once 或缓存pid句柄,避免重复打开文件描述符。