浅谈filebeat实现日志采集

服务器日志采集是现代IT运维、监控和安全分析的重要环节,市面上也有很多非常成熟的工具和框架,类似Fluentd,Logstash,filebeat等等。当然,日志采集只是第一步,后续还需要对日志进行存储和分析,比较出名的ELK(Elasticsearch + Logstash + Kibana)就是非常成熟的全套方案,适合大规模日志搜索和分析。

Filebeat

官网地址:https://www.elastic.co/cn/beats/filebeat

介绍

  • Filebeat 是 Elastic 公司开发的一款轻量级日志数据收集器,属于 Beats 家族。它的核心功能是从各种来源采集日志或文件数据,并将这些数据高效地传输到指定的存储或分析系统(如 Elasticsearch、Logstash、Kafka 等)

Beats家族有不少成员,涉及很多方面的数据采集,比如Packetbeat收集网络流量数据,比如Metricbeat收集系统的CPU和内存使用数据......

  • Filebeat的重要特性:
    • 轻量高效:用 Go 编写,无 JVM 开销(相比 Logstash),资源占用低
    • 背压感知:如果输出目标(如 Elasticsearch)过载,Filebeat 会自动降低发送速率
    • 模块化 :通过模块(如 nginxmysql)快速集成常见服务,无需手动编写解析规则
    • 至少一次交付:确保数据至少发送一次(将每个事件的传递状态存储在注册表文件)

官网上写了,Filebeat 的至少一次交付存在限制,涉及日志轮换和旧文件的删除,如果日志文件写入磁盘并轮换的速度快于 Filebeat 处理的速度,或者在输出不可用时删除文件,则可能会丢失数据。在 Linux 上,Filebeat 还可能由于 inode 重用而跳过行

两个核心组件

官网配图:

在 Filebeat 中, 有两个核心组件:Inputs(输入)Harvesters(收集器),它们协同工作来完成日志数据的采集

  • Inputs 是 Filebeat 中用于 定义和配置数据来源 的组件,负责指定从哪里采集数据

  • Harvesters 是 Filebeat 的 实际数据采集工作单元,主要的工作就是读取文件

  • 一个Input可以对应多个 Harvesters

  • 一个文件只会对应一个Harvesters ,如果日志被轮转(如 nginx.lognginx.log.1),Harvester会关闭旧文件,并启动新的 Harvester 监控新文件

  • 每个Harvester独立运行,Filebeat 可以限制 最大 Harvester 数量(防止打开过多文件),如果不设置,则会尽可能多的的启用

ulimit是Linux系统中用于控制用户进程资源限制的一个机制,它定义了单个用户可以使用的系统资源上限,用ulimit -n可以看到当前用户打开文件数的限制,一般都是65535

步骤原理

