Router 常见问题排查

March 17, 2026 · View on GitHub

English

Router 常见问题排查

本文档基于 Golang Router 的代码实现,汇总了 Router 在使用过程中常见的日志信息、返回输出及问题排查方法,帮助用户快速定位和解决问题。

Router 的基本使用方式请参考 负载均衡调度 Router

常见日志分析

说明{} 表示变量,实际日志中会替换为具体的值。

Error 级别日志

日志表现日志含义导致结果可排查内容
Removed unhealthy prefill instance: {url}Prefill 实例健康检查失败,已被移除该 Prefill 实例不再参与调度健康状况
Removed unhealthy decode instance: {url}Decode 实例健康检查失败,已被移除该 Decode 实例不再参与调度健康状况
Removed unhealthy mixed instance: {url}Mixed 实例健康检查失败,已被移除该 Mixed 实例不再参与调度健康状况
Failed to register instance: {error}实例注册失败Router 无法注册该实例健康状况、注册参数
Failed to read YAML file {path}: {error}启动时无法读取注册配置文件配置文件中的实例无法被注册文件路径、文件权限
Failed to unmarshal YAML file {path}: {error}注册配置文件格式解析错误配置文件中的实例无法被注册YAML 格式
Failed to register instance from index {index}: {error}配置文件中第 {index} 个实例注册失败该实例未能成功注册健康状况、注册参数
failed to send request to {url} with error: {error}健康检查请求发送失败该实例可能被判定为不健康网络连通性、代理设置
scanner error: {error}读取后端流式响应时发生错误当前请求可能失败后端实例状态
[prefill] scanner error: {error}, message={message}读取 Prefill 后端流式响应时发生错误当前 Prefill 请求可能失败后端实例状态
[prefill] copy error: {error}, message={message}复制 Prefill 响应数据时发生错误当前 Prefill 请求可能失败后端实例状态
Panic recovered: {error}请求处理过程中发生 panic 并被恢复当前请求失败,但服务继续运行后端实例状态、请求内容
empty baseURL provided健康检查时传入了空的基础 URL健康检查无法执行注册参数
failed to create request: {error}创建健康检查请求失败该实例可能被判定为不健康网络环境
failed to read response body: {error}读取健康检查响应体失败该实例可能被判定为不健康后端实例状态

Warn 级别日志

日志表现日志含义导致结果可排查内容
Server {url} is not healthy该 URL 对应的实例未通过健康检查Router 无法注册该实例,或将该实例从已注册列表中移除健康状况
Instance {url} role is unknown实例角色无法识别该实例不会被加入调度列表注册参数
cache-aware prefill: tokenizer failed, fallback to char tokens: {error}Tokenizer 服务调用失败,已自动回退至字符级分词cache_aware 策略仍然生效,使用字符级分词代替 Tokenizer 进行缓存匹配,不影响正常请求处理Tokenizer 服务状态
cache-aware prefill: tokenize failed, fallback to process_tokens: {error}分词彻底失败(如输入为空),回退至 process_tokens 策略Prefill 调度暂时不使用 cache_aware 策略,不影响正常请求处理请求内容、Tokenizer 服务状态
cache-aware prefill: final strategy: process_tokens, reason: tokenize failed: {error}. ts_ms={ts}分词失败(新格式),回退至 process_tokens 策略Prefill 调度暂时不使用 cache_aware 策略,不影响正常请求处理请求内容、Tokenizer 服务状态

Info 级别日志

