数据并行路由器#

给定多个GPU运行多个SGLang运行时,SGLang路由器通过其独特的缓存感知负载均衡算法将请求分发到不同的运行时。

路由器是一个独立的Python包,它可以作为OpenAI API的直接替代品使用。

安装#

$ pip install sglang-router

路由器的详细用法可以在launch_routerlaunch_server中找到。此外,您可以直接运行以下命令来查看路由器的用法。

$ python -m sglang_router.launch_server --help
$ python -m sglang_router.launch_router --help

路由器支持两种工作模式:

  1. 共同启动路由器和运行时

  2. 分别启动运行时和路由器

共同启动路由器和运行时#

这将直接替换现有的SGLang Runtime的--dp-size参数。在底层,它使用多进程来启动多个工作器,等待它们准备就绪,然后将路由器连接到所有工作器。

$ python -m sglang_router.launch_server --model-path meta-llama/Meta-Llama-3.1-8B-Instruct --dp-size 1

服务器准备就绪后,您可以像向每个单独的工作者发送请求一样,直接向路由器发送请求。

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

注意:

  • 对于缓存感知的路由器,工作线程将从树和队列中移除。

容错性#

我们提供基于故障容忍的重试机制。

  1. 如果对工作者的请求失败达到max_worker_retries次,路由器将从路由器中移除该工作者并继续到下一个工作者。

  2. 如果重试的总次数超过max_total_retries,路由器将返回一个错误。

注意:

  • max_worker_retries 默认为 3,max_total_retries 默认为 6。

路由策略#

缓存感知负载均衡路由器#

原生路由器结合了两种策略来优化缓存利用率和请求分配:

  1. 缓存感知路由(近似树)

  2. 负载均衡路由(带平衡阈值的最短队列)

路由器根据负载条件在这些策略之间动态切换:

  • 当系统不平衡时使用负载均衡

  • 当系统平衡时使用缓存感知路由

如果满足以下两个条件,系统被认为是不平衡的:

  1. (最大负载 - 最小负载) > 平衡绝对阈值

  2. 最大负载 > 平衡相对阈值 * 最小负载

缓存感知路由(近似树)

当工作者被认为处于平衡状态时,路由器会根据请求历史为每个工作者维护一个近似的基数树,从而消除了在每个工作者上直接查询缓存状态的需要。该树存储原始文本字符而不是令牌ID,以避免令牌化的开销。

过程:

  1. 对于每个请求,找到具有最高前缀匹配的工作者。

    • 如果匹配率大于缓存阈值,则将请求路由到匹配度最高的worker(可能缓存了相关数据)

    • 如果匹配率 ≤ cache_threshold,将请求路由到树大小最小(缓存容量最可用)的工作节点

  2. 后台维护:定期淘汰近似树中最近最少使用的叶节点,以防止内存溢出。

负载均衡(最短队列)

对于不平衡的系统,此策略跟踪每个工作者的待处理请求计数,并将新请求路由到最不繁忙的工作者。这有助于保持工作者之间的最佳负载分配。

配置参数#

  1. cache_threshold: (浮点数, 0.0 到 1.0, 默认值: 0.5)

    • 使用最高匹配路由的最小前缀匹配比率。

    • 低于此阈值时,请求将被路由到具有最多可用缓存空间的工作器。

  2. balance_abs_threshold: (整数, 默认值: 32)

    • 负载不平衡检测的绝对差异阈值。

    • 如果 (max_load - min_load) > abs_threshold,系统可能不平衡。

  3. balance_rel_threshold: (浮点数, 默认值: 1.0001)

    • 负载不平衡检测的相对比率阈值。

    • 如果max_load > min_load * rel_threshold,系统可能不平衡。

    • balance_abs_threshold 结合使用,以确定最终的不平衡状态。

  4. eviction_interval: (整数, 默认值: 60)

    • 近似树的LRU驱逐周期之间的间隔秒数。

    • 后台线程定期淘汰最近最少使用的节点以维护树的大小。

  5. max_tree_size: (整数, 默认值: 16777216)

    • 近似树上的最大节点数。

    • 当超过时,LRU叶子节点将在下一个淘汰周期中被淘汰。