Xinference 可观测性体系:Supervisor 与 Worker 双端 Prometheus 指标导出器实战
【免费下载链接】inferenceSwap GPT for any LLM by changing a single line of code. Xinference lets you run open-source, speech, and multimodal models on cloud, on-prem, or your laptop — all through one unified, production-ready inference API.项目地址: https://gitcode.com/GitHub_Trending/in/inference
本文基于仓库文档 doc/source/user_guide/metrics.rst 展开,系统讲解 Xinference 集群中两类指标导出端点(Supervisor 端/metrics与 Worker 端独立 exporter)的开启方式、指标清单与底层实现原理,并结合 xinference/core/metrics.py 等源码说明指标注册、Registry 隔离与周期性刷新机制。读完本篇,你可以独立完成指标端点的配置与验证,并能准确理解每个指标的类型、标签和数据来源。
两类指标导出端点
一个 Xinference 集群中存在两类 metrics exporter,分别面向控制面与推理面:
- Supervisor 指标导出器:挂载在 Supervisor 的 RESTful 端点上,地址为
<endpoint>/metrics,例如http://127.0.0.1:9997/metrics。其中9997是默认服务端端口,对应 xinference/constants.py 中的XINFERENCE_DEFAULT_ENDPOINT_PORT = 9997。 - Worker 指标导出器:运行在每个 worker 节点上的独立进程,其监听地址与端口可通过
xinference-local或xinference-worker命令的--metrics-exporter-host(简写-MH)与--metrics-exporter-port(简写-mp)两个选项设置。
从 xinference/deploy/cmdline.py 的 CLI 定义可以看到两者的默认行为存在差异:
xinference-local:--metrics-exporter-host未指定时默认与--host相同(见local命令中if metrics_exporter_host is None: metrics_exporter_host = host的兜底逻辑),因此单机模式下 exporter 与主服务同主机。xinference-worker:--metrics-exporter-host默认为XINFERENCE_DEFAULT_DISTRIBUTED_HOST,端口需显式通过-mp指定。
Worker 端的 exporter 由 xinference/core/metrics.py 中的launch_metrics_export_server()启动:它新建一个 FastAPI 应用并注册/metrics路由(基于aioprometheus.asgi.starlette中间件),根路径/重定向到/metrics;服务使用 uvicorn 运行,日志级别固定为warning,并启用 xinference/core/http_protocol.py 中的加固 HTTP 协议以防御 Slowloris 类慢速攻击。启动后实际绑定的 socket 地址会经队列回传给 Worker 进程,写入启动日志(Starting metrics export server at {host}:{port}),方便定位。
禁用指标导出
通过环境变量XINFERENCE_DISABLE_METRICS=1可同时关闭两端导出器(判定逻辑见 xinference/constants.py 的is_metrics_disabled())。测试 xinference/core/tests/test_metrics.py 中的test_disable_metrics_exporter_server验证了禁用后的行为:
- Supervisor 端
GET {endpoint}/metrics返回404; - Worker 端 metrics 端口直接连接被拒(
ConnectionError)。
Supervisor 指标
文档列出的四个 Supervisor 侧指标均由aioprometheus的 Starlette 请求中间件自动采集,覆盖 RESTful API 的请求生命周期:
| 指标名 | 类型 | 含义 |
|---|---|---|
exceptions_total_counter | counter | 产生异常(抛出异常)的请求总数 |
requests_total_counter | counter | 接收到的请求总数 |
responses_total_counter | counter | 已发送的响应总数 |
status_codes_counter | counter | 各响应状态码的计数 |
/metrics路由在 RESTful API 进程中注册,见 xinference/api/restful_api.py:当is_metrics_disabled()为 False 时执行self._app.add_route("/metrics", metrics),且注册前会先从 Registry 中剔除_WORKER_ONLY_METRICS里的 worker 专属指标,避免 Supervisor 端出现空的HELP/TYPE头。测试 test_metrics_exporter_server 通过请求{endpoint}/metrics并断言响应中包含/v1/models,验证了该端点确实承载了 API 请求统计。
源码中的集群级指标(文档的纵深补充)
当前版本的 xinference/core/metrics.py 在 Supervisor 侧还注册了一整套集群/Worker/模型信息类 Gauge,由 API 进程中的_cluster_metrics_update_loop周期性调用update_cluster_metrics()从 Supervisor 的get_cluster_metrics_data()刷新:
| 指标名 | 含义 | 关键标签 |
|---|---|---|
xinference:supervisor_uptime_seconds | Supervisor 运行时长 | — |
xinference:workers_total | 在线 worker 数量 | — |
xinference:models_loaded_total | 按类型统计的已加载模型数 | model_type |
xinference:worker_cpu_utilization | Worker CPU 利用率(0-1) | worker_address |
xinference:worker_memory_used_bytes/worker_memory_total_bytes | Worker 内存已用/总量(字节) | worker_address |
xinference:worker_gpu_utilization_percent | Worker GPU 利用率(0-100) | worker_address,gpu_index,gpu_name |
xinference:worker_gpu_memory_used_bytes/worker_gpu_memory_total_bytes | Worker GPU 显存已用/总量(字节) | 同上 |
xinference:model_info | 运行中模型信息(值恒为 1) | model_uid,model_name,model_type,worker_address,replica_on_worker,replica_total |
xinference:model_status | 模型生命周期状态(值恒为 1) | model_uid,model_name,status |
xinference:model_gpu_binding | 每副本的 GPU 绑定关系(值恒为 1) | 增加gpu_index,replica_index |
xinference:model_gpu_memory_used_bytes | 按模型/GPU 的实时显存占用(字节) | 同上 |
xinference:model_unexpected_termination | 因 worker 故障而下线的副本(值恒为 1,重新部署后清除) | model_uid,model_name,replica_index |
xinference:build_info/xinference:config_info | 构建与配置信息(值恒为 1) | version,python_version,xinference_home,cluster等 |
除了这些,源码中还包含 Token Router 控制面快照指标族(如xinference:token_router_runtime_up、xinference:token_router_status等,见 metrics.py)与 API Key 审计指标(xinference:api_keys_active_total、xinference:banned_ips_total等),后者由update_security_gauges()周期刷新。
值得注意的实现细节:update_cluster_metrics()采用整帧快照 + 过期序列清理策略——每轮刷新时用_drop_series()从 Gauge 底层MetricDict中弹出本帧已不存在的标签组合,确保已下线 worker、已卸载模型不会在/metrics中残留过期时间序列(aioprometheus没有公开的remove()接口,这是从源码注释看唯一正确的删除方式)。
Worker 指标
文档列出的四个 Worker 侧(模型推理)指标:
| 文档指标名 | 类型 | 含义 |
|---|---|---|
xinference:generate_tokens_per_s | gauge | 生成吞吐,tokens/s |
xinference:input_tokens_total_counter | counter | 输入 token 总数 |
xinference:output_tokens_total_counter | counter | 输出 token 总数 |
xinference:time_to_first_token_ms | gauge | 首 token 延迟(ms) |
需要说明的是,当前仓库源码中对应采集器命名为xinference:generate_tokens_total(counter)与xinference:time_to_first_token_seconds(Histogram,桶边界 0.05s~inf),并标注 "LLM only",见 metrics.py。从源码结构看,文档中的generate_tokens_per_s/time_to_first_token_ms是早期版本的命名快照;当前版本的实际输出以源码为准,即吞吐需由 token 总量计数(配合 Prometheusrate())计算,TTFT 则以直方图形式支持分位数聚合。
除 LLM 指标外,源码还注册了覆盖所有模型类型的服务质量指标(metrics.py):
| 指标名 | 类型 | 含义 |
|---|---|---|
xinference:model_request_total | counter | 模型请求总数 |
xinference:model_request_errors_total | counter | 失败的模型请求总数 |
xinference:model_request_duration_seconds | histogram | 模型请求耗时(14 个桶,0.01s~120s) |
xinference:model_serve_count | gauge | 当前正在处理的请求数 |
xinference:model_request_limit | gauge | 模型并发请求上限 |
xinference:model_last_load_duration_seconds | gauge | 最近一次模型加载耗时 |
指标如何被记录与输出
Worker 推理路径通过model_ref.record_metrics(name, op, kwargs)上报数据,该调用最终落到 metrics.py 的record_metrics():以指标名为键从全局命名空间取出采集器,按操作(inc/set/observe)反射调用,任何异常仅记录日志而不影响推理主流程。测试 test_metrics_exporter_server 展示了端到端效果:
# 向模型上报一次输入 token 计数后,GET {worker_metrics_address} 可看到: xinference:input_tokens_total_counter{model_uid="qwen1.5-chat"} 1test_metrics_exporter_data则进一步断言了模型元信息标签的完整性,输出中包含format="ggufv2",gpu_index="",model_name="qwen1.5-chat",model_type="LLM",model_uid="qwen1.5-chat",说明指标携带了足以区分格式、GPU 与模型实例的标签集。
双端 Registry 隔离机制
Supervisor 与 Worker 共用同一份指标定义文件,但两个端点暴露的指标集必须互不污染。metrics.py 用两个集合显式划分:
_SUPERVISOR_ONLY_METRICS:集群/Worker/模型信息与 Token Router、API Key 审计等 60 余项。Worker 启动 exporter 时,launch_metrics_export_server()会在进程内遍历REGISTRY.get_all()并deregister这些采集器,避免 Worker 端输出大量恒为空/零的序列头。_WORKER_ONLY_METRICS:上述 9 项 LLM 推理与服务质量指标。RESTful API 进程注册/metrics路由前同样会将其剔除。
从源码结构看,这一"同一模块、按角色裁剪"的设计使指标定义集中维护,同时保证每个端点的/metrics输出都是最小且干净的。
实操:配置与验证
1. 单机模式(默认端点)
xinference-local --host 127.0.0.1 --port 9997 # metrics exporter 默认与 --host 相同,端口需显式指定: xinference-local --host 127.0.0.1 --port 9997 \ --metrics-exporter-port 9999验证:
curl http://127.0.0.1:9997/metrics # Supervisor:请求计数 + 集群/模型 Gauge curl http://127.0.0.1:9999/metrics # Worker 端 exporter:token 计数、TTFT、请求耗时等2. 分布式模式
xinference-supervisor --host 10.0.0.1 --port 9997 xinference-worker --endpoint http://10.0.0.1:9997 \ --host 10.0.0.2 \ --metrics-exporter-host 10.0.0.2 \ --metrics-exporter-port 9999Prometheus 抓取时建议把 Supervisor 的<endpoint>/metrics与每个 worker 的 exporter 地址都配置为 scrape target(worker 地址取自启动日志或xinference:model_info的worker_address标签)。
3. 关闭指标
XINFERENCE_DISABLE_METRICS=1 xinference-local # 效果:/metrics 返回 404,worker exporter 端口不监听4. 典型 PromQL 用法
# LLM 生成吞吐(由源码中的 token 计数推导) rate(xinference:output_tokens_total_counter{model_uid="qwen1.5-chat"}[1m]) # 首 token 延迟 P99 histogram_quantile(0.99, sum(rate(xinference:time_to_first_token_seconds_bucket[5m])) by (le)) # 模型请求成功率 1 - rate(xinference:model_request_errors_total[5m]) / rate(xinference:model_request_total[5m]) # 单模型 GPU 显存占用 xinference:model_gpu_memory_used_bytes小结
Xinference 的指标体系以"Supervisor 控制面 + Worker 推理面"双导出器为核心:前者通过 API 进程的/metrics路由暴露请求统计与集群资源快照,后者以独立 uvicorn 进程暴露 token 吞吐、TTFT 与请求耗时等推理质量指标。两端共用 xinference/core/metrics.py 中的采集器定义,通过_SUPERVISOR_ONLY_METRICS/_WORKER_ONLY_METRICS按角色裁剪,并支持XINFERENCE_DISABLE_METRICS=1一键关闭。仓库中 monitor/ 目录还附带了 DCGM exporter 配置与 Grafana 仪表盘 JSON,可作为接入现有监控栈的进一步参考。
【免费下载链接】inferenceSwap GPT for any LLM by changing a single line of code. Xinference lets you run open-source, speech, and multimodal models on cloud, on-prem, or your laptop — all through one unified, production-ready inference API.项目地址: https://gitcode.com/GitHub_Trending/in/inference
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考