gRPC Keepalive 保活策略
配置主要用于维持客户端与服务端之间的长连接,避免连接在空闲时被网络中间层(如负载均衡器、代理等)关闭或断开。它可以帮助在不活跃期间定期发送保活信号来检测连接是否仍然有效。
服务端 Keepalive 配置参数:
- MaxConnectionIdle: 如果连接在指定时间内未活动(没有任何 RPC 请求),服务端会关闭连接。
- MaxConnectionAge: 设置连接的最大存活时间,当超过此时间,服务端会强制关闭连接。
- MaxConnectionAgeGrace: 在关闭连接之前给予客户端一段宽限时间,用于完成未完成的 RPC。
- KeepaliveTime: 服务端发送 Keepalive PING 帧的频率(仅在连接空闲时)。
- KeepaliveTimeout: 如果 PING 帧在指定时间内未收到响应,服务端会认为连接不可用。
客户端 Keepalive 配置参数:
- Time: 客户端发送 Keepalive PING 帧的间隔时间。
- Timeout: 如果 PING 帧在指定时间内未收到响应,客户端会认为连接不可用。
- PermitWithoutStream: 是否允许在没有活动 RPC 的情况下发送 Keepalive PING。
1. 服务端配置示例:
import (
"log"
"net"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/keepalive"
)
func main() {
kaPolicy := keepalive.ServerParameters{
MaxConnectionIdle: 5 * time.Minute, // 超过5分钟空闲就关闭连接
MaxConnectionAge: 30 * time.Minute, // 每个连接最多存活30分钟
MaxConnectionAgeGrace: 5 * time.Second, // 关闭前有5秒宽限期
KeepaliveTime: 2 * time.Minute, // 每2分钟发送一次PING帧
KeepaliveTimeout: 20 * time.Second, // 20秒未收到响应认为连接不可用
}
grpcServer := grpc.NewServer(grpc.KeepaliveParams(kaPolicy))
// 注册服务...
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
log.Println("gRPC server running on port :50051")
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}
2. 客户端配置示例:
import (
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/keepalive"
)
func main() {
kaPolicy := keepalive.ClientParameters{
Time: 1 * time.Minute, // 每分钟发送一次PING帧
Timeout: 10 * time.Second, // PING未响应10秒则断开连接
PermitWithoutStream: true, // 即使没有活动流也发送PING帧
}
conn, err := grpc.Dial(
"localhost:50051",
grpc.WithInsecure(), // 示例使用非安全连接
grpc.WithKeepaliveParams(kaPolicy), // 应用Keepalive策略
)
if err != nil {
log.Fatalf("Failed to connect: %v", err)
}
defer conn.Close()
// 创建客户端并发起请求...
log.Println("gRPC client connected")
}
3. keepalive配置的作用
- 防止连接被中间层断开:一些网络中间件会关闭长时间空闲的连接,Keepalive 可以避免这种问题。
- 快速检测连接状态:通过保活 Ping 检测连接是否仍然活跃,减少意外断开造成的请求失败。
- 优化资源管理:通过空闲超时和最大连接时长策略,释放长期不活动的连接,节省资源。