0%

Nginx查找耗时的接口

Nginx查找耗时的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# grep 是筛选的域名   awk中的$5是判断的状态码  sort中的15是指的upstream_response_time  当然也可以统计request_time的时间
#!/bin/bash

# 默认配置
LOG_FILE="/var/log/nginx/access.log" # Nginx日志文件路径
DOMAIN="" # 筛选的域名(空表示所有)
STATUS_CODE="200" # 状态码(空表示所有)
TOP_N=10 # 显示前N条
TIME_FIELD="upstream_response_time" # 统计的时间字段(request_time/upstream_response_time)
TIME_THRESHOLD=0 # 最小耗时阈值(秒,0表示不限制)

# 显示帮助信息
usage() {
echo "用法: $0 [选项]"
echo "分析Nginx日志中耗时较长的接口"
echo "选项:"
echo " -f <日志文件> 指定Nginx日志文件路径(默认: $LOG_FILE)"
echo " -d <域名> 筛选特定域名(如 zhhll.icu)"
echo " -s <状态码> 筛选特定状态码(如 200, 500)"
echo " -n <数量> 显示前N条记录(默认: $TOP_N)"
echo " -t <时间字段> 时间字段(request_time/upstream_response_time, 默认: $TIME_FIELD)"
echo " -T <阈值> 最小耗时阈值(秒,默认: $TIME_THRESHOLD)"
echo " -h 显示帮助信息"
exit 1
}

# 解析命令行参数
while getopts "f:d:s:n:t:T:h" opt; do
case $opt in
f) LOG_FILE="$OPTARG" ;;
d) DOMAIN="$OPTARG" ;;
s) STATUS_CODE="$OPTARG" ;;
n) TOP_N="$OPTARG" ;;
t) TIME_FIELD="$OPTARG" ;;
T) TIME_THRESHOLD="$OPTARG" ;;
h) usage ;;
*) usage ;;
esac
done

# 验证时间字段合法性
if [ "$TIME_FIELD" != "request_time" ] && [ "$TIME_FIELD" != "upstream_response_time" ]; then
echo "错误: 时间字段必须是 request_time 或 upstream_response_time"
exit 1
fi

# 确定时间字段在日志中的列数(根据实际log_format调整)
# 以下假设为默认combined日志格式扩展,包含upstream_response_time
# 请根据实际日志格式修改字段索引
if [ "$TIME_FIELD" = "request_time" ]; then
TIME_COLUMN=10 # 假设request_time在第10列
else
TIME_COLUMN=15 # 假设upstream_response_time在第15列
fi

# 构建筛选条件
FILTER=""
if [ -n "$DOMAIN" ]; then
FILTER="$FILTER | grep '$DOMAIN'"
fi

if [ -n "$STATUS_CODE" ]; then
# 假设状态码在第9列(根据实际日志格式调整)
FILTER="$FILTER | awk '\$9 == $STATUS_CODE {print \$0}'"
fi

# 执行分析命令
echo "分析日志: $LOG_FILE"
echo "筛选条件: 域名=$DOMAIN, 状态码=$STATUS_CODE, 时间字段=$TIME_FIELD, 最小耗时=$TIME_THRESHOLD秒"
echo "----------------------------------------"

eval "cat $LOG_FILE $FILTER | awk -v col=$TIME_COLUMN -v threshold=$TIME_THRESHOLD '
\$col + 0 >= threshold { # 转换为数字比较,过滤小于阈值的记录
print \$col \"\t\" \$7 \"\t\" \$9 # 输出: 耗时 接口路径 状态码
}
' | sort -k1,1nr | head -n $TOP_N"

echo "----------------------------------------"
echo "字段说明: [耗时(秒)] [接口路径] [状态码]"

使用示例

1
2
3
4
5
6
7
8
# 分析默认日志中,zhhll.icu域名下耗时>0.5秒的前20个成功接口(按upstream时间)
./nginx_slow_apis.sh -d zhhll.icu -T 0.5 -n 20

# 分析所有500错误的接口,按总耗时(request_time)排序
./nginx_slow_apis.sh -s 500 -t request_time

# 分析自定义日志文件
./nginx_slow_apis.sh -f /var/log/nginx/access_8080.log -n 15

注意事项

  1. 日志格式适配
    脚本中默认的字段索引(如状态码在第 9 列)基于常见的 Nginx 日志格式,需根据实际 log_format 配置调整 TIME_COLUMN 和状态码列的数值。
  2. 大日志处理
    对于超大日志文件,建议先通过 tail 取最近数据,或使用 awk 直接处理(避免 cat | grep 的管道开销)。
  3. 自动化分析
    可将脚本添加到定时任务,定期生成慢接口报告,及时发现性能退化问题。

欢迎关注我的其它发布渠道