Files
starlette-dial/pkg/dial/LOAD_BALANCING.md
2025-06-28 19:03:29 +08:00

4.0 KiB
Raw Blame History

负载均衡功能

ModifiableRequest 类现在支持 round-robin 负载均衡功能,可以自动在多个后端服务器之间分发请求。

功能特性

  • 🔄 Round-Robin 轮询: 按顺序在多个主机之间分发请求
  • 🛡️ 线程安全: 使用锁机制确保并发安全
  • 🔧 灵活配置: 支持带协议和不带协议的主机配置
  • 🎯 智能路由: 自动判断是否需要负载均衡

使用方法

1. 基本负载均衡

from pkg.dial import client
from pkg.dial.req import ModifiableRequest

def request_handler(request: ModifiableRequest):
    # 只指定路径,让负载均衡器自动选择主机
    request.rewrite_uri("/api/users")
    return request.build()

# 创建代理,支持多个后端服务器
proxy_handler = client.proxy(
    hosts=["server1.com", "server2.com", "server3.com"],
    req_fn=request_handler
)

2. 带协议的主机配置

# 支持混合协议配置
hosts = [
    "http://server1.com",
    "https://server2.com", 
    "server3.com"  # 自动添加 http:// 前缀
]

proxy_handler = client.proxy(hosts, request_handler)

3. 绕过负载均衡

def request_handler_fixed(request: ModifiableRequest):
    # 指定完整 URL绕过负载均衡
    request.rewrite_uri("https://specific-server.com/api/users")
    return request.build()

# 即使配置了多个主机,也会使用指定的 URL
proxy_handler = client.proxy(
    hosts=["server1.com", "server2.com"],
    req_fn=request_handler_fixed
)

工作原理

URL 解析逻辑

  1. 检查 URL 是否包含主机:

    • 如果 URL 包含主机(如 https://example.com/api/users),直接使用该 URL
    • 如果 URL 只有路径(如 /api/users),从主机列表中选择一个
  2. Round-Robin 选择:

    • 使用线程安全的计数器
    • 按顺序循环选择主机
    • 自动处理主机数量变化
  3. URL 构建:

    • 自动添加协议前缀(如果缺失)
    • 确保路径格式正确
    • 合并查询参数

示例请求分发

假设配置了 3 个主机:["server1.com", "server2.com", "server3.com"]

请求 1: http://server1.com/api/users
请求 2: http://server2.com/api/users  
请求 3: http://server3.com/api/users
请求 4: http://server1.com/api/users  # 重新开始轮询
请求 5: http://server2.com/api/users
...

配置示例

Starlette 应用中的使用

from starlette.applications import Starlette
from starlette.routing import Route
from pkg.dial import client

def api_handler(request: ModifiableRequest):
    request.rewrite_uri("/api/v1/data")
    return request.build()

app = Starlette(routes=[
    Route(
        "/api/data",
        client.proxy(
            hosts=[
                "http://backend1:8080",
                "http://backend2:8080", 
                "http://backend3:8080"
            ],
            req_fn=api_handler
        )
    )
])

健康检查集成

def health_check_handler(request: ModifiableRequest):
    request.rewrite_uri("/health")
    return request.build()

# 健康检查路由
health_proxy = client.proxy(
    hosts=["server1.com", "server2.com"],
    req_fn=health_check_handler
)

注意事项

  1. 主机格式: 建议使用完整的主机名或 IP 地址
  2. 协议处理: 如果不指定协议,默认使用 http://
  3. 并发安全: 使用线程锁确保多线程环境下的安全性
  4. 错误处理: 如果主机列表为空,会抛出 ValueError 异常
  5. 性能考虑: 负载均衡器本身开销很小,适合高并发场景

故障排除

常见问题

  1. 主机无法访问: 确保所有配置的主机都是可访问的
  2. 协议错误: 检查主机配置中的协议是否正确
  3. 路径问题: 确保路径格式正确(以 / 开头)

调试技巧

def debug_handler(request: ModifiableRequest):
    # 添加调试信息
    request.add_header("X-Debug", "true")
    request.rewrite_uri("/api/debug")
    return request.build()