Nginx查找耗时的接口

Nginx查找耗时的接口

# 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.com.cn)"
    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 "字段说明: [耗时(秒)]  [接口路径]  [状态码]"

使用示例

# 分析默认日志中,zhhll.com.cn域名下耗时>0.5秒的前20个成功接口(按upstream时间)
./nginx_slow_apis.sh -d zhhll.com.cn -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. 自动化分析
    可将脚本添加到定时任务,定期生成慢接口报告,及时发现性能退化问题。