概述
凌晨两点,支付系统告警炸了。看了半天日志发现不是下游服务挂了,而是 API 网关的连接池打满了——请求堆在网关这一层根本没转发出去。但你的监控大盘上只有 CPU 和内存曲线,压根看不到网关层的延迟、连接数和错误率。
这不是个例。我见过太多团队把 API 网关当"高级 Nginx"用,监控只看 nginx_active_connections,出事了才去翻日志。问题是网关是所有流量的咽喉,一旦这层出问题,影响面是全局的。
这篇文章讲清楚三件事:Kong、APISIX、Envoy 各自暴露哪些指标、怎么用 Prometheus 采集、告警规则怎么设计才能在故障扩散前收到通知。不是泛泛而谈的"最佳实践",是我在生产环境踩过坑后整理出来的方案。
为什么 API 网关需要专门的监控
你可能会想:网关后面已经有服务监控了,为什么还要单独监控网关?
因为网关和后端服务看到的世界不一样。举个例子:
| 维度 | 网关视角 | 后端服务视角 |
|---|---|---|
| 请求延迟 | 包含路由匹配、插件执行、上游转发全链路 | 只看到自己处理那段 |
| 错误来源 | 可能是路由不存在、插件拦截、上游超时、连接池满 | 只知道返回了 500 |
| 连接状态 | 能看到与上游的连接池使用率 | 只知道自己收了多少请求 |
| 限流触发 | 网关层限流命中了哪些规则 | 服务端可能根本不知道被限了 |
简单说,网关是流量高速公路的收费站。收费站堵了,后面所有车都堵。你不在收费站装监控,等问题传导到后端服务再排查,黄花菜都凉了。
三大主流网关的指标体系对比
Kong 的指标暴露
Kong 通过 prometheus 插件暴露指标,启用方式很简单:
# 启用 Prometheus 插件(全局级别)
curl -X POST http://kong-admin:8001/plugins \
--data "name=prometheus" \
--data "config.per_consumer=true" \
--data "config.status_code_metrics=true" \
--data "config.latency_metrics=true" \
--data "config.upstream_health_metrics=true"
启用后访问 http://kong-proxy:8001/metrics 就能拿到 Prometheus 格式的指标。Kong 的核心指标分四类:
| 指标名 | 类型 | 含义 | 典型告警场景 |
|---|---|---|---|
kong_http_requests_total | Counter | 请求总数(按 service/route/status 标签) | 错误率突增 |
kong_latency_ms_bucket | Histogram | 延迟分布(含 Kong 处理时间和上游响应时间) | P99 延迟超阈值 |
kong_upstream_target_health | Gauge | 上游健康状态(HEALTHY/UNHEALTHY) | 上游节点不健康 |
kong_data_plane_version | Gauge | 数据面版本号 | 版本不一致 |
其中延迟指标最关键。Kong 把延迟拆成三段:kong_latency 是 Kong 自身处理耗时(路由匹配、插件执行),upstream_latency 是上游服务响应时间,total_latency 是两者之和。分开看才能判断瓶颈在网关还是在后端。
一个踩坑经验:per_consumer=true 会导致指标基数爆炸。如果你的 consumer 数量超过 1000 个,Prometheus 存储压力会急剧上升。生产环境建议先关掉这个选项,需要时按需开启。
APISIX 的指标暴露
APISIX 用 prometheus 插件,配置方式跟 Kong 类似但底层完全不同:
# APISIX prometheus 插件配置
plugins:
- prometheus
# 通过 Admin API 启用
# 全局路由级别
curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: your-key' -X PUT -d '
{
"uri": "/api/*",
"plugins": {
"prometheus": {
"prefer_name": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8080": 1
}
}
}'
APISIX 默认在 http://apisix-ip:9091/metrics 暴露指标,和 Kong 的区别在于 APISIX 用 etcd 做配置中心,配置变更是推送模式(watch),延迟更低。核心指标:
| 指标名 | 类型 | 含义 |
|---|---|---|
apisix_http_status | Counter | HTTP 状态码计数(按 route/service/consumer) |
apisix_bandwidth | Counter | 上下行带宽 |
apisix_http_latency_bucket | Histogram | 延迟分布 |
apisix_node_info | Gauge | 节点信息(版本、启动时间) |
APISIX 的一个优势是 prefer_name: true 选项,用路由名称而不是 UUID 作为标签,查询时更直观。Kong 默认用 service ID,PromQL 写出来全是 service="4e3f2a1b-..." 这种鬼东西,排障时还得去查表。
踩坑:APISIX 的 prometheus 插件不支持 per-consumer 粒度的延迟分布。如果你的业务需要按消费者分析延迟,得自己在日志层做。别等出事了才发现查不到。
Envoy 的指标暴露
Envoy 是三大网关里指标体系最丰富的,但也是最复杂的。Envoy 暴露的指标有几百个,新手容易迷失。实际生产中需要关注的核心指标:
| 指标名 | 类型 | 含义 |
|---|---|---|
envoy_cluster_upstream_rq_total | Counter | 上游请求总数 |
envoy_cluster_upstream_rq_2xx/4xx/5xx | Counter | 按状态码分类的请求计数 |
envoy_cluster_upstream_rq_time_bucket | Histogram | 上游响应延迟分布 |
envoy_cluster_circuit_breakers_default_cx_pool_open | Gauge | 连接池断路器是否打开 |
envoy_listener_downstream_cx_total | Counter | 下游连接总数 |
envoy_server_live | Gauge | 服务器存活状态(1=alive) |
Envoy 的指标通过 admin 接口(默认 http://envoy-ip:9901/stats)或 stats sink(Prometheus 格式 http://envoy-ip:9901/stats/prometheus)暴露。
配置 stats sink:
# Envoy 配置 - 启用 Prometheus stats sink
stats_sinks:
- name: envoy.stat_sinks.statsd
typed_config:
"@type": type.googleapis.com/envoy.config.metrics.v3.StatsdSink
address:
socket_address:
address: 127.0.0.1
port_value: 9125
prefix: envoy.
# 或者用 Prometheus 格式(推荐)
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901
Envoy 指标的坑在于基数管理。Envoy 默认给每个 cluster、每个 endpoint 都打标签,如果你的路由数量多(比如几百个 API 路径),指标基数会爆炸。解决办法是用 stats_config 过滤掉不需要的标签:
stats_config:
stats_tags:
- tag_name: cluster_name
regex: "^cluster\\.((.+?)\\.)"
stats_matcher:
inclusion_list:
patterns:
- prefix: "cluster."
- prefix: "listener."
- prefix: "server."
- prefix: "http."
这样只保留 cluster、listener、server、http 相关的指标,砍掉一堆用不上的内部统计。
Prometheus 采集配置
Kong 采集
# prometheus.yml - Kong 采集配置
scrape_configs:
- job_name: 'kong'
metrics_path: /metrics
static_configs:
- targets:
- 'kong-gateway:8001' # Kong Admin API 端口
relabel_configs:
- source_labels: [__address__]
target_label: instance
replacement: 'kong-prod-01'
Kong 3.x 之后 Admin API 和 Proxy 可以分端口,确保 metrics_path 指向正确的端口。Kong 2.x 的 /metrics 端点默认在 Admin API(8001)上。
APISIX 采集
# prometheus.yml - APISIX 采集配置
scrape_configs:
- job_name: 'apisix'
metrics_path: /apisix/prometheus/metrics
static_configs:
- targets:
- 'apisix:9091'
relabel_configs:
- source_labels: [__address__]
target_label: instance
replacement: 'apisix-prod-01'
注意 APISIX 的 metrics 端口默认是 9091,路径是 /apisix/prometheus/metrics,不是标准的 /metrics。配错了 Prometheus 会一直报 404。
Envoy 采集
# prometheus.yml - Envoy 采集配置
scrape_configs:
- job_name: 'envoy'
metrics_path: /stats/prometheus
static_configs:
- targets:
- 'envoy-proxy:9901'
Envoy 的 admin 端口默认 9901,Prometheus 格式的指标路径是 /stats/prometheus。如果你的 Envoy 跑在 Kubernetes 里,建议用 Pod Monitor 自动发现:
# Kubernetes PodMonitor(kube-prometheus-stack)
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: envoy-gateway
namespace: monitoring
spec:
selector:
matchLabels:
app: envoy-gateway
podMetricsEndpoints:
- port: admin
path: /stats/prometheus
interval: 15s
核心告警规则设计
这部分是最实用的。我按"故障发现优先级"排了五层告警,从 P0 到 P4,你可以直接抄到自己的告警规则文件里。
第一层:网关存活(P0)
groups:
- name: gateway-availability
rules:
# 网关进程存活
- alert: GatewayDown
expr: up{job=~"kong|apisix|envoy"} == 0
for: 1m
labels:
severity: critical
team: sre
annotations:
summary: "网关 {{ $labels.instance }} 不可达"
description: "Prometheus 已无法采集 {{ $labels.instance }} 的指标,网关可能已宕机"
# 网关 5xx 错误率(1分钟内超过 5%)
- alert: GatewayHighErrorRate
expr: |
sum(rate(kong_http_requests_total{status=~"5.."}[1m])) by (service)
/
sum(rate(kong_http_requests_total[1m])) by (service)
> 0.05
for: 2m
labels:
severity: critical
team: sre
annotations:
summary: "Kong 网关 5xx 错误率超 5%"
description: "服务 {{ $labels.service }} 的 5xx 错误率当前为 {{ $value | humanizePercentage }}"
为什么 for: 2m 而不是立刻告警?因为瞬间毛刺(比如 GC 停顿、连接重置)可能让错误率短暂飙高,1 分钟后自行恢复。2 分钟的持续条件能过滤掉 80% 的噪音。
第二层:延迟异常(P1)
- name: gateway-latency
rules:
# Kong P99 延迟超过 500ms
- alert: GatewayHighLatency
expr: |
histogram_quantile(0.99,
sum(rate(kong_latency_ms_bucket[5m])) by (service, le)
) > 500
for: 5m
labels:
severity: warning
team: sre
annotations:
summary: "Kong 网关 P99 延迟超 500ms"
description: "服务 {{ $labels.service }} 的 P99 延迟当前为 {{ $value }}ms"
# 上游延迟占比过高(Kong 自身延迟 < 总延迟的 20% 说明瓶颈在上游)
- alert: GatewayUpstreamLatencyDominant
expr: |
histogram_quantile(0.95,
sum(rate(kong_latency_ms_bucket{type="upstream"}[5m])) by (service, le)
)
/
histogram_quantile(0.95,
sum(rate(kong_latency_ms_bucket{type="total"}[5m])) by (service, le)
)
> 0.8
for: 10m
labels:
severity: info
team: sre
annotations:
summary: "上游延迟占比超 80%,瓶颈在后端服务"
description: "服务 {{ $labels.service }} 的上游延迟占比 {{ $value | humanizePercentage }},建议排查后端服务"
这条 GatewayUpstreamLatencyDominant 告警是我加的。很多团队只看总延迟,看到延迟高了就去找网关的问题,折腾半天发现是后端慢。这个告警把延迟拆开,上游占比超 80% 就说明瓶颈不在网关,直接把排查方向指向后端。实测能省一半的定位时间。
第三层:上游健康(P2)
- name: gateway-upstream-health
rules:
# 上游节点不健康
- alert: GatewayUpstreamUnhealthy
expr: kong_upstream_target_health{state="UNHEALTHY"} == 1
for: 1m
labels:
severity: warning
team: sre
annotations:
summary: "上游目标 {{ $labels.target }} 不健康"
description: "上游 {{ $labels.upstream }} 的目标 {{ $labels.target }} 当前状态为 UNHEALTHY"
# Envoy 集群断路器打开
- alert: EnvoyCircuitBreakerOpen
expr: envoy_cluster_circuit_breakers_default_cx_pool_open == 1
for: 30s
labels:
severity: critical
team: sre
annotations:
summary: "Envoy 集群 {{ $labels.cluster_name }} 连接池断路器已打开"
description: "集群连接池已满,新请求被拒绝"
断路器打开意味着上游已经扛不住了。这种情况通常伴随着雪崩效应——一个服务慢了拖垮连接池,导致其他正常服务的请求也连不上。这条告警触发后应该立即检查上游服务状态和连接池配置。
第四层:流量异常(P3)
- name: gateway-traffic-anomaly
rules:
# 请求量骤降(可能路由配置有问题或上游全部挂了)
- alert: GatewayTrafficDrop
expr: |
sum(rate(kong_http_requests_total[5m])) by (service)
<
sum(rate(kong_http_requests_total[5m] offset 1h)) by (service) * 0.3
for: 10m
labels:
severity: warning
team: sre
annotations:
summary: "服务 {{ $labels.service }} 流量下降超 70%"
description: "当前请求量比 1 小时前下降 {{ $value }}"
# 请求量突增(可能是被刷了或正常流量高峰)
- alert: GatewayTrafficSpike
expr: |
sum(rate(kong_http_requests_total[5m])) by (service)
>
sum(rate(kong_http_requests_total[5m] offset 1h)) by (service) * 3
for: 5m
labels:
severity: info
team: sre
annotations:
summary: "服务 {{ $labels.service }} 流量增长超 200%"
description: "当前请求量比 1 小时前增长 {{ $value }} 倍,请确认是否为正常流量高峰"
流量突降比突增更值得警惕。突增可能只是业务高峰,但突降几乎一定出事了——要么路由配置被改坏了,要么上游全挂了。
第五层:资源水位(P4)
- name: gateway-resource
rules:
# Kong 数据面连接数过高
- alert: KongHighConnections
expr: |
sum by (instance) (
kong_nginx_http_connections_total{state="active"}
) > 10000
for: 5m
labels:
severity: warning
team: sre
annotations:
summary: "Kong 实例 {{ $labels.instance }} 活跃连接数超 10000"
description: "当前活跃连接数 {{ $value }},可能需要扩容"
# APISIX etcd 连接异常
- alert: APISIXEtcdUnreachable
expr: apisix_etcd_reachable == 0
for: 30s
labels:
severity: critical
team: sre
annotations:
summary: "APISIX 无法连接 etcd"
description: "APISIX 节点 {{ $labels.instance }} 无法连接 etcd,配置变更将无法同步"
etcd 连不上是个要命的故障。APISIX 所有配置都存在 etcd 里,连不上意味着路由规则无法更新、新配置无法下发。虽然已有的配置还在内存里缓存着,暂时不影响流量转发,但你已经失去了对网关的控制权。
Grafana 仪表盘设计
仪表盘布局原则
一个好的 API 网关监控大盘应该让运维一眼看到三个答案:流量正不正常?延迟高不高?有没有报错?
我建议用从上到下四行布局:
┌─────────────────────────────────────────────┐
│ 第 1 行:QPS 总量、错误率、P99 延迟、活跃连接 │ ← 一眼看全局
├─────────────────────────────────────────────┤
│ 第 2 行:各服务 QPS 对比 + 错误率对比 │ ← 谁有问题
├─────────────────────────────────────────────┤
│ 第 3 行:延迟分布热力图 + 延迟分位数趋势 │ ← 延迟详情
├─────────────────────────────────────────────┤
│ 第 4 行:上游健康状态 + 断路器状态 + 连接池 │ ← 底层状态
└─────────────────────────────────────────────┘
核心 Panel 配置
第 1 行:全局概览
# 总 QPS(按网关实例聚合)
sum(rate(kong_http_requests_total[5m]))
# 错误率
sum(rate(kong_http_requests_total{status=~"5.."}[5m]))
/
sum(rate(kong_http_requests_total[5m]))
# P99 延迟
histogram_quantile(0.99,
sum(rate(kong_latency_ms_bucket[5m])) by (le)
)
# 活跃连接数
sum(kong_nginx_http_connections_total{state="active"})
第 3 行:延迟热力图
Grafana 的 Heatmap panel 很适合展示延迟分布。把 Histogram bucket 配置好,能直观看到延迟从哪个时间点开始漂移:
# 延迟热力图数据源
sum(rate(kong_latency_ms_bucket[5m])) by (le, service)
Heatmap 能让你一眼看到"延迟不是均匀涨上来的,而是有一批请求突然变慢了"——这种模式用折线图根本看不出来,但用热力图特别明显。我第一次用热力图排查延迟问题就发现了有个 service 的 P50 正常但尾部延迟在每天 14:00 定期飙高,最后查出是后端服务在跑定时任务占满了线程池。
第 4 行:上游健康表格
用 Table panel 展示每个上游目标的健康状态:
kong_upstream_target_health
加一个 Value Mappings,把 1 映射成红色 UNHEALTHY,0 映射成绿色 HEALTHY,比看数字直观得多。
三种网关监控的对比与选型建议
| 维度 | Kong | APISIX | Envoy |
|---|---|---|---|
| 指标暴露方式 | Prometheus 插件 | Prometheus 插件 | Admin API / Stats Sink |
| 指标丰富度 | 中(够用) | 中(够用) | 高(几百个指标) |
| 延迟分维度 | Kong + 上游 + 总计 | 总计为主 | 非常细(按 cluster/route) |
| 标签可读性 | 默认 UUID,需额外配置 | prefer_name 用路由名 | 需手动配置 stats_filter |
| 连接池监控 | Nginx 层指标 | Nginx 层指标 | 内置断路器指标 |
| 配置存储 | PostgreSQL / Cassandra | etcd | xDS(Istio/Kubernetes) |
| 指标基数风险 | per_consumer 开启后爆炸 | 路由多时中等 | 默认就高,必须过滤 |
选型建议:
- Kong:团队偏保守、已有 Kong 运维经验、指标需求不复杂。Kong 的插件生态成熟,但 per_consumer 粒度监控要做好基数管理
- APISIX:追求动态配置、对配置变更延迟敏感。etcd 的 watch 机制让配置秒级生效,但 etcd 本身也要做好监控和 HA
- Envoy:深度使用 Service Mesh(Istio)、需要精细化的流量观测。Envoy 指标体系最完整但学习曲线最陡,适合有专职 SRE 的团队
生产级踩坑实录
坑 1:Kong 指标基数爆炸
去年我们有个业务方接入了 2000+ 个 consumer,网关开了 per_consumer=true。结果 Prometheus 存储从每天 5GB 涨到 47GB,查询也慢了。因为每个 consumer × 每个 route × 每个 status code 都会产生一个时序,2000 × 50 × 5 = 50 万条时序。
解决:关掉 per_consumer,需要 consumer 级别分析时从网关日志里查。如果非要细粒度指标,用 consumer_label_filter 只保留 Top N 的 consumer。
坑 2:APISIX 配置变更没同步到监控
APISIX 的 Prometheus 插件是在路由级别配置的。有一次同事加了个新路由但忘了挂 prometheus 插件,新路由的流量完全没被监控到,直到有用户反馈这个 API 偶尔超时才发现。
解决:在 CI/CD 里加了一道检查——所有新路由必须包含 prometheus 插件配置,否则流水线拦截。另外在 Grafana 上加了一个"未监控路由检测"面板,定期对比 APISIX Admin API 里的路由列表和 Prometheus 里有指标的路由列表,差集就是漏配的。
坑 3:Envoy stats endpoint 被 OOM kill
Envoy 默认暴露所有统计指标,包括大量内部计数器。路由数量多了以后 /stats/prometheus 的响应体能有几十 MB,Prometheus 每次 scrape 都让 Envoy 内存涨一截,最终被 OOM kill。
解决:用 stats_matcher 只暴露需要的指标前缀(cluster、listener、http、server),响应体从 47MB 降到 3MB。同时调大 scrape interval 从 15s 到 30s,降低采集频率。
坑 4:告警阈值一刀切
我们最初给所有服务都设了 P99 > 500ms 的告警。结果有些批量接口正常响应就要 2-3 秒,天天告警。SRE 习惯了告警噪音后,真正出事的时候反而忽略了。
解决:按服务类型分组设阈值。在线交易类 P99 > 200ms 告警,查询类 P99 > 800ms 告警,批量类 P99 > 5s 才告警。在 Prometheus 里用 service label 做条件分支:
# 按服务类型设置不同延迟阈值
- alert: GatewayHighLatencyOnline
expr: |
histogram_quantile(0.99,
sum(rate(kong_latency_ms_bucket{service=~"order-.*|payment-.*"}[5m])) by (service, le)
) > 200
and on(service)
kong_latency_ms_count{service=~"order-.*|payment-.*"} > 0
for: 5m
labels:
severity: warning
- alert: GatewayHighLatencyBatch
expr: |
histogram_quantile(0.99,
sum(rate(kong_latency_ms_bucket{service=~"report-.*|export-.*"}[5m])) by (service, le)
) > 5000
and on(service)
kong_latency_ms_count{service=~"report-.*|export-.*"} > 0
for: 10m
labels:
severity: warning
坑 5:APISIX etcd 单点故障导致配置丢失
APISIX 所有配置依赖 etcd。有一次 etcd 集群一个节点磁盘满了,APISIX 虽然能继续转发流量(内存里有缓存的配置),但所有新配置都无法下发。更糟糕的是 Prometheus 的 apisix_etcd_reachable 指标显示正常——因为 APISIX 连的是另一个 etcd 节点,那个节点虽然活着但数据已经不一致了。
解决:除了监控 apisix_etcd_reachable,还要监控 etcd 集群本身的健康状态(etcd_server_has_leader、etcd_mvcc_db_total_size_in_bytes、etcd_server_proposals_failed_total),从 etcd 侧做独立检查。别只信网关报告的"我能连上 etcd"。
自动化巡检脚本
光有被动告警不够,主动巡检能提前发现隐患。这是一个检查网关关键指标的脚本:
#!/usr/bin/env python3
"""API 网关健康巡检脚本
通过 Prometheus API 查询网关关键指标,输出巡检报告。
"""
import requests
import sys
from datetime import datetime
PROMETHEUS_URL = "http://prometheus:9090"
# 巡检项配置:指标名 -> 查询语句 -> 阈值 -> 告警级别
CHECKS = [
{
"name": "网关存活",
"query": 'up{job=~"kong|apisix|envoy"}',
"expect": 1,
"severity": "P0"
},
{
"name": "5xx 错误率",
"query": """
sum(rate(kong_http_requests_total{status=~"5.."}[5m]))
/ sum(rate(kong_http_requests_total[5m]))
""",
"threshold": 0.01,
"severity": "P1",
"compare": "gt"
},
{
"name": "P99 延迟",
"query": """
histogram_quantile(0.99,
sum(rate(kong_latency_ms_bucket[5m])) by (le)
)
""",
"threshold": 500,
"severity": "P2",
"compare": "gt"
},
{
"name": "上游不健康节点数",
"query": 'count(kong_upstream_target_health{state="UNHEALTHY"} == 1)',
"threshold": 0,
"severity": "P2",
"compare": "gt"
},
{
"name": "活跃连接数",
"query": 'sum(kong_nginx_http_connections_total{state="active"})',
"threshold": 8000,
"severity": "P3",
"compare": "gt"
},
]
def query_prometheus(query):
"""执行 PromQL 查询"""
resp = requests.get(
f"{PROMETHEUS_URL}/api/v1/query",
params={"query": query},
timeout=10
)
resp.raise_for_status()
data = resp.json()
if data["status"] != "success":
raise ValueError(f"查询失败: {data}")
return data["data"]["result"]
def run_checks():
"""执行所有巡检项"""
print(f"\n{'='*60}")
print(f"API 网关健康巡检 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"{'='*60}\n")
issues = []
for check in CHECKS:
try:
results = query_prometheus(check["query"])
if not results:
print(f"[SKIP] {check['name']}: 无数据")
continue
if check.get("expect") is not None:
value = float(results[0]["value"][1])
status = "OK" if value == check["expect"] else "FAIL"
print(f"[{status}] {check['name']}: {value}")
if status == "FAIL":
issues.append((check["severity"], check["name"], value))
elif check.get("threshold") is not None:
value = float(results[0]["value"][1])
if check.get("compare") == "gt":
exceeded = value > check["threshold"]
else:
exceeded = value < check["threshold"]
status = "OK" if not exceeded else "WARN"
print(f"[{status}] {check['name']}: {value:.2f} (阈值: {check['threshold']})")
if exceeded:
issues.append((check["severity"], check["name"], value))
except Exception as e:
print(f"[ERR] {check['name']}: {e}")
issues.append(("P0", check["name"], str(e)))
print(f"\n{'='*60}")
if issues:
print(f"发现 {len(issues)} 个问题:")
for sev, name, val in issues:
print(f" [{sev}] {name}: {val}")
else:
print("所有巡检项正常")
print(f"{'='*60}\n")
return len(issues) == 0
if __name__ == "__main__":
ok = run_checks()
sys.exit(0 if ok else 1)
这个脚本挂在 cron 里每小时跑一次,结果输出到运维群。比起被动等告警,主动巡检能在指标"开始变差但还没触发告警阈值"的时候就发现问题。比如活跃连接数从 3000 缓慢涨到 7000,还没到 10000 的告警阈值,但巡检脚本会标黄提示你"连接数在涨,该看看了"。
总结
API 网关监控不是"装个 Prometheus 插件就完了"。核心经验有三条:
指标采集要分层。别只看总量指标,把延迟拆成网关处理时间和上游响应时间,把错误率按状态码分类,把连接数按状态区分。分开看才能快速定位瓶颈在网关还是在后端。实测中,把上游延迟占比作为一个独立告警条件,能把故障定位时间砍掉一半——因为它直接告诉你"别在网关上浪费时间了,去查后端"。
告警阈值要分服务。不同类型的服务延迟特征天差地别,在线交易和批量导出用同一个阈值只会制造噪音。我见过最离谱的配置是所有服务统一 P99 > 100ms 告警,结果一个报表导出接口天天告警,SRE 最后把告警群设成了免打扰——然后真正出事的时候没人看到。
配置存储组件必须独立监控。不管你用 Kong+PostgreSQL 还是 APISIX+etcd,存储组件挂了网关不会立刻死,但你会失去对网关的控制权。别只信网关报告的"我能连上存储",要从存储侧独立验证。etcd 的 server_has_leader 和 PostgreSQL 的 pg_is_in_recovery 这类指标比网关侧的可达性检查可靠得多。
最后提一句仪表盘设计。好的监控大盘不是堆图表数量,是让你在 5 秒内回答"系统正不正常"。四行布局——全局概览、服务对比、延迟详情、底层状态——是我反复迭代后的方案,比最初堆了二十几个 panel 的版本好用得多。
参考资料与致谢
本文在撰写过程中参考了以下资料,感谢原作者的贡献:
- Kong Prometheus Plugin 官方文档 — Kong Inc., Prometheus 指标暴露插件的使用说明与配置参数
- Apache APISIX Prometheus Plugin — Apache APISIX, Prometheus 插件文档及指标说明
- Envoy Statistics 文档 — Envoy Proxy, 统计指标体系概览与配置方法
- 终极指南:Kong API网关性能监控的6个核心指标与告警实战 — CSDN, Kong 监控核心指标分析与告警规则设计
- Envoy Gateway 监控与运维:10个关键指标和最佳实践 — CSDN, Envoy Gateway 监控指标详解
- Prometheus 告警实战:写 alerting rules、用 Alertmanager 做路由分组与抑制 — CSDN, Prometheus 告警规则编写与 Alertmanager 路由配置