HTTP Dispatcher系列(1):什么是HTTP Dispatcher?为什么酒店API集成必须要有它
什么是HTTP Dispatcher?为什么它对酒店API集成至关重要?了解它如何管理多个供应商、处理限流和解决连接池挑战。
“我们有50家酒店供应商,每家都有不同的限流策略。每次做促销活动,我们的集成服务就崩溃。” — 一位沮丧的CTO
“我们的HTTP客户端每秒创建数千个连接。供应商5分钟后就封锁我们。” — 一位首席工程师
如果这些故事听起来很熟悉,那你面临的就是HTTP Dispatcher问题。
问题:供应商太多,连接太多
天真的方法:每个供应商一个客户端
// ❌ 天真的实现
type HotelIntegrationService struct {
hotelbedsClient *http.Client
didaClient *http.Client
expediaClient *http.Client
agodaClient *http.Client
// ... 还有46个客户端
}
func (s *HotelIntegrationService) SearchHotels(ctx context.Context, suppliers []string) {
for _, supplier := range suppliers {
go func(supplier string) {
var client *http.Client
switch supplier {
case "hotelbeds":
client = s.hotelbedsClient
case "dida":
client = s.didaClient
// ... 更多case
}
resp, err := client.Get(fmt.Sprintf("/api/hotels?%s", query))
// 处理响应
}(supplier)
}
}
当你搜索50家供应商时会发生什么?
并发请求:50
打开的连接:50(每个供应商一个)
┌─────────────────────────────────────────────────┐
│ 供应商A: 10 请求/秒 (限制: 10) ✅ │
│ 供应商B: 10 请求/秒 (限制: 5) ❌ 429 │
│ 供应商C: 10 请求/秒 (限制: 20) ✅ │
│ 供应商D: 10 请求/秒 (限制: 2) ❌ 429 │
│ ... │
└─────────────────────────────────────────────────┘
结果:40%的请求因429 Too Many Requests失败
根本原因
- 没有限流意识:每个供应商有不同的限制(5 req/s、10 req/s、100 req/s、仅突发、等等)
- 没有连接池:每次请求都创建新连接
- 没有智能重试:收到429就立即放弃
- 没有优先级:所有请求一视同仁
登场:HTTP Dispatcher
什么是HTTP Dispatcher?
HTTP Dispatcher是一个中间件层,位于你的应用程序和供应商API之间。它管理所有HTTP通信,具有智能限流、连接池和请求优先级。
┌─────────────────────────────────────────────────────────┐
│ 你的应用程序 │
└─────────────────────────────────────────────────────────┘
│
│ SearchHotels(request)
▼
┌─────────────────────────────────────────────────────────┐
│ HTTP Dispatcher (大脑) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 限流器 │ │ 连接池 │ │ 优先级调度 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
└─────────┼──────────────────┼──────────────────┼───────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────┐
│ 供应商API(50个端点) │
│ HotelBeds | Dida | Expedia | Agoda | ... │
└─────────────────────────────────────────────────────────┘
核心职责
| 职责 | 为什么重要 |
|---|---|
| 限流 | 防止429错误,尊重供应商限制 |
| 连接池 | 减少延迟,提高吞吐量 |
| 请求优先级 | 确保关键请求优先处理 |
| 智能重试 | 自动处理临时故障 |
| 指标和可观测性 | 实时了解发生的情况 |
| 熔断器 | 停止对故障供应商的请求 |
为什么HTTP Dispatcher对酒店API集成至关重要
挑战1:限流混乱
供应商限流无处不在:
| 供应商 | 限流 | 类型 |
|---|---|---|
| HotelBeds | 10 req/s | 每个IP |
| Dida | 50 req/min | 每个API Key |
| Expedia | 100 req/s | 允许突发 |
| Agoda | 无限制 | 但会阻止滥用 |
| DerbySoft | 5 req/s | 严格 |
| TravelGDS | 20 req/s + 突发 | 令牌桶 |
没有HTTP Dispatcher:
// ❌ 你同时发送100个请求
for i := 0; i < 100; i++ {
go func() {
resp, err := http.Get("https://api.hotelbeds.com/v1/hotels")
// 结果:大多数请求因429失败
}()
}
有HTTP Dispatcher:
// ✅ Dispatcher自动排队和节流
dispatcher := NewHTTPDispatcher()
for i := 0; i < 100; i++ {
dispatcher.Submit(&Request{
Supplier: "hotelbeds",
URL: "https://api.hotelbeds.com/v1/hotels",
Priority: PriorityNormal,
})
}
// Dispatcher自动遵守10 req/s的限制
挑战2:连接开销
创建新的HTTP连接需要时间:
DNS查询: 20-50ms
TCP握手: 30-100ms
TLS握手: 50-150ms
─────────────────────────────
总计: 每个新连接100-300ms
没有连接池:
1000个请求 × 300ms = 300秒 = 5分钟!
有HTTP Dispatcher连接池:
第一个请求:300ms(新连接)
接下来的999个请求:10-20ms(复用连接)
总计:~5-10秒
性能提升:50-100倍更快
挑战3:优先级很重要
并非所有请求都平等:
| 请求类型 | 优先级 | 原因 |
|---|---|---|
| 实时预订 | 高 | 用户在等待,收入风险 |
| 价格比较 | 普通 | 重要但不紧急 |
| 缓存刷新 | 低 | 后台任务 |
| 分析同步 | 最低 | 可以等待 |
HTTP Dispatcher确保:
┌─────────────────────────────────────┐
│ 队列状态 │
│ ─────────────────────────────── │
│ [高] 预订 #1234 ← 处理中 │
│ [高] 预订 #1235 ← 下一个 │
│ [普通] 价格查询 ← 等待中 │
│ [普通] 价格查询 ← 等待中 │
│ [低] 缓存刷新 ← 等待中 │
│ [最低] 分析数据 ← 等待中 │
└─────────────────────────────────────┘
实际影响
案例研究:OTA平台集成
使用HTTP Dispatcher之前:
供应商数量:35
每秒请求数:500
429错误率:45%
P95响应时间:8.2秒
服务器CPU:95%
连接数:2000+
使用HTTP Dispatcher之后:
供应商数量:35
每秒请求数:500
429错误率:0.5%
P95响应时间:1.2秒
服务器CPU:45%
连接数:150
影响:
- 429错误减少89%
- P95延迟降低85%
- CPU使用减少53%
- 连接数减少92%
架构概览
核心组件
┌─────────────────────────────────────────────────────────────┐
│ HTTP Dispatcher │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 1. 请求路由器 │ │
│ │ - 路由到正确的供应商 │ │
│ │ - 应用供应商特定配置 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 2. 限流器(每个供应商) │ │
│ │ - 令牌桶算法 │ │
│ │ - 自适应退避 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 3. 连接池管理器 │ │
│ │ - 保持活动连接 │ │
│ │ - 池大小管理 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 4. 请求优先级调度器 │ │
│ │ - 优先级队列 │ │
│ │ - 公平调度 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 5. 重试和熔断器 │ │
│ │ - 指数退避 │ │
│ │ - 级联故障快速失败 │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
数据流
1. 提交请求
├─ 应用 → Dispatcher: SearchHotelsRequest
└─ Dispatcher → 队列: 带优先级入队
2. 限流检查
├─ Dispatcher → RateLimiter: 检查供应商限制
└─ RateLimiter → 队列: 需要时节流
3. 连接池查找
├─ Dispatcher → PoolManager: 获取连接
└─ PoolManager → Dispatcher: 复用或创建
4. 执行请求
├─ Dispatcher → 供应商: HTTP请求
└─ 供应商 → Dispatcher: 响应或错误
5. 处理响应
├─ 如果是429: 返回限流器,稍后重试
├─ 如果是5xx: 带退避重试
├─ 如果成功: 返回给应用
└─ 跟踪指标
什么时候你需要HTTP Dispatcher?
✅ 你需要HTTP Dispatcher如果:
- 3个以上供应商,有不同限流策略
- 100+ req/s的聚合流量
- 实时要求(预订、可用性检查)
- 成本约束(云提供商按连接收费)
- 需要可观测性了解供应商性能
❌ 你可能不需要如果:
- 1-2个供应商仅
- 低流量(<10 req/s)
- 仅离线批处理
- 原型或MVP阶段
总结
HTTP Dispatcher不是可选项,而是酒店API集成规模化的关键组件。它:
- 防止限流违规 → 更少的429错误
- 减少连接开销 → 更快的响应时间
- 优先处理关键请求 → 更好的用户体验
- 提供可观测性 → 调试变得更容易
- 优雅处理故障 → 更高的可靠性
推荐阅读
系列导航
HTTP Dispatcher系列:
- 什么是HTTP Dispatcher及为什么需要 ← 你在这里
- HTTP Dispatcher如何解决限流和连接池
- 在Go中实现HTTP Dispatcher
- 真实案例研究和性能改进
评论