4.3 共享 HTTP 客户端(连接池上限)
机制原理
CubeAPI 启动时创建一个全局共享的 reqwest::Client 实例,所有外部 HTTP 调用(auth callback、webhook、镜像拉取)都通过它发出。
// CubeAPI/src/state.rs:50-55
http_client = reqwest::Client::builder()
.pool_max_idle_per_host(100)
.timeout(Duration::from_secs(30))
.tcp_keepalive(Duration::from_secs(60))
.connect_timeout(Duration::from_secs(10))
.build()
.expect("http client init"),
关键参数:pool_max_idle_per_host=100 —— 每个 host 上最多保留 100 个空闲连接。
为什么 CubeSandbox 这样设计
- 避免 fd 耗尽 —— 没有连接池上限,1k 个 sandbox 同时回调 auth callback 可能创建 1k+ 连接,吃光 host 的 fd 上限
- 复用连接减少握手 —— TLS 握手是 ~50ms,复用已经握过的连接降低延迟
- 统一超时配置 ——
connect=10stotal=30skeepalive=60s,防止某些请求挂住耗光线程 - 观测入口集中 —— prometheus 抓 client 状态时是单一 client,debug 简单
如何使用 / 配置
硬编码
这是 CubeAPI 默认配置,管理员不可在运行期改。如要修改,改源码后重新构建。
验证
# 看 CubeAPI 进程的 fd
ls /proc/$(pidof cube-api)/fd | wc -l
# 看 socket count
ss -ant | grep $(pidof cube-api) | wc -l
客户端行为
不影响普通客户端行为——只对 server-side 而言共享。
注意:
- 当 auth callback 同时被很多 client 调用,
pool_max_idle_per_host=100可能会成为瓶颈。常见调优:- 把 auth callback 域名走多个 VIP(L4 load balancer 散开)
- 改成 client-side keep-alive 后,连接合并
connect_timeout=10s在网络抖动时会连续 fast-fail,因此 callback 失败可见- 不要尝试关掉 keep-alive(
TcpKeepalive):time wait状态可能在高并发时把 5-tuple 占满 - 客户端构建线程安全,但不要频繁 rebuild(否则连接池全部扔掉重建)
- 典型坑:部署时发现 fd 涨到 65535;如果 host
ulimit -n调到 1M,但net.core.somaxconn没调,新建连接排队 → CubeAPI 卡 10s 才能 throw 错误