Skip to content

Commit b61731b

Browse files
authored
[Feature][Docs] Adjust prefill release & expose load metrics (PaddlePaddle#6884)
1 parent daaf498 commit b61731b

20 files changed

Lines changed: 575 additions & 58 deletions

File tree

docs/online_serving/router.md

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ server:
190190
splitwise: true # true enables PD disaggregation; false disables it
191191

192192
scheduler:
193-
policy: "power_of_two" # Scheduling policy (optional): random, power_of_two, round_robin, process_tokens, request_num, cache_aware, fd_metrics_score
193+
policy: "power_of_two" # Scheduling policy (optional): random, power_of_two, round_robin, process_tokens, request_num, cache_aware, remote_cache_aware, fd_metrics_score, fd_remote_metrics_score
194194
prefill-policy: "cache_aware" # Prefill scheduling policy in PD mode
195195
decode-policy: "fd_metrics_score" # Decode scheduling policy in PD mode
196196
eviction-interval-secs: 60 # Cache eviction interval for CacheAware scheduling
@@ -199,9 +199,13 @@ scheduler:
199199
hit-ratio-weight: 1.0 # Cache hit ratio weight
200200
load-balance-weight: 0.05 # Load balancing weight
201201
cache-block-size: 4 # Cache block size
202-
tokenizer-url: "http://0.0.0.0:8098" # Tokenizer service endpoint (optional)
203-
tokenizer-timeout-secs: 2 # Tokenizer service timeout
202+
# tokenizer-url: "http://0.0.0.0:8098" # Tokenizer service endpoint (optional), cache_aware uses character-level tokenization when not configured.
203+
# Note: Enabling this option causes a synchronous remote tokenizer call on every scheduling decision,
204+
# introducing additional network latency. Only enable it when precise token-level tokenization
205+
# is needed to improve cache hit rate.
206+
# tokenizer-timeout-secs: 2 # Tokenizer service timeout; default: 2
204207
waiting-weight: 10 # Waiting weight for CacheAware scheduling
208+
stats-interval-secs: 5 # Stats logging interval in seconds, includes load and cache hit rate statistics; default: 5
205209

206210
manager:
207211
health-failure-threshold: 3 # Number of failed health checks before marking unhealthy
@@ -254,6 +258,24 @@ Instance Registration Parameters:
254258
255259
Among these, `role`, `host_ip`, and `port` are required; all other parameters are optional.
256260

261+
## Scheduling Strategies
262+
263+
The Router supports the following scheduling strategies, configurable via `policy` (mixed mode), `prefill-policy`, and `decode-policy` (PD disaggregated mode) fields in the configuration file.
264+
265+
**Default strategies**: When not configured, prefill nodes default to `process_tokens`, mixed and decode nodes default to `request_num`.
266+
267+
| Strategy | Applicable Scenario | Implementation |
268+
|----------|---------------------|----------------|
269+
| `random` | General | Randomly selects one available instance, stateless, suitable for lightweight scenarios. |
270+
| `round_robin` | General | Uses atomic counter to cycle through instance list, distributing requests evenly in order. |
271+
| `power_of_two` | General | Randomly picks two instances, compares their concurrent request counts, selects the one with lower load. |
272+
| `process_tokens` | **prefill (default)** | Iterates all instances, selects the one with the fewest tokens currently being processed (in-memory counting), suitable for prefill long-request load balancing. |
273+
| `request_num` | **mixed / decode (default)** | Iterates all instances, selects the one with the fewest concurrent requests (in-memory counting), suitable for decode and mixed scenarios. |
274+
| `fd_metrics_score` | mixed / decode | Uses in-memory counting to get running/waiting request counts, scores by `running + waiting × waitingWeight`, selects the instance with the lowest score. |
275+
| `fd_remote_metrics_score` | mixed / decode | Fetches running/waiting request counts from each instance's remote `/metrics` endpoint in real-time, scores by `running + waiting × waitingWeight`, selects the instance with the lowest score. Requires `metrics_port` in instance registration. **Note: A synchronous remote HTTP request is issued on every scheduling decision. With a large number of instances or poor network conditions, this can significantly increase scheduling latency. Evaluate your deployment conditions carefully before enabling this strategy.** |
276+
| `cache_aware` | prefill | Maintains KV Cache prefix hit information per instance via Radix Tree, selects instances by combining hit ratio and load scores (in-memory counting); automatically falls back to `process_tokens` when load is severely imbalanced. |
277+
| `remote_cache_aware` | prefill | Same cache-aware strategy as `cache_aware`, but uses remote `/metrics` endpoint for instance load data. Requires `metrics_port` in instance registration. **Note: A synchronous remote HTTP request is issued on every scheduling decision. With a large number of instances or poor network conditions, this can significantly increase scheduling latency. Evaluate your deployment conditions carefully before enabling this strategy.** |
278+
257279
## Troubleshooting
258280

259281
If you encounter issues while using the Router, please refer to the [Router Troubleshooting Guide](router_faq.md), which covers common log analysis, response output interpretation, and troubleshooting methods.

docs/online_serving/router_faq.md

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,22 @@ For basic Router usage, please refer to [Load-Balancing Scheduling Router](route
2323
| `Failed to register instance from index {index}: {error}` | Instance at index {index} in config file failed to register | That instance was not registered | Health status, registration parameters |
2424
| `failed to send request to {url} with error: {error}` | Health check request failed to send | The instance may be marked as unhealthy | Network connectivity, proxy settings |
2525
| `scanner error: {error}` | Error occurred while reading backend streaming response | The current request may fail | Backend instance status |
26+
| `[prefill] scanner error: {error}, message={message}` | Error occurred while reading Prefill backend streaming response | The current Prefill request may fail | Backend instance status |
27+
| `[prefill] copy error: {error}, message={message}` | Error occurred while copying Prefill response data | The current Prefill request may fail | Backend instance status |
28+
| `Panic recovered: {error}` | A panic occurred during request processing and was recovered | The current request fails, but the service continues running | Backend instance status, request content |
29+
| `empty baseURL provided` | Health check received an empty base URL | Health check cannot be performed | Registration parameters |
30+
| `failed to create request: {error}` | Failed to create health check request | The instance may be marked as unhealthy | Network environment |
31+
| `failed to read response body: {error}` | Failed to read health check response body | The instance may be marked as unhealthy | Backend instance status |
2632

2733
### Warn-Level Logs
2834

2935
| Log Message | Meaning | Impact | What to Check |
3036
| :--- | :--- | :--- | :--- |
3137
| `Server {url} is not healthy` | The instance at this URL failed health check | Router cannot register the instance, or will remove it from the registered list | Health status |
3238
| `Instance {url} role is unknown` | Instance role cannot be recognized | The instance will not be added to the scheduling list | Registration parameters |
33-
| `cache-aware prefill: tokenizer failed, fallback to process_tokens: {error}` | Tokenizer service call failed, automatically falling back to process_tokens strategy | Prefill scheduling temporarily does not use cache_aware strategy; normal request processing is not affected | Tokenizer service status |
39+
| `cache-aware prefill: tokenizer failed, fallback to char tokens: {error}` | Tokenizer service call failed, automatically falling back to character-based tokenization | cache_aware strategy remains active, using character-based tokenization for cache matching instead of the Tokenizer; normal request processing is not affected | Tokenizer service status |
40+
| `cache-aware prefill: tokenize failed, fallback to process_tokens: {error}` | Tokenization completely failed (e.g., empty input), falling back to process_tokens strategy | Prefill scheduling temporarily does not use cache_aware strategy; normal request processing is not affected | Request content, Tokenizer service status |
41+
| `cache-aware prefill: final strategy: process_tokens, reason: tokenize failed: {error}. ts_ms={ts}` | Tokenization failed (new format), falling back to process_tokens strategy | Prefill scheduling temporarily does not use cache_aware strategy; normal request processing is not affected | Request content, Tokenizer service status |
3442

3543
### Info-Level Logs
3644

@@ -42,6 +50,42 @@ For basic Router usage, please refer to [Load-Balancing Scheduling Router](route
4250
| `No instances found in config file {path}` | No instances found in the registration config file | Check whether register.yaml is empty |
4351
| `Request completed successfully.` | Request processing completed | Normal operation log |
4452
| `Request failed, retrying...` | Request failed, retrying | Router will retry up to 3 times |
53+
| `select worker (prefill): {url}, tokens: {tokens}` | Prefill scheduler selected a worker, showing current token processing count | Normal operation log |
54+
| `select worker ({type}): {url}, count: {count}` | Decode/Mixed scheduler selected a worker, showing current request concurrency | Normal operation log |
55+
| `release worker: {url}, count: {count}` | Request ended, worker counter released | Normal operation log |
56+
| `release prefill tokens: {url}, tokens: {tokens}` | Prefill request ended, token load released | Normal operation log |
57+
| `cleanup unhealthy worker counter: {url}` | Cleaned up counter for unhealthy worker | Normal operation log |
58+
| `removed counters for {count} unhealthy workers: {urls}` | Batch cleanup of counters for unhealthy workers | Normal operation log |
59+
| `[stats] total_running={n}, workers: [{loads}], cache_hit_rate={rate}% (hits={hits}/total={total})` | Periodic stats: total requests, worker loads, cache hit rate | Normal operation log, useful for monitoring and tuning |
60+
| `Parsing completed; starting worker selection.` | Request parsing completed, starting worker selection | Normal operation log |
61+
| `Request completed with an error.` | Request processing completed with an error | Check backend instance status |
62+
| `[SelectWorkerPair] decode selection failed, releasing prefill counter url={url}` | Decode selection failed in PD disaggregated mode, releasing Prefill counter | Error handling log |
63+
| `[prefill] first chunk received, release counter url={url}` | Prefill streaming response received first chunk, counter released | Normal operation log |
64+
| `[prefill] non-stream prefill response done, release counter url={url}` | Prefill non-streaming response completed, counter released | Normal operation log |
65+
| `[prefill] backendResp is nil or backendResp.Body is nil, url={url}` | Prefill backend response is nil | May indicate backend connection issue |
66+
| `[prefill] release in defer (fallback) url={url}, isStream={bool}` | Fallback resource release when Prefill request exits abnormally | Error handling log |
67+
| `[prefill] release in CommonCompletions defer (error path) url={url}` | Prefill resource release on error path | Error handling log |
68+
| `cache-aware prefill: final strategy: process_tokens, reason: strategy not initialized` | cache_aware strategy not initialized, falling back to process_tokens | Check cache_aware configuration |
69+
| `cache-aware prefill: final strategy: process_tokens, reason: load imbalanced, loads={loads}. ts_ms={ts}` | Load imbalanced across instances, falling back to process_tokens strategy | Normal operation log, automatic load balancing switch |
70+
| `cache-aware prefill: final strategy: cache_aware_scoring, selected={url}, loads={loads}, hitRatios={ratios}. ts_ms={ts}` | cache_aware scoring strategy selected a worker | Normal operation log, showing loads and hit ratios |
71+
| `[{method}] {path} {proto} {status} {latency} {clientIP}` | HTTP request access log | Normal operation log, records basic info for each request |
72+
| `before SelectWorker prefill. ts_ms={ts}` | Starting Prefill worker selection in PD disaggregated mode | Normal operation log, for performance tracing |
73+
| `before SelectWorker decode, after prefill. ts_ms={ts}` | Starting Decode worker selection after Prefill selection | Normal operation log, for performance tracing |
74+
| `after SelectWorker decode, before return. ts_ms={ts}` | Decode worker selection completed | Normal operation log, for performance tracing |
75+
76+
### Debug-Level Logs
77+
78+
> Debug-level logs are only output when the log level is set to `debug`, typically used for development debugging.
79+
80+
| Log Message | Meaning | Description |
81+
| :--- | :--- | :--- |
82+
| `Healthy instances: prefill={urls}, decode={urls}, mixed={urls}` | Lists healthy instances for each role | Useful for verifying instance discovery |
83+
| `cache-aware prefill: hashes={n} workers={n} load={loads} hit={hits}` | Hash count, worker count, and load info for cache_aware strategy | Useful for debugging cache hits |
84+
| `cache-aware prefill: tokenizer tokens={tokens}` | Tokenizer tokenization result | Useful for debugging tokenization results |
85+
| `cache-aware score: worker={url} hit={hit} loadRatio={ratio} score={score}` | Scoring details for cache_aware strategy | Useful for debugging scheduling decisions |
86+
| `radix match: hashes={n} matched_len={n} node_children={n}` | Radix tree match details | Useful for debugging cache matching |
87+
| `radix record: worker={url} hashes={n} node_depth={n}` | Radix tree record details | Useful for debugging cache recording |
88+
| `radix eviction: removed={n} nodeCount={n}` | Radix tree eviction details | Useful for debugging cache eviction |
4589

4690
## Common Response Output Analysis
4791

@@ -189,9 +233,10 @@ If `Failed to start server` appears in startup logs, check:
189233

190234
### Tokenizer Service (cache_aware Strategy)
191235

192-
When using the `cache_aware` scheduling strategy, the Router calls a Tokenizer service to tokenize requests for cache hit ratio computation. When the Tokenizer service is unavailable, the Router will log a Warn-level message: `tokenizer failed, fallback to process_tokens`.
236+
When using the `cache_aware` scheduling strategy, the Router calls a Tokenizer service to tokenize requests for cache hit ratio computation. When the Tokenizer service is unavailable, the Router has a two-level degradation mechanism:
193237

194-
**This does not affect normal request processing** — the Router has a built-in degradation mechanism that automatically falls back to the `process_tokens` strategy for continued scheduling. The only impact is the temporary loss of cache-aware optimization.
238+
1. **Fallback to character-based tokenization** (common case): The log will show `tokenizer failed, fallback to char tokens`. The cache_aware strategy remains active, using character-based tokenization for cache matching instead of the Tokenizer. Cache hit accuracy may decrease, but normal request processing is not affected.
239+
2. **Fallback to process_tokens strategy** (extreme case): When tokenization completely fails (e.g., empty request content), the log will show `tokenize failed, fallback to process_tokens`. The cache_aware strategy temporarily becomes inactive, and scheduling falls back to token processing volume. Normal request processing is not affected.
195240

196241
To restore full cache_aware functionality:
197242

docs/zh/online_serving/router.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ server:
190190
splitwise: true # true代表开启pd分离模式,false代表开启非pd分离模式
191191

192192
scheduler:
193-
policy: "power_of_two" # 调度策略(可选): random, power_of_two, round_robin, process_tokens, request_num, cache_aware, fd_metrics_score; 默认: request_num
193+
policy: "power_of_two" # 调度策略(可选): random, power_of_two, round_robin, process_tokens, request_num, cache_aware, remote_cache_aware, fd_metrics_score, fd_remote_metrics_score; 默认: request_num
194194
prefill-policy: "cache_aware" # pd分离模式下prefill节点调度策略; 默认: process_tokens
195195
decode-policy: "fd_metrics_score" # pd分离模式下decode节点调度策略; 默认: request_num
196196
eviction-interval-secs: 60 # cache-aware策略清理过期cache的间隔时间
@@ -199,9 +199,12 @@ scheduler:
199199
hit-ratio-weight: 1.0 # cache-aware策略命中率权重
200200
load-balance-weight: 0.05 # cache-aware策略负载均衡权重
201201
cache-block-size: 4 # cache-aware策略cache block大小
202-
tokenizer-url: "http://0.0.0.0:8098" # tokenizer服务地址(可选)
203-
tokenizer-timeout-secs: 2 # tokenizer服务超时时间
202+
# tokenizer-url: "http://0.0.0.0:8098" # tokenizer服务地址(可选), 不配置时cache_aware策略自动使用字符级分词。
203+
# 注意:配置此项会在每次调度时同步调用远程tokenizer服务,引入额外网络时延,
204+
# 仅在需要精确token级分词以提升cache命中率时再考虑启用。
205+
# tokenizer-timeout-secs: 2 # tokenizer服务超时时间; 默认: 2
204206
waiting-weight: 10 # cache-aware策略等待权重
207+
stats-interval-secs: 5 # 日志统计信息打印间隔时间(秒), 包含负载和缓存命中率等统计数据; 默认: 5
205208

206209
manager:
207210
health-failure-threshold: 3 # 健康检查失败次数,超过次数后认为节点不健康
@@ -265,10 +268,12 @@ Router 支持以下调度策略,可通过配置文件中的 `policy`(mixed
265268
| `random` | 通用 | 从所有可用实例中随机选择一个,无状态感知,适合轻量场景。 |
266269
| `round_robin` | 通用 | 使用原子计数器对实例列表循环取模,按顺序均匀分发请求。 |
267270
| `power_of_two` | 通用 | 随机选取两个实例,比较其当前并发请求数,选择负载较低的一个。 |
268-
| `process_tokens` | **prefill(默认)** | 遍历所有实例,选择当前正在处理的 token 数最少的实例,适合 prefill 阶段的长请求负载均衡。 |
269-
| `request_num` | **mixed / decode(默认)** | 遍历所有实例,选择当前并发请求数最少的实例,适合 decode 及 mixed 场景的请求均衡。 |
270-
| `fd_metrics_score` | mixed / decode | 实时从各实例的 metrics 接口获取 running/waiting 请求数,按 `running + waiting × waitingWeight` 打分,选择得分最低的实例。 |
271-
| `cache_aware` | prefill | 基于 Radix Tree 维护各实例的 KV Cache 前缀命中情况,综合命中率与负载打分选择实例;负载严重不均衡时自动回退至 `process_tokens`。 |
271+
| `process_tokens` | **prefill(默认)** | 遍历所有实例,选择当前正在处理的 token 数最少的实例(内存计数),适合 prefill 阶段的长请求负载均衡。 |
272+
| `request_num` | **mixed / decode(默认)** | 遍历所有实例,选择当前并发请求数最少的实例(内存计数),适合 decode 及 mixed 场景的请求均衡。 |
273+
| `fd_metrics_score` | mixed / decode | 基于内存计数获取 running/waiting 请求数,按 `running + waiting × waitingWeight` 打分,选择得分最低的实例。 |
274+
| `fd_remote_metrics_score` | mixed / decode | 实时从各实例的远程 `/metrics` 接口获取 running/waiting 请求数,按 `running + waiting × waitingWeight` 打分,选择得分最低的实例。需要实例注册时提供 `metrics_port`。**注意:每次调度时会同步发起远程 HTTP 请求,在实例数量较多或网络条件较差时会显著增加调度时延,请结合实际情况评估后再启用。** |
275+
| `cache_aware` | prefill | 基于 Radix Tree 维护各实例的 KV Cache 前缀命中情况,综合命中率与负载打分(内存计数)选择实例;负载严重不均衡时自动回退至 `process_tokens`。 |
276+
| `remote_cache_aware` | prefill | 与 `cache_aware` 相同的缓存感知策略,但使用远程 `/metrics` 接口获取实例负载数据。需要实例注册时提供 `metrics_port`。**注意:每次调度时会同步发起远程 HTTP 请求,在实例数量较多或网络条件较差时会显著增加调度时延,请结合实际情况评估后再启用。** |
272277

273278
## 常见问题排查
274279

0 commit comments

Comments
 (0)