🎉 init starlette dial

This commit is contained in:
loveuer
2025-06-28 19:03:29 +08:00
commit 739a518e51
19 changed files with 1375 additions and 0 deletions

157
pkg/dial/LOAD_BALANCING.md Normal file
View File

@@ -0,0 +1,157 @@
# 负载均衡功能
`ModifiableRequest` 类现在支持 round-robin 负载均衡功能,可以自动在多个后端服务器之间分发请求。
## 功能特性
- 🔄 **Round-Robin 轮询**: 按顺序在多个主机之间分发请求
- 🛡️ **线程安全**: 使用锁机制确保并发安全
- 🔧 **灵活配置**: 支持带协议和不带协议的主机配置
- 🎯 **智能路由**: 自动判断是否需要负载均衡
## 使用方法
### 1. 基本负载均衡
```python
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. 带协议的主机配置
```python
# 支持混合协议配置
hosts = [
"http://server1.com",
"https://server2.com",
"server3.com" # 自动添加 http:// 前缀
]
proxy_handler = client.proxy(hosts, request_handler)
```
### 3. 绕过负载均衡
```python
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 应用中的使用
```python
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
)
)
])
```
### 健康检查集成
```python
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. **路径问题**: 确保路径格式正确(以 `/` 开头)
### 调试技巧
```python
def debug_handler(request: ModifiableRequest):
# 添加调试信息
request.add_header("X-Debug", "true")
request.rewrite_uri("/api/debug")
return request.build()
```