AWS生产环境gRPC间歇性Connection reset by peer错误排查
生产环境Go gRPC服务与PHP/Laravel客户端间歇性连接重置问题
问题背景
生产环境基于3台AWS实例部署,Go gRPC服务器与PHP/Laravel gRPC客户端通信时出现间歇性错误,该问题未在开发环境复现。错误信息如下:
gRPC call failed: recvmsg:Connection reset by peer
已确认生产环境的网络设置、防火墙规则与开发环境完全一致。
相关代码
Go gRPC 服务器代码
func RunGrpcServer() { lis, err := net.Listen("tcp", ":8089") if err != nil { log.Fatalf("Cannot create listener : %s", err) } serverRegistrar := grpc.NewServer() service := &myToysServiceServer{} gasgrpc.RegisterToysServiceServer(serverRegistrar, service) err = serverRegistrar.Serve(lis) if err != nil { log.Fatalf("impossible to server: %s", err) } }
PHP/Laravel gRPC 客户端代码
public function __construct() { $channelCredentials = ChannelCredentials::createSsl(); $this->client = new ToysServiceClient(config('grpc.grpc_url'), [ 'credentials' => $channelCredentials, ]); } public function getToys(): RepeatedField { $request = new GetAllToysRequest(); list($response, $status) = $this->client->GetAllToys( $request, [], ['timeout' => $this->timeout] )->wait(); if ($status->code !== \Grpc\STATUS_OK) { throw new \Exception("gRPC call failed: " . $status->details); } return $response->getToysHistories(); }
可能的原因分析
- AWS网络组件的连接回收机制:AWS负载均衡器(ALB/NLB)或实例TCP栈会主动回收空闲连接(默认ALB空闲超时为60秒)。若客户端复用了已被回收的连接,发起请求时就会触发连接重置。需检查LB超时设置,同时在客户端配置合理的连接存活时间,避免复用过期连接。
- 服务器端资源瓶颈:生产环境流量高峰时,Go服务器的文件描述符、内存或CPU资源耗尽,操作系统会主动重置新连接或现有连接。需查看服务器监控指标(CPU、内存、文件描述符使用率),确认是否存在资源耗尽情况。
- gRPC Keepalive配置缺失:
- 服务器端未配置Keepalive参数,空闲连接被中间网络设备(防火墙、LB)断开。可在创建gRPC服务器时添加
grpc.KeepaliveParams配置,定期发送心跳维持连接。 - 客户端未配置连接池或Keepalive策略,导致频繁创建销毁连接,或复用已失效连接。可在客户端初始化时添加连接复用、Keepalive相关参数(如
grpc.keepalive_time_ms)。
- 服务器端未配置Keepalive参数,空闲连接被中间网络设备(防火墙、LB)断开。可在创建gRPC服务器时添加
- SSL/TLS握手异常:生产环境SSL证书可能存在有效期不足、证书链不完整等问题,间歇性导致握手失败进而触发连接重置。需检查证书状态,或临时关闭SSL(仅测试环境)验证是否为证书问题。
- AWS网络波动:跨可用区或实例间的网络偶尔出现丢包、延迟,导致TCP连接异常终止。可查看CloudWatch的网络监控指标(数据包丢失率、延迟)确认网络层面问题。
- 服务器进程异常重启:某台AWS实例上的gRPC服务进程偶尔崩溃重启,客户端复用该实例的连接时就会收到连接重置错误。需检查服务器日志,确认是否有进程崩溃记录。
内容的提问来源于stack exchange,提问作者I.Jokhadze
相关产品推荐
相关产品推荐

