[/metrics] — 反向分析接口参数请求抓包
# 一、引言
在进行 Ambari-Metrics 接口开发和调试时,单纯依赖源码中的描述和静态参数配置往往无法满足实际需求。没有实战数据,我们很难准确构建标准化的请求体,尤其在推送监控数据时,如何正确构造请求参数成了难题。
# 如何解决这个问题?
我们可以通过部署成功的集群,拦截请求并获取具体的请求体数据。通过捕获实际请求体,我们能够快速反向分析出请求参数的结构,从而帮助我们构建自定义的监控指标数据。
提示
通过截获请求数据并解析,我们能够更清楚地了解请求参数的结构,这为构建标准的请求体和推送数据提供了依据。
# 二、捕获请求数据
通过拦截正在运行的集群的请求体,我们可以获得实际的请求数据。以下是一个用来捕获 /ws/v1/timeline/metrics
请求体的 Bash
脚本。执行后,它会将请求体保存到指定的目录中,供我们后续分析和使用。
# 2.1 请求捕获脚本
#!/usr/bin/env bash
# 捕获 AMS /ws/v1/timeline/metrics 请求体并美化保存
set -euo pipefail
IFACE="${1:-any}" # 网卡
HOST_FILTER="${2:-}" # 可选 host
OUTDIR="${OUTDIR:-/tmp/ams-json}" # 输出目录
TLS_KEYLOG="${TLS_KEYLOG:-}" # https 时可指定 TLS keylog file
mkdir -p "$OUTDIR"
CAPFILT="tcp port 6188"
[[ -n "$HOST_FILTER" ]] && CAPFILT="$CAPFILT and host $HOST_FILTER"
TSHARK_OPTS=(
-i "$IFACE" -f "$CAPFILT"
-o tcp.desegment_tcp_streams:true
-o http.desegment_body:true
-o http.decompress_body:true
)
[[ -n "$TLS_KEYLOG" && -f "$TLS_KEYLOG" ]] && TSHARK_OPTS+=( -o tls.keylog_file:"$TLS_KEYLOG" )
echo "[INFO] Capturing on iface=$IFACE filter=$CAPFILT"
echo "[INFO] Output dir: $OUTDIR"
# 注意这里严格保证只有四个字段输出,避免 body 被塞进文件名
sudo tshark "${TSHARK_OPTS[@]}" \
-Y 'http.request.method == "POST" && http.request.uri contains "/ws/v1/timeline/metrics"' \
-T fields -E separator=$'\t' -E occurrence=f \
-e tcp.stream -e frame.time_epoch -e ip.src -e http.file_data \
| while IFS=$'\t' read -r stream tsep src body; do
ts="${tsep%.*}" # 秒级时间戳
base="$OUTDIR/${ts}-stream${stream}" # 只用时间戳和stream
raw="${base}.raw.json"
pretty="${base}.pretty.json"
# 写 body
printf '%s\n' "$body" > "$raw"
# 美化 body
if command -v jq >/dev/null 2>&1 && jq . "$raw" >/dev/null 2>&1; then
jq . "$raw" > "$pretty"
elif command -v python3 >/dev/null 2>&1; then
python3 - <<PY > "$pretty" || cp "$raw" "$pretty"
import sys, json
try:
s=open("$raw").read()
print(json.dumps(json.loads(s), indent=2, ensure_ascii=False))
except Exception:
print(open("$raw").read())
PY
else
cp "$raw" "$pretty"
fi
echo "[+] Saved: $pretty (src:$src stream:$stream)"
done
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
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
# 2.2 执行环境配置
在运行此脚本之前,请确保已满足以下环境要求:
- 安装
tshark
工具:该工具用于捕获网络数据包。 - 配置正确的网络接口:确保选择的接口能够捕获目标请求数据。
- 配置 TLS 抓包:如果使用 HTTPS,需要提供 TLS 密钥日志文件以解密流量。
注意
确保您有权限使用 tshark
捕获网络数据包,并且输出目录有写入权限。
# 2.3 执行结果
执行该脚本后,您会看到捕获到的请求数据。例如,以下是捕获到的请求数据截图:
注意
确保捕获的数据存储在正确的目录,并可以正常访问。
# 三、解析捕获的请求体
捕获到的数据将被保存到指定目录中。我们可以查看 JSON 文件,分析请求体的实际内容。以下是一个捕获的请求体示例:
# 3.1 请求体示例
{
"metrics": [
{
"timestamp": 0,
"type": "COUNTER",
"metadata": {},
"metricname": "dfs.NNTopUserOpCounts.windowMs=300000.op=setTimes.TotalCount",
"appid": "namenode",
"hostname": "dev1",
"starttime": 1758093480921,
"metrics": {
"1758093480921": 2,
"1758093490922": 2,
"1758093500921": 2,
"1758093510922": 3,
"1758093520922": 2,
"1758093530922": 2
}
},
{
"timestamp": 0,
"type": "COUNTER",
"metadata": {},
"metricname": "dfs.NNTopUserOpCounts.windowMs=300000.op=setTimes.user=ams.count",
"appid": "namenode",
"hostname": "dev1",
"starttime": 1758093480921,
"metrics": {
"1758093480921": 1,
"1758093490922": 1,
"1758093500921": 1,
"1758093510922": 2,
"1758093520922": 2,
"1758093530922": 2
}
}
]
}
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
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
# 3.2 请求体解析
通过查看该 JSON 文件,您可以发现请求体的结构,包含了多个监控指标。主要字段包括:
- metrics:包含监控数据。
- metricname:具体的指标名称。
- appid:应用标识符。
- hostname:数据来源主机。
- starttime:数据采集起始时间。
- metrics:包含时间戳和对应的值。
小提示
通过解析这些字段,您可以快速构建符合标准的请求体,并有效推送自定义的监控数据。
- 01
- [/metrics/aggregated] — 聚合数据范围 检查点09-19
- 02
- [/metrics] — 普通指标写入方法 POST09-17
- 03
- [/metrics] — 验证写入逻辑规则09-17