数据并行路由器#
考虑到多张 GPU 运行多个 SGLang 运行时,SGLang 路由器使用其独特的缓存感知负载均衡算法将请求分发到不同的运行时。
路由器是一个独立的 Python 包,可以作为 OpenAI API 的直接替代品使用。
安装#
pip install sglang-router
路由器的详细用法可以在 launch_router 和 launch_server 中找到。此外,您也可以直接运行以下命令查看路由器的用法。
python -m sglang_router.launch_server --help
python -m sglang_router.launch_router --help
路由器支持两种工作模式
协同启动路由器和运行时
分别启动运行时和路由器
协同启动路由器和运行时#
这将是 SGLang 运行时现有 --dp-size
参数的直接替代品。其内部使用多进程启动多个工作进程,等待它们准备就绪后,再将路由器连接到所有工作进程。
python -m sglang_router.launch_server --model-path meta-llama/Meta-Llama-3.1-8B-Instruct --dp-size 4 --host 0.0.0.0
服务器准备就绪后,您可以直接向路由器发送请求,方式与向每个单独的工作进程发送请求相同。
请相应地调整批量大小(batchsize)以实现最大吞吐量。
import requests
url = "http://localhost:30000/generate"
data = {"text": "What is the capital of France?"}
response = requests.post(url, json=data)
print(response.json())
分别启动运行时和路由器#
这对于多节点 DP 非常有用。首先,在多个节点上启动工作进程,然后在主节点上启动路由器,并将路由器连接到所有工作进程。
python -m sglang_router.launch_router --worker-urls http://worker_url_1 http://worker_url_2
动态扩展 API#
我们提供 /add_worker
和 /remove_worker
API,用于从路由器动态添加或移除工作进程。
/add_worker
用法
curl -X POST http://localhost:30000/add_worker?url=http://worker_url_1
示例
python -m sglang.launch_server --model-path meta-llama/Meta-Llama-3.1-8B-Instruct --port 30001
curl -X POST http://localhost:30000/add_worker?url=http://127.0.0.1:30001
# Successfully added worker: http://127.0.0.1:30001
/remove_worker
用法
curl -X POST http://localhost:30000/remove_worker?url=http://worker_url_1
示例
curl -X POST http://localhost:30000/remove_worker?url=http://127.0.0.1:30001
# Successfully removed worker: http://127.0.0.1:30001
注意
对于缓存感知路由器,工作进程将从树结构和队列中移除。
容错#
我们提供基于重试的容错机制。
如果向某个工作进程发送请求失败达到
max_worker_retries
次,路由器将从路由器中移除该工作进程,并转向下一个工作进程。如果总重试次数超过
max_total_retries
,路由器将返回错误。
注意
max_worker_retries
默认为 3,max_total_retries
默认为 6。
路由策略#
缓存感知负载均衡路由器#
原生路由器结合了两种策略来优化缓存利用率和请求分发
缓存感知路由(近似树)
负载均衡路由(基于平衡阈值的最短队列)
路由器根据负载情况动态切换这些策略
当系统不均衡时使用负载均衡
当系统均衡时使用缓存感知路由
如果同时满足以下两个条件,则认为系统不均衡
(max_load - min_load) > balance_abs_threshold
max_load > balance_rel_threshold * min_load
缓存感知路由(近似树)
当工作进程被认为是均衡的,路由器会根据请求历史为每个工作进程维护一个近似基数树,无需直接查询每个工作进程的缓存状态。该树存储原始文本字符而不是 token ID,以避免分词开销。
流程
对于每个请求,找到具有最高前缀匹配的工作进程。
如果匹配率 > cache_threshold,将请求路由到匹配度最高的工作进程(可能缓存了相关数据)
如果匹配率 ≤ cache_threshold,将请求路由到树结构最小的工作进程(有最多的可用缓存容量)
后台维护:定期在近似树上驱逐最近最少使用的叶子节点,以防止内存溢出。
负载均衡(最短队列)
对于不均衡的系统,此策略跟踪每个工作进程的待处理请求计数,并将新请求路由到最不忙的工作进程。这有助于在工作进程之间保持最佳的负载分布。
配置参数#
cache_threshold
: (float, 0.0 to 1.0, default: 0.5)使用最高匹配路由所需的最小前缀匹配率。
低于此阈值时,请求将被路由到具有最多可用缓存空间的工作进程。
balance_abs_threshold
: (integer, default: 32)用于负载不均衡检测的绝对差阈值。
如果 (max_load - min_load) > abs_threshold,系统可能不均衡。
balance_rel_threshold
: (float, default: 1.0001)用于负载不均衡检测的相对比率阈值。
如果 max_load > min_load * rel_threshold,系统可能不均衡。
与
balance_abs_threshold
结合使用,以确定最终的不均衡状态。
eviction_interval
: (integer, default: 60)近似树的 LRU 驱逐周期(以秒为单位)间隔。
后台线程定期驱逐最近最少使用的节点,以维持树的大小。
max_tree_size
: (integer, default: 16777216)近似树上的最大节点数。
超过此限制时,LRU 叶子节点将在下一个驱逐周期被驱逐。