gRPC Connection reset by peer 问题

前提 因产品需求,需用PHP(v7.0.12)调用k8s集群中gRPC([email protected])服务。 问题 经过dev环境测试,当php-fpm启动后第一次调用或者距离上次调用时间20分钟后左右,再次请求gRPC微服务接口,就会返回 Connection reset by peer 错误,说明gRPC服务端或者客户端主动关闭连接了。继续发起请求到服务端,又恢复正常。 思考 经查阅相关资料,发现问题可能出现在k8s集群的kube-proxy模式上。当前k8s环境(dev)下的kube-proxy为ipvs模式,服务端与客户端之间通信如下: 把上图client看成是apsopen-inside服务pod,Backend pod(1~3)看成gRPC服务,可以看出它们之间的交互路径: ---> gRPC server pod1 gRPC-client ---> ipvs ---> gRPC server pod3 ---> gRPC server pod3 我们知道gRPC是基于HTTP/2协议的,gRPC的client和server在交互时会建立多条连接,为了性能,这些连接都是长连接并且是一直保活的。 这段环境中不管是客户端服务还是gRPC服务都被调度到各个相同配置信息的Kubernetes节点上,这些k8s节点的 keep-alive 是一致的,如果出现连接主动关闭的问题,因为从client到server经历了一层ipvs,所以最大的可能就是ipvs出将连接主动断开,而client端还不知情。 搜索 ipvs timeout 关键字找到了下面相关的链接: https://github.com/moby/moby/issues/31208 https://success.docker.com/article/ipvs-connection-timeout-issue https://github.com/kubernetes/kubernetes/issues/32457 其中 https://github.com/moby/moby/issues/31208 中是关于docker swarm在overlay网络下长连接的问题,这个和k8s kube-proxy应该是类似的,按照这个链接中的描述查看 我们这套环境关于tcp keepalive的内核参数: #进入igo-util-shorturi容器 sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_probes net.ipv4.tcp_keepalive_intvl net.ipv4.tcp_keepalive_time = 7200 net.ipv4.tcp_keepalive_probes = 9 net.ipv4.tcp_keepalive_intvl = 75 上面这段参数的含义: net.ipv4.tcp_keepalive_time 是连接时长,当超过这个时间后,每个 net.ipv4.tcp_keepalive_intvl 的时间间隔会发送keepalive数据包, net.ipv4.tcp_keepalive_probe 是发送keepalived数据包的频率。 解决 使用 ipvsadm 命令查看k8s节点上ipvs的超时时间:...

2019-07-22 · 1 min · L