返回 筑基・网络云路秘径
长连接与连接池设计
博主
大约 4 分钟
长连接与连接池设计
一、问题引入:短连接的性能瓶颈
1.1 真实案例:微服务通信延迟优化
场景:电商系统微服务间调用,平均响应时间200ms
问题:服务间调用频繁,TCP握手开销占比过高
分析:
┌─────────────────────────────────────────────────────────────┐
│ 短连接问题: │
│ - 每次调用需TCP三次握手(约50ms) │
│ - TLS握手(约100ms) │
│ - 实际数据传输仅10ms │
│ - 连接建立开销占比75% │
├─────────────────────────────────────────────────────────────┤
│ 长连接优化效果: │
│ - 连接复用,消除握手开销 │
│ - 平均响应时间:200ms → 50ms │
│ - 系统吞吐量提升4倍 │
└─────────────────────────────────────────────────────────────┘
1.2 长连接vs短连接
短连接:
请求 → 建立连接 → 发送数据 → 关闭连接
缺点:频繁握手,开销大
长连接:
建立连接 → 请求1 → 请求2 → 请求3 → ... → 保持连接
优点:减少握手开销,提高吞吐量
二、HTTP Keep-Alive与连接复用
2.1 HTTP Keep-Alive机制
HTTP/1.1 Keep-Alive:
┌──────────────────────────────────────────────────────────────┐
│ │
│ 请求头:Connection: keep-alive │
│ │
│ 响应头: │
│ Connection: keep-alive │
│ Keep-Alive: timeout=60, max=1000 │
│ │
│ 优势: │
│ - 复用TCP连接 │
│ - 减少延迟 │
│ - 降低CPU消耗 │
│ │
│ 注意事项: │
│ - 需要处理连接超时 │
│ - 注意连接数限制 │
│ - 处理"哑代理"问题 │
│ │
└──────────────────────────────────────────────────────────────┘
Nginx配置:
```nginx
keepalive_timeout 65;
keepalive_requests 1000; # 单个连接最大请求数
### 2.2 HTTP/2多路复用
HTTP/2特性:
- 单一TCP连接承载多个流
- 请求响应交错发送
- 彻底解决队头阻塞
- 头部压缩(HPACK)
## 三、数据库连接池设计
### 3.1 连接池核心参数
```java
/**
* HikariCP最佳实践
*/
HikariConfig config = new HikariConfig();
// 连接池大小公式:connections = ((core_count * 2) + effective_spindle_count)
int poolSize = Runtime.getRuntime().availableProcessors() * 2 + 1;
config.setMaximumPoolSize(poolSize);
config.setMinimumIdle(poolSize / 2);
// 超时配置
config.setConnectionTimeout(30000); // 获取连接超时:30s
config.setIdleTimeout(600000); // 空闲超时:10min
config.setMaxLifetime(1800000); // 最大生命周期:30min
// 性能优化
config.setAutoCommit(false);
config.setCachePrepStmts(true);
config.setPrepStmtCacheSize(250);
3.2 连接池监控
@Component
public class ConnectionPoolMonitor {
@Scheduled(fixedRate = 60000)
public void monitor() {
HikariPoolMXBean poolMXBean = dataSource.getHikariPoolMXBean();
log.info("Pool Stats - Active: {}, Idle: {}, Wait: {}",
poolMXBean.getActiveConnections(),
poolMXBean.getIdleConnections(),
poolMXBean.getThreadsAwaitingConnection()
);
}
}
四、HTTP连接池设计
4.1 OkHttp连接池
/**
* OkHttp连接池配置
*/
@Bean
public OkHttpClient okHttpClient() {
ConnectionPool connectionPool = new ConnectionPool(
50, // 最大空闲连接
5, // 存活时间(分钟)
TimeUnit.MINUTES
);
return new OkHttpClient.Builder()
.connectionPool(connectionPool)
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.connectionPool(connectionPool)
.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
.build();
}
4.2 WebClient连接池
@Bean
public WebClient webClient() {
ConnectionProvider provider = ConnectionProvider.builder("custom")
.maxConnections(500)
.maxIdleTime(Duration.ofSeconds(20))
.maxLifeTime(Duration.ofSeconds(60))
.pendingAcquireTimeout(Duration.ofSeconds(60))
.build();
HttpClient httpClient = HttpClient.create(provider)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.responseTimeout(Duration.ofSeconds(30));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
五、长连接保活机制
5.1 TCP Keepalive
# Linux TCP Keepalive配置
# 探测间隔
sysctl -w net.ipv4.tcp_keepalive_intvl=30
# 探测次数
sysctl -w net.ipv4.tcp_keepalive_probes=3
# 空闲时间
sysctl -w net.ipv4.tcp_keepalive_time=300
5.2 应用层心跳
/**
* WebSocket心跳机制
*/
@Component
public class WebSocketHeartbeat {
private static final long HEARTBEAT_INTERVAL = 30000; // 30秒
@Scheduled(fixedRate = HEARTBEAT_INTERVAL)
public void sendHeartbeat() {
sessions.forEach(session -> {
if (session.isOpen()) {
session.sendMessage(new PingMessage());
}
});
}
}
六、连接池最佳实践
检查清单:
□ 合理设置连接池大小(避免过大或过小)
□ 配置连接超时和空闲检测
□ 启用连接池监控
□ 处理连接泄漏
□ 设置连接最大生命周期
□ 配置健康检查
□ 优雅关闭连接池
系列上一篇:TCP拥塞控制深度解析
系列下一篇:微服务网络通信模式
知识点测试
读完文章了?来测试一下你对知识点的掌握程度吧!
评论区
使用 GitHub 账号登录后即可发表评论,支持 Markdown 格式。
如果评论系统无法加载,请确保:
- 您的网络可以访问 GitHub
- giscus GitHub App 已安装到仓库
- 仓库已启用 Discussions 功能