Prometheus Exporter 是暴露监控指标的小程序,核心是将自定义业务/系统指标转为 Prometheus 可识别格式,并通过默认 /metrics HTTP 接口供其抓取;推荐使用 prometheus_client 的 start_http_server 启动轻量内置服务,而非手写或混用 Flask/FastAPI,避免并发问题与指标失真。

用 prometheus_client 暴露指标端点,别手写 HTTP 服务
直接起一个独立的 Flask/FastAPI 服务来返回 Prometheus 格式文本,既冗余又容易出错。正确做法是用 prometheus_client 自带的 start_http_server——它启动的是轻量级内置 WSGI server,专为指标暴露设计,不干扰你的主 Web 服务。
常见错误:在 FastAPI 里手动注册 /metrics 路由并调用 generate_latest(),结果并发请求时指标被锁住或漏采样。这不是 bug,是反模式。
- 安装:
pip install prometheus-client - 在应用启动后(比如
if __name__ == "__main__":块里)调用start_http_server(8001),端口避开主服务端口 - 确保该端口未被防火墙或容器网络策略拦截;Kubernetes 中需显式开放
targetPort
用 Summary 记录单个接口的延迟与请求计数,别用 Histogram 硬凑
Histogram 适合观测分布(如 P95/P99),但要精确统计 QPS 和平均延迟,Summary 更直接:它原生提供 _count 和 _sum 指标,除一下就是均值,rate() 一下就是 QPS。
误区:给每个路径都定义独立 Histogram,导致指标爆炸(http_request_duration_seconds_bucket{path="/api/user",le="0.1"} → 组合爆炸)。而 Summary 支持 labels,且无预设分桶开销。
- 定义:
REQUEST_TIME = Summary('http_request_duration_seconds', 'HTTP request duration', ['method', 'endpoint']) - 在中间件或路由 handler 开头调用
timer = REQUEST_TIME.labels(method=request.method, endpoint=request.url.path).time() - 在响应返回前调用
timer.observe()(自动结束计时并上报) - PromQL 查 QPS:
rate(http_request_duration_seconds_count[1m]);查平均延迟:rate(http_request_duration_seconds_sum[1m]) / rate(http_request_duration_seconds_count[1m])
在 ASGI(FastAPI/Starlette)中加中间件,别在每个路由里重复埋点
手动在每个 @app.get() 里写 time() 和 observe(),不仅易漏,还污染业务逻辑。ASGI 中间件能统一拦截所有请求,天然适配生命周期管理。
注意:不要用 BaseHTTPMiddleware 的 dispatch 方法捕获异常后忽略 —— 这会导致失败请求不计入 _count,QPS 虚高,延迟失真。
- FastAPI 示例:继承
BaseHTTPMiddleware,在dispatch开头start = time.time(),结尾无论成功失败都计算耗时并调用REQUEST_TIME.labels(...).observe(elapsed) - 必须捕获并重新抛出异常,否则中间件链中断,后续中间件(如日志、CORS)不执行
- label 值要 sanitize:避免将用户输入(如 UUID 路径参数)直接当
endpointlabel,防止标签爆炸;建议统一截断为静态路由模板(/api/user/{id})
部署后指标不更新?检查 scrape_interval 与 job 配置是否匹配
Prometheus 默认每 15 秒拉取一次,但如果你的应用刚启动,或者 start_http_server 调用晚于 main thread 启动,首次 scrape 可能拿到空指标。这不是代码问题,是配置时序问题。
典型现象:Prometheus targets 页面显示 UP,但 http_request_duration_seconds_count 始终为 0;或只有重启后前几秒有数据,之后归零。
- 确认 Prometheus 的
scrape_config中job_name与你的服务发现方式一致(static_configs / kubernetes_sd_configs) - 检查
metrics_path是否为/metrics(默认值),若改过需显式指定 - 临时验证:
curl http://your-app:8001/metrics | grep http_request_duration_seconds_count,看输出是否实时增长 - 如果用 Kubernetes,确保
podMonitor或serviceMonitor的namespaceSelector和selector正确匹配目标 Service
指标不是埋完就完事——label 设计不合理、scrape 频率和应用生命周期不同步、异常路径漏统计,这三处最容易让 QPS 和延迟数据失去参考价值。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