shell 复制代码
+-------------------+       +-------------------+       +-------------------+
|                   |       |                   |       |                   |
|   日志文件         | → → → |   Filebeat        | → → → |   输出目标         |
|  (如Nginx/App日志) |       |                   |       |  (Elasticsearch/  |
|                   |       |                   |       |   Logstash/Kafka)  |
+-------------------+       +---------+---------+       +-------------------+
                                      ^
                                      |
                              +-------+-------+
                              |               |
                      +-------v-------+ +-----v-----+
                      |  输入阶段      | | 处理阶段   |
                      | (Input)       | | (Process) |
                      | - 监控文件变化 | | - 字段提取 |
                      | - 记录偏移量   | | - 多行合并 |
                      +-------+-------+ +-----+-----+
                              ^               |
                              |               |
                      +-------v---------------+-------+
                      |                           |
              +-------v-------+           +-------v-------+
              |  内存队列      |           |  磁盘队列      |
              | (Spooling)     |           | (可选缓冲)     |
              | - 批量聚合事件  |           | - 防崩溃持久化 |
              +-------+-------+           +---------------+
                      |
              +-------v-------+
              |  输出阶段      |
              | (Output)      |
              | - 负载均衡    |
              | - 加密/重试   |
              +---------------+
  1. 输入阶段(Input)
    • 文件发现 :根据配置的路径(如 /var/log/*.log)扫描文件,记录已发现的文件状态
    • 监控日志文件 :持续跟踪配置的日志文件(如 /var/log/nginx.log),通过注册表文件(registry)记录每个文件的读取位置(偏移量),之后只读取文件新增的内容(通过文件大小变化
    • 处理轮转文件 :自动识别日志轮转(如从 nginx.log 切换到 nginx.log.1),通过 inode 和文件名识别轮转后的新文件
  2. 处理阶段(Process)
    • 多行日志合并:如程序报错输出的堆栈信息,通过正则表达式将多行合并为单个事件
    • 内置模块:预配置了常见服务(如 Nginx、MySQL、Docker)的解析规则,也可以自动提取字段(如 HTTP 状态码、数据库查询时间)。
    • 支持自定义处理
      • 添加字段(可以自己增加一些)。
      • 删除敏感字段、过滤无关日志(通过条件判断)。
      • 转换数据格式(如 JSON 编码)。
  3. 队列缓冲(Spooling)
    • 内存队列 :Filebeat 不会逐条发送日志,而是将数据缓存在内存中(称为 spool),默认固定时间秒或达到 固定事件数时触发一次发送
    • 磁盘队列(可选):启用后,数据会持久化到磁盘,防止进程崩溃时丢失。
  4. 输出阶段(Output)
    • 负载均衡:轮询多个目标主机(如 Elasticsearch 集群节点)。
    • 重试机制:网络故障时自动重试,确保数据可靠传输。
    • 压缩与加密:支持 TLS 加密和 Gzip 压缩。

安装

参考官网:https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-installation-configuration.html

shell 复制代码
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.17.4-linux-x86_64.tar.gz

tar xzvf filebeat-8.17.4-linux-x86_64.tar.gz

解压后文件目录是:

复制代码
.
├── fields.yml
├── filebeat
├── filebeat.reference.yml
├── filebeat.yml
├── kibana
├── LICENSE.txt
├── module
├── modules.d
├── NOTICE.txt
└── README.md

Demo1:开始采集

  • 因为是demo,出于方便性,这里直接输出到本地文档,后面的demo都是输出本地文档
  • 此处以及后面的demo都包含了笔者自己的想法,一定一定一定要辩证看待
  • 新建一个filebeat-demo1.yml,用下面的配置(原本的配置中有些处理器规则和ES配置,暂时用不到)
yml 复制代码
filebeat.inputs:
# Filebeat的一种输入类型,适合监控文件变化
- type: filestream
# 唯一标识符,用于区分多个输入源(在多个 filestream 配置时必需)
  id: my-filestream-id
# 启用此输入配置(如果为 false 则不会采集日志)
  enabled: true
# 指定要监控的日志文件路径
  paths:
    - /home/xxx/dev_logs/adspyhub_api/*.log

# 输出配置
output.file:
  path: "/home/xxx/dev_logs/filebeat"   
  filename: "demo1.log"       
# 定义日志格式,string: '%{[message]}' 表示仅输出原始日志内容(不添加元数据)
  codec.format:                 
    string: '%{[message]}'
  • ./filebeat -e -c ./filebeat-demo1.yml: 执行,如果指定目录没有看到输出文件,可以多等会,或者多打些日志触发输出!

  • 这里采集的是全部数据,没做任何处理,等于将log原封不动的存到demo1.log

  • 我们定义的filenamedemo1.log,但实际上看到的输出文件是demo1.log-20250331.ndjson`

    • Filebeat 的 output.file 默认会按 时间或大小 自动轮转日志文件,生成带时间戳的新文件。
    • .ndjson 后缀表示文件内容是 Newline-Delimited JSON(每行一个记录),这是 Filebeat 的默认输出格式。
  • 上面命令执行后,控制台能看到一大串输出,是 Filebeat 的 监控日志 ,记录了 Filebeat 自身的运行状态和性能指标(如果想关闭的话,在配置中设置monitoring.enabled: false),下面我截取了一部分看看:

    • log.logger: "monitoring":表示这是监控模块的日志。
    • message: "Non-zero metrics in the last 30s":说明这是过去 30 秒的非零指标汇总。(默认每 30 秒输出一次)
    • CPU 使用率 = total.time.ms / (30s * 1000) * 100% = 20ms / 30000ms * 100% ≈ 0.07%:(极低)
    • 内存占用 ≈ rss / 1024 / 1024 ≈ 64.4 MB
    • filebeat.events.added: 5: 过去 30 秒新增 5 个日志事件
    • filebeat.events.done: 5:已处理完成 5 个事件(无积压
    • filebeat.harvester.running: 2:当前有 2 个 Harvester 在运行(每个文件一个)
    • libbeat.output.events.acked: 5:成功发送到输出目标(这里是指定文件)的事件数。(无事件积压,吞吐正常)
    • libbeat.output.write.bytes: 1689:输出的总字节数。
    • libbeat.pipeline.queue.max_events: 3200:内存队列最大容量(事件数)。
    • system.load:这里面记录了系统本身的负载,主机负载较高(这里计算比较复杂,我在附录中介绍),但未影响 Filebeat
    • beat.info.uptime.ms: 330086:Filebeat 已运行 330 秒(约 5.5 分钟)。
    • registrar.states.current: 0:当前注册的日志文件状态数(无持久化)。
    json 复制代码
    {
        "log.level": "info",
        "@timestamp": "2025-03-31T16:22:35.304+0800",
        "log.logger": "monitoring",
        "log.origin": {
            "function": "github.com/elastic/beats/v7/libbeat/monitoring/report/log.(*reporter).logSnapshot",
            "file.name": "log/log.go",
            "file.line": 192
        },
        "message": "Non-zero metrics in the last 30s",
        "service.name": "filebeat",
        "monitoring": {
            "metrics": {
                "beat": {
                    "cgroup": {
                        "cpuacct": {
                            "total": {
                                "ns": 21628431718
                            }
                        },
                        "memory": {
                            "mem": {
                                "usage": {
                                    "bytes": 11737444352
                                }
                            }
                        }
                    },
                    "cpu": {
                        "system": {
                            "ticks": 80,
                            "time": {
                                "ms": 10
                            }
                        },
                        "total": {
                            "ticks": 230,
                            "time": {
                                "ms": 20
                            },
                            "value": 230
                        },
                        "user": {
                            "ticks": 150,
                            "time": {
                                "ms": 10
                            }
                        }
                    },
                    "handles": {
                        "limit": {
                            "hard": 65535,
                            "soft": 65535
                        },
                        "open": 12
                    },
                    "info": {
                        "ephemeral_id": "153b748f-4b14-4e24-8754-93da1b4c2185",
                        "uptime": {
                            "ms": 330086
                        },
                        "version": "8.17.4"
                    },
                    "memstats": {
                        "gc_next": 35294704,
                        "memory_alloc": 17763872,
                        "memory_total": 39110464,
                        "rss": 67510272
                    },
                    "runtime": {
                        "goroutines": 34
                    }
                },
                "filebeat": {
                    "events": {
                        "active": 0,
                        "added": 5,
                        "done": 5
                    },
                    "harvester": {
                        "closed": 2,
                        "open_files": 2,
                        "running": 2,
                        "started": 2
                    }
                },
                "libbeat": {
                    "config": {
                        "module": {
                            "running": 0
                        }
                    },
                    "output": {
                        "events": {
                            "acked": 5,
                            "active": 0,
                            "batches": 1,
                            "total": 5
                        },
                        "write": {
                            "bytes": 1689,
                            "latency": {
                                "histogram": {
                                    "count": 5,
                                    "max": 0,
                                    "mean": 0,
                                    "median": 0,
                                    "min": 0,
                                    "p75": 0,
                                    "p95": 0,
                                    "p99": 0,
                                    "p999": 0,
                                    "stddev": 0
                                }
                            }
                        }
                    },
                    "pipeline": {
                        "clients": 2,
                        "events": {
                            "active": 0,
                            "published": 5,
                            "total": 5
                        },
                        "queue": {
                            "acked": 5,
                            "added": {
                                "events": 5
                            },
                            "consumed": {
                                "events": 5
                            },
                            "filled": {
                                "bytes": 0,
                                "events": 0,
                                "pct": 0
                            },
                            "max_bytes": 0,
                            "max_events": 3200,
                            "removed": {
                                "events": 5
                            }
                        }
                    }
                },
                "registrar": {
                    "states": {
                        "current": 0
                    }
                },
                "system": {
                    "load": {
                        "1": 1.87,
                        "15": 3.75,
                        "5": 2.69,
                        "norm": {
                            "1": 0.935,
                            "15": 1.875,
                            "5": 1.345
                        }
                    }
                }
            },
            "ecs.version": "1.6.0"
        }
    }

Demo2:日志改名

之前有想过问题:日志被改名了,Harvester会怎样,还能读取日志吗?

官网上的原话是:Because files can be renamed or moved, the filename and path are not enough to identify a file. For each file, Filebeat stores unique identifiers to detect whether a file was harvested previously.

我在AI和一些博客上面看的的说法是,日志被改名了,Harvester仍然运行,还能继续读取日志,原因是filebeat的注册表通过**inodedevice_id**:唯一标识文件,不管怎么样,实践下


  1. 新建一个filebeat-demo2.yml,用下面的配置
yml 复制代码
filebeat.inputs:
- type: filestream
  id: my-filestream-id
  enabled: true
  paths:
    - /home/xxx/dev_logs/demo2/test.log

filebeat.config.modules:
  path: ${path.config}/modules.d/*.yml
  reload.enabled: false


output.file:
  path: "/home/xxx/dev_logs/filebeat"   
  filename: "demo2.log"       
  codec.format:                 
    string: '%{[message]}'
  1. test.log里面随便初始化点内容,启动:./filebeat -e -c ./filebeat-demo2.yml:
  2. 需要提前记录下iNode:ls -i test.log ,这里输出了13012064 test.log
  3. 用mv命令修改test.log的名字为test1.log,并随便补充内容(echo "新增的内容" >> test.log,不要用vim,vim保存会删除旧文件,创建新文件),再次观察iNode,仍然是13012064 test1.log
  4. 结果发现日志并没有采集!!!

个人推测:

  • 可能是版本原因,老版本是这样的,有条件可以再验证

  • 可能是我指定了一个明确的路径,后面可以结合轮转再看看

  • Filebeat 的 filestream 输入类型通过 多因素组合 来唯一标识文件,文件路径也是很重要的影响因素,依据如下

    • 我们打开data/registry/filebeat/log.json,一般是这个路径,是 Filebeat注册表 的 日志,随便找一行看看,发现source中明显记录了路径
    json 复制代码
    {
        "k": "filestream::my-filestream-id::native::13012064-64785",
        "v": {
            "updated": [
                2062507668637,
                1743421740
            ],
            "cursor": {
                "offset": 37
            },
            "meta": {
                "source": "/home/xxx/dev_logs/demo2/test.log",
                "identifier_name": "native"
            },
            "ttl": 0
        }
    }

结论:日志改名会影响采集

Demo3: 日志轮转

  • filebeat.yml文件配置为:
yml 复制代码
filebeat.inputs:
- type: filestream
  enabled: true
  paths:
    - /home/xxx/dev_logs/demo3/*.log*      # 监控所有轮转文件
  close.on_state_change.inactive: 3m  # 1分钟不活跃后关闭文件收集器
  ignore_older: 2h             # 忽略超过2小时的旧文件


output.file:
  path: "/home/xxx/dev_logs/filebeat"   
  filename: "demo3.log"       
  rotate_every_kb: 1024       # 输出文件达到1MB后轮转
  codec.format:                 
    string: '%{[message]}'
  • python脚本为:
python 复制代码
import logging
import time
from logging.handlers import TimedRotatingFileHandler


# 配置日志轮转(每分钟)
logger = logging.getLogger("demo_logger")
logger.setLevel(logging.INFO)

handler = TimedRotatingFileHandler(
    filename=f"app.log",
    when="M",          # 每分钟轮转
    interval=1,        # 间隔1分钟
    backupCount=5,     # 保留5个历史文件
)
handler.suffix = "%Y%m%d_%H%M.log"  # 轮转文件名格式(如 app.log_20250331_1422.log)
logger.addHandler(handler)

# 模拟持续写入日志
count = 0
while True:
    logger.info(f"This is a test log line {count} (INFO level).")
    if count % 3 == 0:
        logger.error(f"Error occurred: something went wrong {count}!")
    count += 1
    time.sleep(10)  # 每10秒写一条日志(方便观察轮转效果)
  • 多等一会,发现生成了多个日志

    复制代码
    .
    ├── app.log
    ├── app.log.20250331_2037.log
    ├── app.log.20250331_2038.log
    ├── app.log.20250331_2039.log
    ├── app.log.20250331_2040.log
    ├── app.log.20250331_2041.log
    ├── app.log.20250331_2042.log
    └── test.py
  • 通过监控日志观察harvesterrunning数量依次为1,2,3,4,4,而closed的数量依次为0,0,0,0,1

  • 日志中有一条记录,如下,大致意思就是app.log这个文件的harvester关闭了

json 复制代码
{
    "log.level": "info",
    "@timestamp": "2025-03-31T20:42:52.063+0800",
    "log.logger": "input.filestream",
    "log.origin": {
        "function": "github.com/elastic/beats/v7/filebeat/input/filestream.(*filestream).readFromSource",
        "file.name": "filestream/input.go",
        "file.line": 367
    },
    "message": "Reader was closed. Closing. Path='/home/xxx/dev_logs/demo3/app.log'",
    "service.name": "filebeat",
    "id": "198A799FBD3BD5DB",
    "source_file": "filestream::.global::native::13150956-64785",
    "path": "/home/xxx/dev_logs/demo3/app.log",
    "state-id": "native::13150956-64785",
    "ecs.version": "1.6.0"
}

关键点: close.on_state_change.inactive 确保及时释放已轮转文件的句柄。

Processer: 处理器

这里引入了一个新的概念,Processor(处理器), 是用于在日志数据发送到输出目标(如 Elasticsearch、文件等)之前,对数据进行实时转换、过滤或增强的组件。它们构成了 Filebeat 数据处理管道的核心部分,允许用户在数据采集阶段实现灵活的定制化处理。


  • 每条日志会被封装为一个 事件(Event) 对象,包含:
    • 原始消息(message
    • 元数据(如 @timestamphost.name
    • 自定义字段(通过处理器添加或修改)
  • Processor 通过修改事件来实现数据处理。
  • Processor按配置的 声明顺序 依次执行,每个处理器接收上一个处理器的输出作为输入

官方文档中写的processer非常多,大概有三四十个,覆盖了多种功能

  • 字段操作类
    • add_fields:添加静态字段(如标记数据来源)
    • drop_fields:删除指定字段
    • include_fields:仅保留指定字段(白名单)
  • 数据解析类
    • dissect:通过分隔符提取字段(高性能,适合简单结构化日志)
    • grok:通过正则表达式提取复杂字段(灵活但耗资源)
  • 条件判断类
    • if-then-else:根据条件执行不同处理器

Demo4: 使用dissect解析格式化日志

  • dissect处理器主要用于处理格式化的日志,属于非常常用的处理器,他有如下几种配置设置
yml 复制代码
processors:
  - dissect:
      tokenizer: %{key1}-%{key2}-%{key3|convert_datatype}
      field: "message"
      target_prefix: "parsed"
      ignore_failure: false
      overwrite_keys: true
  • tokenizer(必填 ):定义字段的格式,示例中,日志的不同字段用-隔开,可以使用其|作为分隔符将值转换为指定类型
  • field:要标记化的事件字段。默认值为message,就是原始字段
  • target_prefix:为解析后的字段添加统一前缀,避免命名冲突。
  • ignore_failure:用于控制当标记器无法匹配消息字段时处理器是否返回错误。如果设置为 true,处理器将默默恢复原始事件,从而允许执行后续处理器(如果有)。如果设置为 false(默认),处理器将记录错误,从而阻止执行其他处理器。
  • overwrite_keys:是否覆盖目标字段中已存在的值
  • trim_values:启用对提取的值的修剪。有助于删除前导和/或尾随空格
    • none:(默认)不进行修剪。
    • left:值在左侧被修剪(前导)。
    • right:值在右侧(尾随)被修剪。
    • all:修剪前导和尾随的值。
  • trim_chars:启用修剪功能时,要从值中修剪的字符集。默认为修剪空格字符 ( " ")。要修剪多个字符,只需将其设置为包含要修剪的所有字符的字符串。例如, trim_chars: " \t"将修剪空格和/或制表符。

  • 现有日志格式如下,假设需求是,

    • INFO日志舍弃

    • 其余级别的日志,保留1,2,3,6,7列的信息

    • 额外增加my_log_processor的前缀,标记下这是自己的项目

      2025-03-31 08:22:01.048 | 16641 | ERROR | other_utils.get_country_from_ip:78 | df139a576db44845bd6b7efaeadcc644 | post | /napi/v1/advanced-analysis | division by zero | -
      2025-03-31 08:22:01.056 | 16641 | INFO | user_middleware.dispatch:153 | df139a576db44845bd6b7efaeadcc644 | get | /napi/v1/list | division by zero | -
      2025-03-31 08:22:01.057 | 16641 | WARNING | l:wqog_middleware.dispatch:123 | df139a576db44845bd6b7efaeadcc644 | post | /napi/v1/detail | division by zero | -

  • filebeat.yml文件配置为:

yml 复制代码
filebeat.inputs:
- type: filestream
  enabled: true
  paths:
    - /home/xxx/dev_logs/demo4/*.log

processors:
  # 1. 先添加全局字段(放在最前)
  - add_fields:
      target: ""  # 添加到事件根级别
      fields:
        name: "my_log_processor"

  # 2. 解析原始日志
  - dissect:
      tokenizer: "%{timestamp} | %{thread_id} | %{log_level} | %{module} | %{trace_id} | %{http.method} | %{http.path} | %{error_msg} | %{status}"
      field: "message"
      target_prefix: "parsed"

  # 3. 最后过滤日志(避免影响字段添加)
  - drop_event:
      when:
        equals:
          parsed.log_level: "INFO"

output.file:
  path: "/home/xxx/dev_logs/filebeat"
  filename: "demo4.log"
  codec.format:
    string: "%{[name]} | %{[parsed.timestamp]} | %{[parsed.thread_id]} | %{[parsed.log_level]} | %{[parsed.http.method]} | %{[parsed.http.path]}"
  • 结果:

    my_log_processor | 2025-03-31 08:22:01.048 | 16641 | ERROR | post | /napi/v1/advanced-analysis
    my_log_processor | 2025-03-31 08:22:01.057 | 16641 | WARNING | post | /napi/v1/detail

  • fliebeat处理的行数据实际上会被转换成json格式:

    json 复制代码
    {
      "@timestamp": "2025-03-31T08:22:01.048Z",  // Filebeat 自动添加的时间戳
      "name": "my_log_processor",               // 通过 add_fields 添加的固定字段
      "message": "原始日志内容...",              // 原始日志(未修改)
      "parsed": {                              // dissect 解析后的字段
        "timestamp": "2025-03-31 08:22:01.048",
        "thread_id": "16641",
        "log_level": "ERROR",
        "module": "other_utils.get_country_from_ip:78",
        "trace_id": "df139a576db44845bd6b7efaeadcc644",
        "http.method": "post",
        "http.path": "/napi/v1/advanced-analysis",
        "error_msg": "division by zero",
        "status": "-"
      }
    }

浅聊输出

  • 日志采集处理算是很专业的领域了,这里只说了采集侧的一点点,后面需要做的还有很多,存储,分析,检索,可视化等等
  • Filebeat 支持的输出目标如下,市面上有很多日志存储分析工具,很多工具Filebeat不支持直接输出的,需要用Logstash做转发
输出类型 适用场景
Elasticsearch 需要完整 ELK 栈的场景
Logstash 需要预处理日志的场景
Kafka 高吞吐量/缓冲场景
Redis 临时缓存/队列场景
文件 本地调试或备份
console 本地调试
  • 最推荐的还是接入ES,FileBeat自带的模块很多,官网上能看到好几十种(类似Nginx,MySQL之类的),和ES的契合度非常高
  • ELK是一套很强大的日志采集架构,但资源消耗大,维护成本高,类似promtail+loki+Grafana也是一套很不错的轻量级框架
  • 很多时候,filebeat只会作为采集工具,而不是去处理日志内容,想要处理日志内容,更多会用到logstash,功能更多也更全面
  • Logstash 是一个开源的服务器端数据处理管道,它可以用于采集,但更多用于转换、过滤、传输日志及其他事件数据。如果日志量很大,PB级别的日志量, 也可以用它来增加层级,接入Kafka的中间件

PS:附录

CPU负载计算:

  • 系统负载指标(load.1load.5load.15)是衡量 CPU 和 I/O 压力的关键指标,但判断是否"健康"需要结合 CPU 核心数工作负载类型 综合分析。以下是具体解读方法:


    1. 负载指标的含义

    指标 说明
    load.1 过去 1 分钟 的平均负载(最敏感,反映短期压力)。
    load.5 过去 5 分钟 的平均负载(平衡敏感性和稳定性)。
    load.15 过去 15 分钟 的平均负载(最稳定,反映长期趋势)。

    关键规则

    • 负载值表示 系统中正在使用或等待 CPU/I/O 资源的任务数(包括运行中的进程 + 不可中断的 I/O 等待进程)。
    • 负载值 不是百分比,而是绝对数值,需与 CPU 核心数对比。

    2. 如何判断是否健康?

    步骤 1:获取 CPU 核心数
    bash 复制代码
    nproc       # 查看逻辑CPU核心数(例如输出为2)
    步骤 2:计算归一化负载(Norm Load)
    • 公式
      归一化负载 = 负载值 / CPU核心数
      • 示例 :若 load.1 = 1.87 且 CPU 核心数为 2,则 norm_load = 1.87 / 2 = 0.935
    步骤 3:健康阈值参考
    归一化负载范围 健康状态 处理建议
    < 0.7 健康,系统空闲或轻度使用。 无需干预。
    0.7 ~ 1.0 轻度负载,资源利用率较高,但未过载。 监控趋势,检查是否有异常进程。
    > 1.0 过载:任务排队等待资源(CPU 或 I/O 瓶颈)。 需要立即排查高负载原因
    持续 > 2.0 严重过载,系统响应可能变慢,甚至卡死。 紧急优化或扩容。

    • 如果负载高但 CPU 使用率低(如 top 显示 %CPU < 50%),可能是 I/O 瓶颈(如磁盘慢、网络阻塞)。
    • 数据库、虚拟机等 I/O 密集型服务对负载更敏感。
相关推荐
乘云数字DATABUFF6 小时前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
荣--2 天前
一键部署不是为了省时间 —— 它是把"买来的 PaaS"变成"自己的平台"的拐点
运维·zabbix·工程化·一键部署·平台化·边界设计
江华森2 天前
动手实战学 Docker — 从零到集群编排完全指南
运维
Avan_菜菜3 天前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB4 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode5 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220706 天前
如何搭建本地yum源(上)
运维
大树889 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠9 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
通信小呆呆9 天前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人