日志表现日志含义说明
Starting server on {host:port}Router 服务正在启动正常启动日志
Server {url} is healthy实例健康检查通过正常运行日志
Successfully registered instance from index {index}配置文件中的实例注册成功正常启动日志
No instances found in config file {path}注册配置文件中未找到实例信息请检查 register.yaml 内容是否为空
Request completed successfully.请求处理完成正常运行日志
Request failed, retrying...请求失败,正在进行重试Router 最多重试 3 次
select worker (prefill): {url}, tokens: {tokens}Prefill 调度选中 Worker,显示当前 token 处理量正常运行日志
select worker ({type}): {url}, count: {count}Decode/Mixed 调度选中 Worker,显示当前请求并发数正常运行日志
release worker: {url}, count: {count}请求结束,释放 Worker 计数器正常运行日志
release prefill tokens: {url}, tokens: {tokens}Prefill 请求结束,释放 token 负载正常运行日志
cleanup unhealthy worker counter: {url}清理不健康 Worker 的计数器正常运行日志
removed counters for {count} unhealthy workers: {urls}批量清理不健康 Worker 的计数器正常运行日志
[stats] total_running={n}, workers: [{loads}], cache_hit_rate={rate}% (hits={hits}/total={total})周期性统计:总请求数、各 Worker 负载、缓存命中率正常运行日志,用于监控调优
Parsing completed; starting worker selection.请求解析完成,开始选择 Worker正常运行日志
Request completed with an error.请求处理完成但发生错误请排查后端实例状态
[SelectWorkerPair] decode selection failed, releasing prefill counter url={url}PD 分离模式下 Decode 选择失败,释放 Prefill 计数器异常处理日志
[prefill] first chunk received, release counter url={url}Prefill 流式响应收到首个数据块,释放计数器正常运行日志
[prefill] non-stream prefill response done, release counter url={url}Prefill 非流式响应完成,释放计数器正常运行日志
[prefill] backendResp is nil or backendResp.Body is nil, url={url}Prefill 后端响应为空可能表示后端连接异常
[prefill] release in defer (fallback) url={url}, isStream={bool}Prefill 请求异常退出时的兜底资源释放异常处理日志
[prefill] release in CommonCompletions defer (error path) url={url}请求出错时释放 Prefill 资源异常处理日志
cache-aware prefill: final strategy: process_tokens, reason: strategy not initializedcache_aware 策略未初始化,回退至 process_tokens请检查 cache_aware 相关配置
cache-aware prefill: final strategy: process_tokens, reason: load imbalanced, loads={loads}. ts_ms={ts}实例间负载不均衡,回退至 process_tokens 策略正常运行日志,负载均衡自动切换
cache-aware prefill: final strategy: cache_aware_scoring, selected={url}, loads={loads}, hitRatios={ratios}. ts_ms={ts}cache_aware 打分策略选中 Worker正常运行日志,显示负载和命中率
[{method}] {path} {proto} {status} {latency} {clientIP}HTTP 请求访问日志正常运行日志,记录每个请求的基本信息
before SelectWorker prefill. ts_ms={ts}PD 分离模式下开始选择 Prefill Worker正常运行日志,用于性能追踪
before SelectWorker decode, after prefill. ts_ms={ts}Prefill 选择完成后开始选择 Decode Worker正常运行日志,用于性能追踪
after SelectWorker decode, before return. ts_ms={ts}Decode Worker 选择完成正常运行日志,用于性能追踪

Debug 级别日志

Debug 级别日志需要将日志级别设置为 debug 才会输出,通常用于开发调试。

日志表现日志含义说明
Healthy instances: prefill={urls}, decode={urls}, mixed={urls}列出当前各角色的健康实例列表用于确认实例发现是否正常
cache-aware prefill: hashes={n} workers={n} load={loads} hit={hits}cache_aware 策略的 hash 数量、Worker 数量及负载信息用于调试缓存命中
cache-aware prefill: tokenizer tokens={tokens}Tokenizer 分词结果用于调试分词结果
cache-aware score: worker={url} hit={hit} loadRatio={ratio} score={score}cache_aware 策略的打分详情用于调试调度决策
radix match: hashes={n} matched_len={n} node_children={n}前缀树匹配详情用于调试缓存匹配
radix record: worker={url} hashes={n} node_depth={n}前缀树记录详情用于调试缓存记录
radix eviction: removed={n} nodeCount={n}前缀树淘汰详情用于调试缓存淘汰

常见返回输出分析

推理请求错误(/v1/chat/completions、/v1/completions)

输出表现HTTP 状态码含义可排查内容
{"error": "No available prefill/decode workers"}503Prefill 或 Decode 实例全部不可用,没有已注册的健康实例健康状况
{"error": "Failed to select worker pair"}502PD 分离模式下选择 Worker 对失败健康状况、调度策略
{"error": "Failed to select worker"}502集中式模式下选择 Worker 失败健康状况、调度策略
{"error": "Failed to connect to backend service"}502连接后端推理实例失败(已重试 3 次仍失败)后端实例状态、网络连通性
{"error": "Failed to build disaggregate_info"}500构建 PD 分离通信信息失败注册参数(connector_port、device_ids 等)
{"error": "Invalid request body"}400请求体读取失败请求格式
{"error": "Invalid JSON format"}400请求体 JSON 解析失败请求格式

注册请求错误(/register)

输出表现HTTP 状态码含义可排查内容
{"code": 503, "msg": "{url} service is not healthy"}503实例健康检查未通过,无法注册健康状况
{"code": 400, "msg": "Invalid request body"}400注册请求体读取失败请求格式
{"code": 400, "msg": "Invalid InstanceInfo JSON format: {error}"}400注册请求 JSON 格式错误请求格式
{"code": 400, "msg": "splitwise mode only supports PREFILL/DECODE instances"}400PD 分离模式下不允许注册 MIXED 实例部署模式、实例角色
{"code": 400, "msg": "only MIXED instances are allowed"}400集中式模式下只允许注册 MIXED 实例部署模式、实例角色
{"code": 400, "msg": "invalid InstanceInfo format: {error}"}400实例注册信息校验失败注册参数
{"code": 200, "msg": "Register success"}200注册成功

常见注册参数校验错误

错误信息含义解决方法
role is required缺少 role 字段添加 role 字段,可选值:prefill / decode / mixed
invalid role: {role}role 值不合法使用合法的 role 值:prefill / decode / mixed
host_ip is required缺少 host_ip 字段添加 host_ip 字段
invalid host_ip: {ip}host_ip 不是合法的 IP 地址填写正确的 IP 地址
port is required缺少 port 字段添加 port 字段
invalid port: {port}port 不是合法的端口号填写 1-65535 范围内的端口号
invalid protocol: {protocol}传输协议不合法使用合法的协议值:ipc / rdma

