7.6.3 日志分析与可视化(goaccess/ELK)
在日志分析与可视化方面,Nginx常用两条路线:轻量快速分析的 GoAccess 与集中化检索分析的 ELK(Elasticsearch/Logstash/Kibana)。前者适合单机或小规模,后者适合多节点、跨业务、长期留存与告警联动的场景。核心目标是把“访问日志与错误日志”转化为可查询指标、可视化报表与问题定位依据。
原理草图(采集→解析→存储→可视化):
一、Nginx日志格式准备(GoAccess/ELK通用)
# /etc/nginx/nginx.conf
http {
log_format ops '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time urt=$upstream_response_time '
'ua="$upstream_addr" rid=$request_id';
access_log /var/log/nginx/access.log ops;
error_log /var/log/nginx/error.log warn;
}
说明:
- rt、urt 用于慢请求定位;rid 便于跨系统追踪;字段稳定是解析成功的关键。
二、GoAccess:快速分析与实时页面
1) 安装(以 Ubuntu 为例)
sudo apt-get update
sudo apt-get install -y goaccess
goaccess --version
2) 解析访问日志(离线报表)
# 生成静态HTML报表
goaccess /var/log/nginx/access.log \
--log-format='%h - %u [%d:%t %^] "%r" %s %b "%R" "%u" rt=%T urt=%^ ua="%^" rid=%^' \
--date-format='%d/%b/%Y' \
--time-format='%H:%M:%S' \
-o /var/www/html/report.html
关键参数说明:
- --log-format 必须与 Nginx log_format 一致;%^ 表示跳过不需字段
- -o 输出HTML到Web目录,浏览器打开即可
3) 实时监控页
goaccess /var/log/nginx/access.log \
--log-format='%h - %u [%d:%t %^] "%r" %s %b "%R" "%u" rt=%T urt=%^ ua="%^" rid=%^' \
--date-format='%d/%b/%Y' \
--time-format='%H:%M:%S' \
--real-time-html \
-o /var/www/html/realtime.html
预期效果:实时看到请求量、状态码分布、慢请求、TOP URL。
常见排错:
- 报“Invalid log format”:核对 Nginx log_format 与 GoAccess --log-format 是否一致
- 时间字段解析失败:检查 time_local 是否包含时区,必要时用 %^ 跳过
- 实时页无数据:确保访问日志持续写入,且文件权限可读
三、ELK:集中化检索与可视化
1) 组件与流程示意
2) Filebeat 安装与采集配置
sudo apt-get install -y filebeat
sudo tee /etc/filebeat/filebeat.yml >/dev/null <<'EOF'
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
fields:
service: nginx
fields_under_root: true
output.logstash:
hosts: ["127.0.0.1:5044"]
EOF
sudo systemctl enable --now filebeat
sudo systemctl status filebeat --no-pager
3) Logstash 解析配置(基于上述 log_format)
# /etc/logstash/conf.d/nginx.conf
input {
beats { port => 5044 }
}
filter {
grok {
match => {
"message" => '%{IPORHOST:remote_addr} - %{DATA:remote_user} \[%{HTTPDATE:time_local}\] "%{WORD:request_method} %{DATA:uri} HTTP/%{NUMBER:http_version}" %{NUMBER:status:int} %{NUMBER:body_bytes_sent:int} "%{DATA:http_referer}" "%{DATA:http_user_agent}" rt=%{NUMBER:request_time:float} urt=%{DATA:upstream_response_time} ua="%{DATA:upstream_addr}" rid=%{DATA:request_id}'
}
}
date {
match => [ "time_local", "dd/MMM/yyyy:HH:mm:ss Z" ]
target => "@timestamp"
}
}
output {
elasticsearch {
hosts => ["http://127.0.0.1:9200"]
index => "nginx-%{+YYYY.MM.dd}"
}
}
启动与检查:
sudo systemctl enable --now logstash
sudo systemctl status logstash --no-pager
4) Elasticsearch 健康检查
curl -s http://127.0.0.1:9200/_cluster/health?pretty
5) Kibana 基础可视化建议
- 指标:QPS、状态码分布、P95/P99 请求时间、上游失败率、TOP URL
- 过滤:status:[500 TO 599] 定位服务端异常
- 对比:按 service 或 host 维度拆分
常见排错:
- Kibana无数据:检查 Logstash 输出索引名与 Kibana Index Pattern 是否一致
- grok解析失败:到 Logstash 日志中查看 _grokparsefailure,调试正则或 log_format
- 高基数字段:http_user_agent 字段建议做分词/截断或仅保留解析后版本
四、关键命令与效果速查
# 统计近1分钟的访问量(快速命令)
tail -n 2000 /var/log/nginx/access.log | awk '{print $4}' | uniq -c | tail
# 统计5xx错误
awk '$9 ~ /^5/ {count++} END{print "5xx:",count}' /var/log/nginx/access.log
# 查找超时上游
awk '$0 ~ /urt=/ {print $0}' /var/log/nginx/access.log | grep 'urt=-' | head
五、练习
1) 练习1:为 Nginx 增加 request_id 字段并验证 GoAccess 正确解析
目标:打开 report.html 可看到“请求数/状态码/慢请求”报表。
2) 练习2:在 Logstash 中新增字段 is_slow(request_time > 1)并在 Kibana 过滤
目标:创建“慢请求趋势图”,观察高峰时段。
3) 练习3:模拟 500 错误并在 Kibana 快速定位
方法:临时配置一个返回 500 的 location,刷新后在 Kibana 通过 status:500 过滤。