2. 日志采集异常排查:Agent故障、日志轮转丢失、编码与格式错乱问题
日志采集这事儿,看着简单,其实坑特别多。我做了这么多年数据工程,光是在日志采集环节翻车的次数,两只手都数不过来。今天咱们就聊聊最常见的三类问题:Agent 挂了、日志轮转搞丢数据、还有编码格式乱成一锅粥。
2.1 Agent 故障:采集链路的第一道坎
Agent 是日志采集的「排头兵」。它要是罢工了,后面整个链路都白搭。我个人习惯把 Agent 故障分成三类:进程级故障、网络级故障、资源级故障。
| 故障类型 | 典型表现 | 排查方向 |
|---|---|---|
| 进程级 | Agent 进程消失、频繁重启 | 检查 OOM、配置错误、依赖库缺失 |
| 网络级 | 数据发送超时、连接被重置 | 检查防火墙、DNS、目标端口连通性 |
| 资源级 | CPU 飙高、内存泄漏、磁盘写满 | 监控资源使用率,设置告警阈值 |
我在项目中遇到过最离谱的一次,是 Agent 因为日志文件权限被误改,直接罢工了三天。排查的时候发现进程还在,但就是读不到新日志。你想想看,这种「假活」状态比真挂了还难发现。
2.2 日志轮转丢失:无声无息的数据黑洞
日志轮转(log rotation)是运维标配,但也是数据丢失的重灾区。为什么会这样?说白了,就是 Agent 采集的速度没跟上日志轮转的速度。
举个例子:应用每 10 分钟轮转一次日志文件,但 Agent 还在读旧文件。轮转发生时,旧文件被重命名或删除,Agent 手里的文件句柄就失效了。嗯,这里要注意——文件句柄失效后,Agent 可能还在傻等,而新日志已经写到新文件里去了。
解决这个问题,我建议从三个角度入手:
- 轮转策略优化:尽量使用「复制+清空」模式,而不是「重命名+新建」模式。前者对文件句柄更友好。
- 采集频率匹配:Agent 的扫描间隔要小于轮转间隔。比如轮转是 10 分钟一次,Agent 最好每 2 分钟扫一次。
- 启用文件追踪:使用 inode 或文件唯一标识来追踪文件,而不是依赖文件名。
2.3 编码与格式错乱:数据质量的隐形杀手
编码问题,我愿称之为「最让人头秃的日志异常」。明明看着是中文,存到系统里就变成乱码。格式错乱更麻烦,字段对不齐、分隔符乱飞,解析器直接报错。
常见的编码问题有这些:
- UTF-8 和 GBK 混用:不同应用输出的日志编码不一致
- BOM 头干扰:Windows 下生成的 UTF-8 文件自带 BOM,Linux 下解析会多出三个字节
- 特殊字符转义:比如 JSON 日志里的换行符没转义,导致一行变多行
file 命令先检测文件编码,再用 iconv 或 chardet 库做自动转换。别等到数据入库了再处理,那时候成本就高了。
格式错乱方面,我见过最典型的是日志分隔符不一致。有的用空格,有的用制表符,有的用逗号。更坑的是,同一份日志里,不同行用的分隔符还不一样。
嗯,这里给个实用建议:在 Agent 侧做「格式预校验」。采集到数据后,先按预期格式做一次解析尝试,如果失败率超过阈值,立刻告警。别等到数据进了 Kafka 或 HDFS 才发现问题。
2.4 知识体系总览
下面这张图,是我自己梳理的日志采集异常排查的知识结构。你可以把它当成一张「作战地图」,遇到问题按图索骥就行。
2.5 实战排查清单
最后,我整理了一份排查清单。遇到日志采集异常时,按这个顺序查一遍,基本能覆盖 90% 的问题。
- 先看 Agent 状态:进程在不在?吞吐量有没有掉?日志里有没有报错?
- 再看日志文件:文件有没有被轮转?轮转时间点和 Agent 采集时间点是否冲突?
- 最后看数据内容:编码对不对?格式是否一致?有没有乱码或字段错位?