常见问题排查方式

健康状况

实例健康检查是 Router 正常运行的基础。当出现实例无法注册或被移除的情况时,请按以下步骤排查:

1. 查看实例注册情况

查看 Router 当前已注册的实例列表和数量:

# 查看已注册实例列表
curl -X GET http://{router_url}/registered

# 查看已注册实例数量
curl -X GET http://{router_url}/registered_number

确认所有预期实例是否都已注册成功。如果实例数量不符,说明部分实例注册失败或已被健康检查移除。

2. 检查实例健康状态与网络连通性

从 Router 所在机器直接访问推理实例的健康接口:

curl -X GET http://{server_url}/health
  • 返回 HTTP 200 表示实例健康且网络连通
  • 无法访问或返回非 200 状态码,请进一步排查:
    • 实例是否已启动并监听在正确端口上
    • Router 与实例之间是否存在代理干扰(尝试关闭代理:unset http_proxy && unset https_proxy
    • 是否存在防火墙限制

常见解决方式:

  • 关闭网络代理:unset http_proxy && unset https_proxy
  • gunicorn 版本兼容问题:如果出现注册实例数不全的情况,可能是 gunicorn 与 FastDeploy 版本不兼容,回退至 gunicorn==25.0.3 可解决

调度策略

当出现 Failed to select workerFailed to select worker pair 错误时:

1. 确认已注册实例数

curl -X GET http://{router_url}/registered_number

如果返回的实例数为 0,说明没有可用的健康实例,请先参考健康状况排查。

2. 检查调度策略配置

确认 config.yaml 中的调度策略与部署模式匹配。Router 的默认调度策略如下:

部署模式配置项默认策略
集中式模式policyrequest_num
PD 分离模式(Prefill 节点)prefill-policyprocess_tokens
PD 分离模式(Decode 节点)decode-policyrequest_num

如未通过配置文件指定策略,Router 将使用上述默认策略进行调度。如需使用 cache_awarefd_metrics_score 等高级策略,请通过配置文件显式指定。各策略的详细说明请参考 调度策略说明

3. 检查 fd_metrics_score 策略的依赖

使用 fd_metrics_score 策略时,Router 会实时从推理实例的 /metrics 接口获取 running/waiting 请求数进行打分调度。当 /metrics 接口不可用时(如实例未配置 metrics_port 或 metrics 服务异常),Router 会自动回退至内部请求计数器进行调度,不影响正常的请求处理,但调度精度会有所下降。

如需确保 fd_metrics_score 策略获得最佳调度效果,请确认推理实例的 metrics 接口正常返回:

curl -X GET http://{server_url}/metrics

注册参数

当注册失败且返回参数校验错误时:

1. 检查部署模式与实例角色是否匹配

  • PD 分离模式(--splitwise):只能注册 prefilldecode 角色的实例
  • 集中式模式(默认):只能注册 mixed 角色的实例

2. 检查必填参数

注册请求必须包含以下字段:

  • role:实例角色(prefill / decode / mixed)
  • host_ip:实例 IP 地址
  • port:实例端口号

3. 检查 PD 分离模式下的可选参数

PD 分离模式下建议完整配置以下参数,以确保 KV Cache 传输正常:

  • connector_port:PD 通信端口
  • transfer_protocol:传输协议(ipc / rdma)
  • device_ids:GPU 设备 ID
  • rdma_ports:RDMA 端口(使用 rdma 协议时必填)

启动失败

1. 配置文件加载失败

启动时日志出现 Failed to load config,请检查:

  • --config_path 指向的文件路径是否正确
  • 配置文件是否为合法的 YAML 格式
  • 配置参数值是否合法

2. 端口被占用

启动时日志出现 Failed to start server,请检查:

  • --port 指定的端口是否已被其他进程占用
  • 可使用 lsof -i:{port}netstat -tlnp | grep {port} 确认端口使用情况

Tokenizer 服务(cache_aware 策略)

使用 cache_aware 调度策略时,Router 会调用 Tokenizer 服务对请求进行分词以计算缓存命中率。当 Tokenizer 服务不可用时,Router 内置了两级退化机制:

  1. 回退至字符级分词(常见情况):日志出现 tokenizer failed, fallback to char tokens。此时 cache_aware 策略仍然生效,只是使用字符级分词代替 Tokenizer 进行缓存匹配,缓存命中精度会有所下降,但不影响正常请求处理。
  2. 回退至 process_tokens 策略(极端情况):当分词彻底失败(如请求内容为空)时,日志出现 tokenize failed, fallback to process_tokens。此时 cache_aware 策略暂时不生效,改为按 token 处理量进行调度,同样不影响正常请求处理。

如需恢复 cache_aware 策略的完整功能:

1. 检查 Tokenizer 服务是否正常运行

curl -X POST http://{tokenizer_url}/tokenize \
  -H "Content-Type: application/json" \
  -d '{"text": "hello"}'

2. 检查相关配置

  • 确认 config.yaml 中 tokenizer-url 配置正确
  • 如果 Tokenizer 服务响应较慢,可适当增大 tokenizer-timeout-secs(默认 2 秒)