[中文Readme] [模块关系-中文] [程序有效性评估-中文] [算法对比与选择指导]
[Modules relationships] [Program effectiveness evaluation-EN] [Scheduler Algorithm Comparison Analysis and guide]
[LLM Performance improvement test]
An intelligent scheduler for LLM inference gateway, designed to work with F5 LTM for optimal load balancing based on real-time performance metrics from inference engines.
- Intelligent Scheduling Algorithm: S1,S2. Based on different LLM server metrics
- Multi-Engine Support: Supports vLLM and SGLang inference engines, including variants (e.g., vllm_ascend, vllm_musa, vllm-mlu)
- Heterogeneous Engine Pool:
engine_type: autoenables vLLM + SGLang mixed pools with per-member automatic engine detection - Real-time Monitoring: Automatically fetches F5 Pool members and inference engine performance metrics
- High Availability Design: Asynchronous architecture with concurrent processing support
- RESTful API: Provides standard HTTP interfaces
- Configuration Hot Reload: Supports runtime configuration updates
- Comprehensive Logging: Detailed debugging and runtime logs
- Weighted Random Selection: Score-based probabilistic selection algorithm
- Manual or automatic fallback mechanisms: can be applied in scenarios such as load balancing algorithm fallback for inference servers, service backup, maintenance control, version A/B rollout, and cross-region inference traffic scheduling.
- Performance Analysis: Provides selection process simulation and probability analysis interfaces
scheduler-project/
├── main.py # Main program entry point
├── config/
│ ├── __init__.py
│ ├── config_loader.py # Configuration file loader module
│ └── scheduler-config.yaml # Configuration file
├── core/
│ ├── __init__.py
│ ├── models.py # Data model definitions
│ ├── f5_client.py # F5 API client
│ ├── metrics_collector.py # Metrics collection module
│ ├── score_calculator.py # Score calculation module
│ └── scheduler.py # Scheduler core logic
├── api/
│ ├── __init__.py
│ └── server.py # API server
├── utils/
│ ├── __init__.py
│ ├── logger.py # Logging utilities
│ └── exceptions.py # Custom exceptions
├── tests/ # Test files
├── requirements.txt # Project dependencies
└── README.md # Project documentation
Check here for detailed architecture.
Set up F5 BIG-IP:
- http standard vs
- optional: session persistence (source ip or based on session/cookie, depends your real case)
- apply the irule in the docs/F5-irule (change related variables to yours)
- set default inference pool and/or fallback inference pool(depends your needs)
- set least conn LB for the pool
- create a guest account that can list these pools on the BIG-IP
Set up your inference engine correctly. Currently offcial support vLLM, SGlang. For xInference it is WIP for now.
- Python 3.10+
- F5 LTM device access permissions
- Inference engine services (vLLM or SGLang)
pip install -r requirements.txtConfiguration file:
config/scheduler-config.yamlEdit the configuration file to set F5 connection information and Pool configuration:
global:
interval: 5 # Configuration hot reload check interval (seconds)
api_port: 8080 # API service port
api_host: 0.0.0.0 # API service listening address
log_level: INFO # Log level
f5:
host: 192.168.1.100 # F5 device IP (required)
port: 443 # F5 management port
username: admin # F5 username
password_env: F5_PASSWORD # F5 password environment variable
scheduler:
pool_fetch_interval: 10 # Pool member fetch interval (seconds)
metrics_fetch_interval: 3000 # Metrics collection interval (milliseconds)
modes:
- name: s1_enhanced # Algorithm mode name
w_a: 0.1 # Waiting queue weight
w_b: 0.9 # Cache usage weight
pools:
- name: llm-pool-1 # Pool name (required)
partition: Common # Partition name
engine_type: vllm # Engine type (required)
fallback: # Fallback configuration (optional)
pool_fallback: false # Pool-level fallback switch
member_running_req_threshold: 20.0 # Running requests threshold
member_waiting_queue_threshold: 15.0 # Waiting queue threshold
metrics:
schema: http # Protocol type
#port: 5001 # when metrics port is different to the port of F5 pool members
path: /metrics # Metrics path
timeout: 4 # Request timeout
# Engine variants metrics keys configuration (optional)
# Use this to support vLLM/SGLang variants with different metrics key names
engines_metrics_keys:
vllm_ascend: # Huawei Ascend variant
waiting_queue: vllm:num_requests_waiting
cache_usage: vllm:kv_cache_usage_perc # Ascend uses kv_cache instead of gpu_cache
running_req: vllm:num_requests_running
vllm_musa: # Moore Threads variant
cache_usage: vllm:gpu_cache_usage_perc
vllm-mlu: # Cambricon variant
cache_usage: vllm:mlu_cache_usage_percKnown Issue 1:
When configuring the specified port under metrics, it means that the scheduler no longer uses the port in the F5 Pool members. Since the configuration file only allows the definition of one port at this time, if the IP in the F5 Pool members is also the same IP, This will cause the scheduler to obtain metrics for different pool members with the same IP and the same port, which will cause problems. Therefore, if the metrics port needs to be specified, the IP in the pool member of F5 must be different.
export F5_PASSWORD="your_f5_password"
export METRIC_PWD="your_metrics_password" # If needed
# Optional: Log file path configuration (for non-Docker deployment)
export LOG_FILE_PATH="/var/log/f5-scheduler/scheduler.log" # Custom log file pathOptional Environment Variable: LOG_FILE_PATH
-
If set: The scheduler will write logs to the specified file path
export LOG_FILE_PATH="/var/log/f5-scheduler/scheduler.log" # Logs will be written to: /var/log/f5-scheduler/scheduler.log
-
If not set: The scheduler will use the default log file path
# Default log file: scheduler.log (in the current working directory) # For example: if you run the scheduler from /opt/f5-scheduler/, # the log file will be created at /opt/f5-scheduler/scheduler.log
Note: This environment variable is primarily used for non-Docker deployments. For Docker deployments, use the LOG_TO_STDOUT and LOG_FILE_PATH environment variables as described in the Docker Deployment section.
python main.py# Build production image
docker build -f Dockerfile.production -t f5-scheduler:latest .
# Run with production configuration (stdout logging - recommended)
docker run -d \
--name f5-scheduler \
-p 8080:8080 \
-v $(pwd)/config/scheduler-config.yaml:/app/config/scheduler-config.yaml:ro \
-e F5_PASSWORD=your-password \
-e METRIC_PWD=your-metric-password \ #optional
-e LOG_TO_STDOUT=true \
--log-driver json-file \
--log-opt max-size=100m \
--log-opt max-file=3 \
--restart unless-stopped \
f5-scheduler:latest# Run with file logging (if required by your environment)
docker run -d \
--name f5-scheduler-container \
-p 8080:8080 \
-v $(pwd)/config/scheduler-config.yaml:/app/config/scheduler-config.yaml:ro \
-v $(pwd)/logs:/app/logs \
-e F5_PASSWORD="your_f5_password" \
-e METRIC_PWD="your_metrics_password" \
-e LOG_TO_STDOUT="false" \
-e LOG_FILE_PATH="/app/logs/scheduler.log" \
--restart unless-stopped \
f5-scheduler:latest# Required
-e F5_PASSWORD="your_f5_password" # F5 device password
# Optional
-e METRIC_PWD="your_metrics_password" # Metrics service password (optional)
-e LOG_TO_STDOUT="true" # Log output method (optional, production only, default: true recommended)
-e LOG_FILE_PATH="/app/logs/scheduler.log" # Log file path (optional, only used when LOG_TO_STDOUT=false)Recommended: Use LOG_TO_STDOUT="true" (default) for container deployments because:
- Follows 12-Factor App principles and container best practices
- Better integration with Docker/Kubernetes logging systems
- Easier log collection with centralized logging solutions (ELK, Fluentd, etc.)
- Use
docker logs -f f5-scheduler-containerto view logs - Better performance (no file I/O overhead)
File logging should only be used when required by specific enterprise environments or legacy log collection systems.
POST /scheduler/select
Function: Select the optimal member based on real-time performance metrics of Pool members
Request Body:
{
"pool_name": "llm-pool-1",
"partition": "Common",
"members": ["10.10.10.10:8001", "10.10.10.10:8002"]
}Response:
Successfully selected optimal member:
10.10.10.10:8001
Pool has fallback mode enabled:
fallback
Unable to select optimal member (Pool doesn't exist, empty member list, all members have Score of 0, etc.):
none
Status Codes:
200: Success (includes successful selection, fallback, and unable to select scenarios)400: Bad request parameters500: Internal server error
Response Types:
- Normal Selection: Returns specific member address (e.g.,
10.10.10.10:8001) - Fallback Mode: Returns string
fallbackwhen Pool is configured withpool_fallback: true - Unable to Select: Returns string
none
Common scenarios when unable to select:
- Pool does not exist in the scheduler
- No intersection between requested member list and actual Pool members
- No members in the Pool
- All candidate members are filtered out by thresholds
GET /pools/{pool_name}/{partition}/status
Function: Get detailed status information for a specific Pool
Parameters:
pool_name: Pool namepartition: Partition name
Response:
{
"name": "llm-pool-1",
"partition": "Common",
"engine_type": "vllm",
"member_count": 2,
"members": [
{
"ip": "10.10.10.10",
"port": 8001,
"score": 0.75,
"metrics": {
"waiting_queue": 2.0,
"cache_usage": 0.3
},
"detected_variant": "vllm_ascend",
"detected_engine_type": "vllm",
"detection_status": "ok"
},
{
"ip": "10.10.10.10",
"port": 8002,
"score": 0.82,
"metrics": {
"waiting_queue": 1.5,
"cache_usage": 0.25
},
"detected_variant": "vllm",
"detected_engine_type": "vllm",
"detection_status": "ok"
}
]
}GET /pools/{pool_name}/{partition}/status?simple
Function: Get simpele score information for a specific Pool
Parameters:
pool_name: Pool namepartition: Partition naemsimple: query parameter
Response:
127.0.0.1:8001 0.5404
127.0.0.1:8002 0.0000
127.0.0.1:8003 0.2846
GET /pools/status
Function: Get status information for all Pools
Response:
{
"pools": [
{
"name": "llm-pool-1",
"partition": "Common",
"engine_type": "vllm",
"member_count": 2,
"members": [...]
},
{
"name": "llm-pool-2",
"partition": "Common",
"engine_type": "sglang",
"member_count": 3,
"members": [...]
}
]
}GET /health
Function: Check scheduler service health status
Response:
{
"status": "healthy",
"message": "Scheduler is running normally"
}POST /pools/{pool_name}/{partition}/simulate
Function: Simulate multiple selection processes for testing and analysis (test interface)
Parameters:
pool_name: Pool namepartition: Partition nameiterations: Number of simulations (query parameter, default 100)
Request Body:
{
"pool_name": "llm-pool-1",
"partition": "Common",
"members": ["10.10.10.10:8001", "10.10.10.10:8002"]
}Response:
{
"results": {
"10.10.10.10:8001": 45,
"10.10.10.10:8002": 55
},
"iterations": 100
}POST /pools/{pool_name}/{partition}/analyze
Function: Detailed analysis of selection accuracy and probability bias (test interface)
Parameters:
pool_name: Pool namepartition: Partition nameiterations: Number of analyses (query parameter, default 1000)
Request Body:
{
"pool_name": "llm-pool-1",
"partition": "Common",
"members": ["10.10.10.10:8001", "10.10.10.10:8002"]
}Response:
{
"member_analysis": {
"10.10.10.10:8001": {
"theoretical_probability": 0.4286,
"actual_probability": 0.4310,
"selection_count": 431,
"deviation": 0.0024,
"deviation_percentage": 0.56
},
"10.10.10.10:8002": {
"theoretical_probability": 0.5714,
"actual_probability": 0.5690,
"selection_count": 569,
"deviation": -0.0024,
"deviation_percentage": -0.42
}
},
"overall_stats": {
"total_iterations": 1000,
"avg_deviation": 0.0024,
"max_deviation": 0.0024,
"quality_score": 99.44
}
}| Config Item | Type | Required | Default | Description |
|---|---|---|---|---|
interval |
Integer | No | 60 | Configuration file hot reload check interval (seconds) |
api_port |
Integer | No | 8080 | API service listening port |
api_host |
String | No | "0.0.0.0" | API service listening address (0.0.0.0 means all interfaces) |
log_level |
String | No | "INFO" | Log level (DEBUG/INFO/WARNING/ERROR/CRITICAL) |
log_debug |
Boolean | No | false | Backward compatible debug switch (used when log_level is not configured) |
| Config Item | Type | Required | Default | Description |
|---|---|---|---|---|
host |
String | Yes | None | F5 device IP address or hostname |
port |
Integer | No | 443 | F5 iControl REST API port |
username |
String | No | "admin" | F5 device login username. The guest role or high. |
password_env |
String | No | None | Environment variable name for F5 password |
| Config Item | Type | Required | Default | Description |
|---|---|---|---|---|
pool_fetch_interval |
Integer | No | 10 | Interval to fetch Pool members from F5 (seconds) |
metrics_fetch_interval |
Integer | No | 1000 | Interval to collect Metrics from inference engines (milliseconds) |
| Config Item | Type | Required | Default | Description |
|---|---|---|---|---|
name |
String | No | "s1" | Algorithm mode name (supports s1 and s2) |
w_a |
Float | No | 0.5 | Waiting queue weight (between 0-1) |
w_b |
Float | No | 0.5 | Cache usage weight (between 0-1) |
w_g |
Float | No | 0.0 | Running requests weight (used in S2 algorithm) |
| Config Item | Type | Required | Default | Description |
|---|---|---|---|---|
name |
String | Yes | None | Pool name, must match Pool name on F5 |
partition |
String | No | "Common" | Partition name on F5 |
engine_type |
String | Yes | None | Inference engine type: vllm, sglang, or auto (heterogeneous pool) |
| Config Item | Type | Required | Default | Description |
|---|---|---|---|---|
pool_fallback |
Boolean | No | false | Pool-level fallback switch, returns "fallback" when enabled |
member_running_req_threshold |
Float | No | null | Running requests threshold, members are excluded when exceeded |
member_waiting_queue_threshold |
Float | No | null | Waiting queue length threshold, members are excluded when exceeded |
Fallback Feature Description:
- Pool-level fallback: When
pool_fallback: true,/scheduler/selectAPI directly returns string"fallback"without any member selection or score calculation - Member threshold filtering: Compares against raw metrics values, members exceeding thresholds are excluded from selection
- Priority: Pool-level fallback has the highest priority; when enabled, member threshold filtering is ignored
- Threshold comparison: Uses raw collected metric values (not normalized scores) for direct numerical comparison with configured thresholds
| Config Item | Type | Required | Default | Description |
|---|---|---|---|---|
schema |
String | No | "http" | Protocol type (http/https) |
port |
Integer | No | null | Metrics service port, null means use Pool member's own port |
path |
String | No | "/metrics" | URL path for Metrics service |
timeout |
Integer | No | 3 | HTTP request timeout (seconds) |
APIkey |
String | No | null | API key for Metrics service |
metric_user |
String | No | null | Username for Metrics service |
metric_pwd_env |
String | No | null | Environment variable name for Metrics service password |
| Config Item | Type | Required | Default | Description |
|---|---|---|---|---|
{variant_name} |
Object | No | null | Variant configuration block (e.g., vllm_ascend, vllm_musa, sglang_xxx) |
{variant_name}.waiting_queue |
String | No | null | Custom waiting queue metric key |
{variant_name}.cache_usage |
String | No | null | Custom cache usage metric key |
{variant_name}.running_req |
String | No | null | Custom running requests metric key |
Notes:
- Variant names must start with
vllmorsglang - All metric keys within a variant are optional; unconfigured keys use built-in defaults
- For homogeneous pools, set
engine_typetovllmorsglangand configure variant keys inengines_metrics_keys; for heterogeneous pools, useauto(see Heterogeneous Engine Pool section) - The scheduler automatically detects which variant each member uses based on available metrics
# Complete configuration example
global:
interval: 5
api_port: 8080
api_host: 0.0.0.0
log_level: INFO
f5:
host: 192.168.1.100 # Required: F5 device address
port: 443
username: admin
password_env: F5_PASSWORD
scheduler:
pool_fetch_interval: 10
metrics_fetch_interval: 3000
modes:
#Currently support s1 and s2. s1 use 2 metrics, s2 use 3 metrics
#You need test of them to see which one is better in your environment
#- name: s1
#w_a: 0.8 # In practice, w_a has greater impact on TTFT
#w_b: 0.2
- name: s2
w_a: 0.4 # Weight for waiting queue metric
w_b: 0.3 # Weight for cache usage metric
w_g: 0.3 # Weight for running requests metric
pools:
- name: llm-pool-1 # Required: Pool name
partition: Common
engine_type: vllm # Required: Engine type
fallback: # Optional: Fallback configuration
pool_fallback: false # Pool-level fallback switch
member_running_req_threshold: 25.0 # Exclude overloaded members
member_waiting_queue_threshold: 20.0 # Exclude high-queue members
metrics:
schema: http
path: /metrics
timeout: 4
APIkey: your-api-key
metric_user: metrics_user
metric_pwd_env: METRIC_PWD
- name: llm-pool-2
partition: tenant-1
engine_type: sglang
fallback: # Optional: Fallback configuration
pool_fallback: false # Normal scheduling mode
member_running_req_threshold: 30.0 # Higher threshold for SGLang
# member_waiting_queue_threshold not set - no queue limit
metrics:
schema: https
port: 9090 # Use unified metrics port
path: /custom/metrics
timeout: 5
# Engine variants metrics keys configuration (optional)
# Use this to support vLLM/SGLang variants with different metrics key names
engines_metrics_keys:
vllm_ascend: # Huawei Ascend variant
waiting_queue: vllm:num_requests_waiting
cache_usage: vllm:kv_cache_usage_perc # Ascend uses kv_cache instead of gpu_cache
running_req: vllm:num_requests_running
vllm_musa: # Moore Threads variant
cache_usage: vllm:gpu_cache_usage_perc
vllm-mlu: # Cambricon variant
cache_usage: vllm:mlu_cache_usage_percPlease refer to [LLM-Inference-Gateway-Scheduler-Algorithm-Comparison-Analysis]
Weighted random selection based on each member's Score value:
- Calculate the sum of all members' Scores
- Generate a random number between 0 and the total sum
- Select the corresponding member based on which interval the random number falls into
- Members with higher Scores occupy larger intervals and have higher selection probability
vLLM Engine (standard):
vllm:num_requests_waiting: Number of requests waiting in queuevllm:gpu_cache_usage_perc: GPU cache usage percentagevllm:num_requests_running: Number of requests currently running (for S2 algorithm)
SGLang Engine (standard):
sglang:num_queue_reqs: Number of requests in queuesglang:token_usage: Token cache usage ratesglang:num_running_reqs: Number of requests currently running (for S2 algorithm)
For vLLM and SGLang variants (e.g., vllm_ascend for Huawei Ascend, vllm_musa for Moore Threads, vllm-mlu for Cambricon), the scheduler supports automatic metrics key detection and configuration.
Configuration: Use the engines_metrics_keys section to define custom metrics keys for each variant:
engines_metrics_keys:
vllm_ascend: # Huawei Ascend variant
waiting_queue: vllm:num_requests_waiting
cache_usage: vllm:kv_cache_usage_perc # Different from standard vllm
running_req: vllm:num_requests_running
vllm_musa: # Moore Threads variant
cache_usage: vllm:gpu_cache_usage_perc
vllm-mlu: # Cambricon variant
cache_usage: vllm:mlu_cache_usage_perc
sglang_xxx: # Custom SGLang variant
waiting_queue: sglang:num_queue_reqs
cache_usage: sglang:token_usageKey Points:
- Variant naming: Must start with
vllmorsglang(underscore or hyphen allowed, e.g.,vllm_ascend,vllm-mlu) - Pool engine_type: Use
vllmorsglangfor homogeneous pools; useautofor heterogeneous pools (see below). Do not use variant names asengine_type - Optional keys: Only configure keys that differ from the built-in standard; unconfigured keys fall back to built-in defaults
- Priority: User-configured variant keys are tried first, then fall back to built-in keys
- Auto-detection: The scheduler automatically detects which variant a member is using based on available metrics
- Hot reload: Changes to
engines_metrics_keysare hot-reloaded and take effect on the next metrics collection cycle
API Response: The /pools/{pool_name}/{partition}/status endpoint includes detected_variant, detected_engine_type (for auto pools), and detection_status (ok / partial / failed / degraded) for each member.
When a single F5 Pool contains members running different Prometheus-based inference engines (e.g., vLLM and SGLang mixed together, including their variants), set engine_type: auto. The scheduler automatically detects each member's engine family (vLLM or SGLang) and variant from a single /metrics scrape—no per-member manual labeling is required.
Typical use cases:
- One F5 Pool with both vLLM and SGLang backends serving the same model endpoint
- Mixed standard and variant members (e.g., standard vLLM + Huawei Ascend vLLM + standard SGLang) in one pool
Configuration example:
pools:
- name: pool_mixed_llm
partition: Common
engine_type: auto # Heterogeneous pool: auto-detect vLLM / SGLang per member
fallback:
pool_fallback: false
metrics:
schema: http
path: /metrics
timeout: 4
# Optional: only needed when members use non-standard metric key names
engines_metrics_keys:
vllm_v0_8: # Prefix vllm → vLLM candidate pool
waiting_queue: vllm:pending_requests
cache_usage: vllm:kv_cache_usage_perc
running_req: vllm:active_requests
sglang_v2: # Prefix sglang → SGLang candidate pool
waiting_queue: sglang:pending_req
cache_usage: sglang:token_usage_v2
running_req: sglang:running_req_v2
vllm_mindie: # Variant without vllm: prefix (e.g., MindIE)
waiting_queue: num_requests_waiting
cache_usage: npu_cache_usage_perc
running_req: num_requests_runningHow auto-detection works:
- Stage 1 — Engine family: Scan Prometheus metrics for vLLM / SGLang signature keys (built-in + user-configured
engines_metrics_keys). Each member is classified independently. - Stage 2 — Variant keys: Within the detected family, match metric keys by priority (user variants first, then built-in defaults) and cache results for steady-state performance.
engine_type comparison:
| Value | Pool type | Behavior |
|---|---|---|
vllm |
Homogeneous | Only vLLM metric keys are scanned; best cold-start performance |
sglang |
Homogeneous | Only SGLang metric keys are scanned |
auto |
Heterogeneous | Per-member vLLM / SGLang detection; standard members need no extra config |
engines_metrics_keys rules in auto mode:
- Use one top-level entry per variant; the variant name prefix (
vllm_*/sglang_*) determines which engine family the keys belong to - Do not combine vLLM and SGLang keys under a single variant entry
- Standard vLLM / SGLang members work without any variant configuration
detection_status values (visible in /pools/.../status):
| Status | Meaning |
|---|---|
ok |
Engine family detected; required metrics (waiting_queue, cache_usage) collected |
partial |
Engine family detected but a required metric is missing |
failed |
Engine family not detected, or no usable metrics |
degraded |
Previously cached keys temporarily unavailable; re-probing in progress |
API response example (engine_type: auto):
{
"name": "pool_mixed_llm",
"partition": "Common",
"engine_type": "auto",
"member_count": 2,
"members": [
{
"ip": "10.0.0.1",
"port": 8001,
"score": 0.72,
"metrics": { "waiting_queue": 12.0, "cache_usage": 0.35, "running_req": 5.0 },
"detected_variant": "vllm",
"detected_engine_type": "vllm",
"detection_status": "ok"
},
{
"ip": "10.0.0.2",
"port": 8010,
"score": 0.85,
"metrics": { "waiting_queue": 3.0, "cache_usage": 0.55, "running_req": 2.0 },
"detected_variant": "sglang",
"detected_engine_type": "sglang",
"detection_status": "ok"
}
]
}Note:
automode supports vLLM and SGLang (Prometheus/metrics) only. XInference uses a different metrics protocol and should be configured in a separate pool withengine_type: xinference.
The scheduler generates detailed log files scheduler.log, including:
- Configuration loading and hot reload records
- Pool member fetch and update records
- Metrics collection status and results
- Score calculation process and results
- API request and response records
- Scheduling selection decision process
- Error and exception information
Through API interfaces you can view:
- Number and status of members in each Pool
- Real-time Metrics data of members
- Score distribution and trend changes
- Selection result statistics and probability analysis
- System runtime health status
- DEBUG: Shows all detailed information, including detailed process of each selection
- INFO: Shows key operations and status changes
- WARNING: Shows warning information such as missing configuration, connection issues, etc.
- ERROR: Shows error information such as configuration errors, network failures, etc.
- CRITICAL: Shows critical errors that may prevent the program from running
-
F5 Connection Failure
- Check F5 device network connectivity:
ping <f5_host> - Verify username and password are correct
- Confirm F5 device has iControl REST functionality enabled
- Check if the user is locked as multi time failure logins
- Change log level to debug to see detail
- Check F5 device network connectivity:
-
Metrics Collection Failure
- Check if inference engine services are running normally
- Verify Metrics interface configuration is correct
- Confirm network firewall settings allow access
- Check inference engine's Metrics port and path
- Change log level to debug to see detail
-
Score Calculation Anomaly
- Check if algorithm mode configuration is correct
- Verify weight parameter settings (w_a + w_b recommended to equal 1)
- Review Metrics data completeness
- Confirm inference engine type configuration is correct
- Change log level to debug to see detail
-
Pool Member Fetch Failure
- Verify Pool name and Partition match F5 configuration
- Check Pool status on F5 device
- Confirm F5 client connection and authentication are normal
- Change log level to debug to see detail
Enable detailed debug logging:
global:
log_level: DEBUGOr use backward compatible method:
global:
log_debug: trueUse health check interface to monitor service status:
curl http://localhost:8080/healthNormal response:
{"status": "healthy", "message": "Scheduler is running normally"}For vLLM/SGLang Variants (Recommended):
Simply add the variant configuration to engines_metrics_keys in the config file:
engines_metrics_keys:
vllm_custom: # Your custom vLLM variant
waiting_queue: vllm:custom_waiting_metric
cache_usage: vllm:custom_cache_metric
running_req: vllm:custom_running_metricNo code changes required. The scheduler will automatically detect and use the correct keys.
For Completely New Engine Types:
- Add new engine type in
core/models.py:
class EngineType(Enum):
VLLM = "vllm"
SGLANG = "sglang"
NEW_ENGINE = "new_engine" # Add new engine- Define key metrics in
BASE_ENGINE_METRICS:
BASE_ENGINE_METRICS = {
EngineType.NEW_ENGINE: {
"waiting_queue": "new_engine:queue_length",
"cache_usage": "new_engine:cache_usage",
"running_req": "new_engine:running_requests"
}
}- Update parsing logic in
metrics_collector.py(if metric format is different)
The project now supports two algorithms: S1 and S2. To implement additional algorithms:
- Add new mode in configuration:
modes:
- name: s3
w_a: 0.3
w_b: 0.3
w_g: 0.2
w_h: 0.2 # Add new weight parameters as needed- Add metrics support in
core/models.pyif new metrics are needed:
ENGINE_METRICS = {
EngineType.VLLM: {
"waiting_queue": "vllm:num_requests_waiting",
"cache_usage": "vllm:gpu_cache_usage_perc",
"running_req": "vllm:num_requests_running",
"new_metric": "vllm:new_metric_name" # Add new metric
}
}- Implement algorithm logic in
core/score_calculator.py:
def _calculate_s3_scores(self, pool: Pool, mode_config: ModeConfig) -> None:
# Implement S3 algorithm
pass- Update the main calculation method to support the new algorithm:
elif mode_config.name == "s3":
self._calculate_s3_scores(pool, mode_config)This project is for internal use, please comply with relevant usage terms.
