网络层封装:HTTP/HTTPS请求构造与连接池管理
网络层封装是SDK的血管。
说白点,所有业务逻辑最终都要通过它把数据发出去,再把响应接回来。我在项目中见过太多SDK因为网络层写得糙,上线就崩。今天就聊聊HTTP请求怎么构造、HTTPS握手怎么优化、连接池怎么管。
1. HTTP请求构造:别只写个URL就完事
一个完整的HTTP请求,远不止URL。你想想看,SDK要跟后端通信,方法、路径、Header、Body、超时、编码,每一环都不能省。
| 组成要素 | 常见场景 | 个人踩坑 |
|---|---|---|
| HTTP方法 | GET(查)、POST(写)、PUT(全量更新)、DELETE(删) | 有人拿GET上传大JSON,接口直接挂 |
| URL+路径参数 | RESTful路径、QueryString | 中文没URLEncode,服务端400 |
| 请求头 | Content-Type、Authorization、User-Agent | Content-Type写错,Body解析失败 |
| 请求体 | JSON、Form、Multipart | 大文件上传没分块,OOM |
| 超时控制 | 连接超时、读超时、写超时 | 默认超时太长,用户反馈卡死 |
我的习惯:把请求构造拆成Builder模式。这样每个参数都强校验,不会漏掉Content-Type。
2. HTTPS与SSL/TLS握手:别让安全拖慢性能
HTTPS不是玄学。每次握手至少两次RTT,连接池如果没复用,那你的SDK性能会很难看。
我建议关注这几个点:
- 证书验证:生产环境用信任链,测试环境可以宽松。但别偷懒全关掉,我记得有一次测试环境忘记关验证,调试了一下午。
- 会话复用(Session Ticket / Session ID):断线重连时能省去完整握手,性能提升明显。
- SNI(Server Name Indication):一台服务器挂多个域名,必须支持SNI,否则证书不匹配。
- HTTP/2+ALPN:如果服务端支持,用HTTP/2能多路复用,减少连接数。
核心经验:HTTPS不是配置完就不管了。我建议监控TLS握手耗时,一旦超过200ms,就要检查证书链或会话复用配置。
3. 连接池管理:最容易被忽略的瓶颈
连接池做不好,SDK就会变成“连接泄漏器”。
核心参数就几个,但每个参数背后都有坑。
| 参数 | 说明 | 我建议的值 |
|---|---|---|
| 最大连接数 | 同时保持的连接上限 | CPU核心数×2,或根据QPS压测 |
| 空闲超时 | 连接空闲多久后关闭 | 30秒(太短频繁建连,太长浪费资源) |
| Keep-Alive | TCP层面保持存活 | 5秒探测一次,3次无响应就断开 |
| 队列大小 | 等待获取连接的最大请求数 | 100左右,超出直接拒绝(快速失败) |
代码示例(Java风格,仅示意):
public class ConnectionPoolConfig {
private int maxTotal = 50;
private int maxPerRoute = 10;
private int connectionTimeout = 5000; // 5秒
private int socketTimeout = 10000; // 10秒
private int idleTimeout = 30000; // 30秒
private boolean evictExpired = true;
// getter/setter省略
}
避坑指南:我曾经在生产环境遇到连接池泄漏——第三方服务端超时不关连接,我们这边连接池占满,所有请求全排队。后来加了空闲检测和主动关闭,才压住。
4. 重试与超时策略:别让用户等到哭
重试不是无限重试。指数退避才是标准答案。
- 重试次数:通常3次,再多反而加重服务器压力。
- 退避算法:第一次1秒,第二次2秒,第三次4秒,加上随机抖动。
- 超时分类:连接超时(5秒)、读超时(10秒)、写入超时(10秒)。不同场景分开设置。
我的做法:把重试逻辑封装成拦截器。这样业务层不需要关心网络异常,只等成功或最终失败回调。
5. 知识结构总图
下面这张图展示了网络层封装的核心模块与数据流向。
6. 避坑合集
- 连接泄漏:响应流没读完整就close,底层连接会被标记为“脏”,必须显式discard。
- DNS缓存:移动端切换WiFi后,如果缓存旧IP,请求会超时。我建议设置DNS TTL不要超过30秒。
- 线程安全:连接池通常线程安全,但每次请求都new一个HttpClient就悲剧了。
- Mock测试:网络层必须有Mock能力,不然集成测试跑一遍要半天。
一句话总结:网络层做得好,SDK就像老司机——稳、快、不出事;做不好,用户第一反应就是“这SDK真烂”。