最轻量可控的 Prometheus metrics server 方式是用 prometheus-client 单独启 HTTP server,需在 daemon 线程中运行 start_http_server,端口与 scrape_config 一致,指标类型(Counter/Gauge)和命名(小写+下划线)须严格合规,更新须覆盖所有执行路径,多进程需 MultiProcessCollector。

直接用 prometheus-client 启一个独立的 HTTP metrics server,是最轻量、最可控的方式;别把它塞进 Flask/FastAPI 的主路由里,否则容易卡死或被中间件吞掉响应。
start_http_server 必须在 daemon 线程里跑
这个函数是阻塞式的——它会一直占住当前线程,直到进程退出。如果你写成:
start_http_server(8001)
那后面所有代码都不会执行,Web 服务根本起不来。
- 必须用
threading.Thread启动,并设daemon=True,避免程序退出时残留线程 - 端口要和 Prometheus 的
scrape_config.targets一致,比如localhost:8001 - 在 Docker/K8s 里注意:容器内
localhost指自己,要用host.docker.internal:8001(Mac/Win)或 Service 名(K8s)
指标类型选错,数据就废了
Counter 和 Gauge 不是随便换着用的。用错一个,Grafana 里要么全是 0,要么突变断崖。
-
Counter只增不减:适合累计值,如http_requests_total、spider_errors_total -
Gauge可设可增可减:适合瞬时状态,如queue_length、app_pending_tasks -
Histogram和Summary开销大,只在真要 P95/P99 延迟时用;普通耗时打点优先用@decorator包裹的Summary
命名不合规,Prometheus 直接拒收
你 curl http://localhost:8001/metrics 能看到内容,但 Prometheus targets 页面显示 DOWN 或日志报 invalid metric name,八成是命名问题。
- 必须全小写 + 下划线:
myapp_http_requests_total✅,MyAppRequestsTotal❌ - 必须以字母开头,不能含空格、点、破折号、大写字母
- label 名也要
snake_case:.labels(status_code='500')✅,.labels(statusCode='500')❌ - 建议加业务前缀(如
myapp_),避免和process_cpu_seconds_total这类系统指标冲突
更新指标必须覆盖所有执行路径
漏掉一个 except 分支、没写进 finally、异步函数里忘了 await 就返回——指标就会停滞、归零,告警完全失效。
- 所有
.inc()、.set()必须放在try/except的finally块里,或每个分支都显式调用 - 异步函数中更新
Gauge时,确保await完成后再调.set(),否则并发写入可能脏数据 - 批量任务场景下,别只在循环外
.inc(100),应每次处理完一个就.inc(),才能反映真实速率
最常被忽略的一点:多进程部署(如 Gunicorn 多 worker)时,start_http_server 会抢端口。这时候得改用 make_wsgi_app() + WSGI 中间件,或启用 MultiProcessCollector 配合文件共享机制。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











