kratos服务性能卡在100ms以上主因是连接、压缩、负载策略配置不当:grpc长连接池需设minconnecttimeout≥5s及keepalive参数;protobuf须手动启用gzip压缩并调大maxrecvmsgsize;负载均衡应按场景选wrr或直连ip,且需匹配maxconcurrentstreams与并发量。

Kratos服务性能卡在100ms以上?大概率不是代码逻辑问题,而是连接、压缩、负载策略这三块没调对。
gRPC长连接池配置不生效的常见原因
Kratos默认用grpc.Dial建连,但很多项目漏掉关键参数,导致每次请求都新建TCP连接。现象是监控里transport/grpc/transport.go显示连接数飙升、TLS握手耗时占比超30%。
- 必须显式设置
grpc.WithConnectParams里的MinConnectTimeout(建议≥5s),否则短超时会反复重试断连 -
grpc.WithKeepaliveParams中PermitWithoutStream要设为true,否则空闲时无法发心跳保活 - 服务端需同步配
grpc.KeepaliveParams的MaxConnectionIdle(建议30s)和MaxConnectionAge(建议10m),否则客户端心跳会被单方面关闭
Protobuf消息未压缩导致带宽瓶颈
小消息不压缩影响不大,但一旦返回结构体含bytes字段或列表长度>100,gRPC响应体积可能翻3倍。Kratos默认不启用压缩,需手动开启。
- 客户端加
grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip")),生产环境优先选gzip而非snappy(后者压缩率低且Kratos 2.8+有兼容问题) - 服务端必须配
grpc.MaxRecvMsgSize(如4*1024*1024),否则压缩后消息超过默认4MB会直接报rpc error: code = ResourceExhausted - 注意:HTTP/1.1网关透传gRPC时,部分Nginx配置会丢弃
grpc-encoding头,需检查proxy_set_header grpc-encoding ""是否遗漏
负载均衡策略选错引发流量倾斜
用discovery:///user-service却没指定balancerName,Kratos会走默认P2C算法。但P2C依赖节点延迟反馈,新实例上线前几秒可能被集中打爆。
- 灰度发布场景强制用
grpc.WithBalancerName("wrr"),配合selector.WithWeight给新实例配低权重(如10) - 固定IP调用第三方服务时,别用服务发现模式——直接写
"127.0.0.1:9000"并配http.DefaultClient.Transport.MaxIdleConnsPerHost=100,避免Consul Watcher引入额外延迟 - 所有
grpc.Dial调用必须加grpc.WithTimeout(建议≤3s),否则P2C选节点时阻塞会导致整个连接池卡住
最易被忽略的是服务端grpc.MaxConcurrentStreams和客户端并发请求数的匹配关系:设成1000看似够用,但如果单个请求平均耗时200ms,实际每秒只能撑5000 QPS,超出部分会堆积在gRPC流队列里,表现为延迟毛刺而非错误——这种问题只能靠grpc_server_stream_msgs_received_total指标定位。











