3、日志采集与聚合:日志规范与ELK/EFK技术栈搭建
日志这东西,说简单也简单,说复杂真能坑死人。我在早期做交易系统的时候,吃过不少日志的亏。有一次线上出了个诡异的问题,交易订单莫名其妙丢失了几笔,排查了整整一个通宵,最后发现——日志格式不统一,采集端直接把关键字段截断了。嗯,从那以后,我对日志规范这件事,就特别较真。
3.1 日志规范:结构化日志与日志级别
先聊聊日志规范。很多团队觉得日志就是随便打打,出问题再看。我告诉你,这种想法在电子交易系统里是致命的。交易系统每秒处理成千上万笔订单,日志量巨大,如果没有规范,你根本没法快速定位问题。
3.1.1 结构化日志
什么叫结构化日志?说白了,就是每条日志都是一个结构化的数据对象,而不是一段随意拼接的字符串。我个人习惯用JSON格式,因为解析方便,字段清晰。
举个例子,非结构化的日志可能是这样的:
2024-01-15 10:30:22 ERROR 订单处理失败,订单号: ORD20240115001,原因: 余额不足
而结构化的日志应该是这样的:
{
"timestamp": "2024-01-15T10:30:22.123Z",
"level": "ERROR",
"service": "order-service",
"trace_id": "abc123def456",
"order_id": "ORD20240115001",
"error_code": "INSUFFICIENT_BALANCE",
"message": "订单处理失败",
"duration_ms": 235
}
你想想看,第二种格式,Elasticsearch直接就能索引,Kibana里随便搜。第一种格式,你还得写正则去解析,费时费力还容易出错。
核心字段建议:
- timestamp:ISO 8601格式,带时区
- level:日志级别
- service:服务名称
- trace_id:链路追踪ID
- error_code:错误码(如果有)
- duration_ms:耗时(毫秒)
3.1.2 日志级别规范
日志级别这块,我见过太多乱用的。有人把所有信息都打INFO,有人把业务异常打WARN,真正出问题的时候根本分不清轻重。
我的建议是这样的:
| 级别 | 使用场景 | 示例 |
|---|---|---|
| FATAL | 系统级故障,无法自动恢复 | 数据库连接池耗尽、磁盘空间不足 |
| ERROR | 业务处理失败,需要人工介入 | 订单扣款失败、风控拒绝 |
| WARN | 异常情况但系统可自动恢复 | 重试第3次成功、接口响应超时 |
| INFO | 关键业务流程节点 | 订单创建成功、支付回调到达 |
| DEBUG | 开发调试用,生产环境关闭 | SQL语句、中间变量值 |
注意:生产环境千万不要开DEBUG级别,否则日志量会暴涨,磁盘很快写满。我曾经有个项目,上线前忘了关DEBUG,半小时就把100GB的磁盘写爆了……
3.2 ELK/EFK技术栈搭建
ELK大家都熟,Elasticsearch、Logstash、Kibana。EFK就是把Logstash换成了Fluentd。我个人更倾向于EFK,因为Fluentd资源占用更小,配置也更灵活。不过今天咱们重点讲ELK,毕竟它更通用。
3.2.1 架构图
先画个图,让大家对整体架构有个直观认识:
3.2.2 搭建步骤
搭建ELK其实不复杂,但有几个坑要注意。我直接给出一套经过验证的部署方案。
第一步:安装Elasticsearch
# 使用Docker Compose部署
version: '3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms4g -Xmx4g
- xpack.security.enabled=false
ports:
- "9200:9200"
volumes:
- es_data:/usr/share/elasticsearch/data
volumes:
es_data:
小提示:生产环境建议至少3个节点,并且给ES分配的内存不要超过物理内存的50%,否则容易触发JVM的GC问题。
第二步:安装Logstash
logstash:
image: docker.elastic.co/logstash/logstash:8.11.0
ports:
- "5044:5044"
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
第三步:安装Kibana
kibana:
image: docker.elastic.co/kibana/kibana:8.11.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
3.3 日志采集工具Filebeat/Logstash配置实战
这里我重点讲Filebeat,因为它是轻量级的采集器,部署在每台应用服务器上,几乎不占资源。Logstash则负责集中处理。
3.3.1 Filebeat配置
# filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/app/*.log
multiline:
pattern: '^\d{4}-\d{2}-\d{2}'
negate: true
match: after
fields:
service: order-service
env: production
output.logstash:
hosts: ["logstash:5044"]
这里有个关键点——multiline配置。Java的异常栈是跨多行的,如果不做多行合并,一条异常会被拆成几十条日志,根本没法看。我当初就踩过这个坑,排查问题时发现异常栈被拆得七零八落,气得我直接加了这个配置。
3.3.2 Logstash配置
# logstash.conf
input {
beats {
port => 5044
}
}
filter {
# 解析JSON日志
json {
source => "message"
target => "parsed"
}
# 添加时间戳
date {
match => ["parsed.timestamp", "ISO8601"]
target => "@timestamp"
}
# 移除原始message
mutate {
remove_field => ["message"]
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "app-logs-%{+YYYY.MM.dd}"
}
}
注意:如果日志不是JSON格式,记得先用grok插件解析。但说实话,我强烈建议你直接用结构化日志,省去解析的麻烦。
3.4 日志索引生命周期管理
日志索引生命周期管理(ILM),说白了就是让ES自动管理索引的创建、滚动和删除。交易系统的日志量很大,一天可能几十GB,如果不做ILM,磁盘很快会爆。
3.4.1 ILM策略配置
PUT _ilm/policy/logs_policy
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50GB",
"max_age": "1d"
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": {
"number_of_shards": 1
},
"forcemerge": {
"max_num_segments": 1
}
}
},
"cold": {
"min_age": "30d",
"actions": {
"freeze": {}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}
这个策略的意思是:
- Hot阶段:当前写入的索引,超过50GB或1天就滚动
- Warm阶段:7天后的索引,合并段、减少分片,节省存储
- Cold阶段:30天后的索引,冻结,几乎不占资源
- Delete阶段:90天后的索引,直接删除
嗯,这里要注意,交易系统的日志保留时间,建议至少90天,因为监管审计需要。但如果你磁盘有限,可以缩短到30天,不过要做好备份。
3.4.2 索引模板配置
PUT _index_template/logs_template
{
"index_patterns": ["app-logs-*"],
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.lifecycle.name": "logs_policy",
"index.lifecycle.rollover_alias": "app-logs"
},
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"level": { "type": "keyword" },
"service": { "type": "keyword" },
"trace_id": { "type": "keyword" },
"message": { "type": "text" }
}
}
}
}
总结一下:日志规范是基础,ELK是工具,ILM是保障。这三者缺一不可。我见过太多团队只搭了ELK,没做规范也没做ILM,结果三个月后磁盘爆了,日志全丢。别让这种事发生在你身上。
好了,这一章的内容就到这里。日志采集与聚合这块,说白了就是三个字——规范、采集、管理。把这三件事做好,你的监控体系就有了最坚实的基础。
公众号:蓝海资料掘金营,微信deep3321