最近添哥一直反映,他手下的设备以grpc stream的方式向我服务端发送数据。偶然会收到错误。现象如下:

  1. 连接已经建立了一段时间,正常使用。
  2. 突然client.Send 返回 eof。
  3. 客户端有报错:connection reset by peer
  4. 在服务端找到错误:context canceled

这里不得不提一下,客户端上报到服务的网络环境并不是很好,而且服务端每个进程有数十万个协程在运行,处理上十万条grpc stream。

选取了几个设备在服务端与客户端tcpdump,通过七七四十九天,终于捕获到了异常时的抓包。

现象:

  1. 正常情况下,服务端客户端定期互Ping。
  2. 当异常时,在服务端/客户端的抓包会发现Ping包未回。很快连接断开。

猜测和grpc keepalive功能有关。

grpc server keepalive配置

原始配置

	var keepAliveArgs = keepalive.ServerParameters{
Time: 60 * time.Second,
Timeout: 5 * time.Second,
}
s := grpc.NewServer(
grpc.KeepaliveParams(keepAliveArgs).....)

为了防止客户端断连后资源泄漏,grpc的服务端一般会配置keepalive,每隔一段时间就向空闲的client发送ping包,并计算回包的时间。当ping没有回应。则认为连接已失败(比如被墙),此时在服务端会关闭这个连接并配置svr.Context()为done。

上面的配置代表,每60S向客户端检测一次,如果ping的包没有在5秒内回,则断开连接。此时就会出现上述的异常事件。

原因分析

为了弄清keepalive的逻辑,查看源码grpc/internal/transport/http2_server.go

grpc ping发包逻辑

每隔预设的时间,就会发一个包。并将kpTimeoutLeft置为keepalive.Timeout

发包之后逻辑

  1. 检测是否在kpTimeoutLeft为0前收到了任何数据(不仅是ping的回包)。
  2. 此时outstandingPing为true,所以不会再有新的ping被发出。这是最坑的一点设计。合理的设计应该允许重试几次,以重试后能收到包为准。
  3. 不停的去sleep,并去减小kpTimeoutLeft。
  4. 当kpTimeoutLeft<0,连接关闭。

预期外断联原因

可能是因为网络抖动或者grpc server忙不过来,使得某次的ping包被丢弃或未及时处理。造成了连接被错误的切断。

解决

一开始,想要找一找有没有retry之类的配置。不要仅丢弃一次就把连接切断,但没找到。这时,添哥突发奇想,将Timeout的时间延长。于是,keepalive的配置变成了这样:

	var keepAliveArgs = keepalive.ServerParameters{
Time: 30 * time.Second,
Timeout: 90 * time.Second,
}

在这个配置下,为ping之后给了更长的反应时间,根据grpc的源码,90秒内如果有任意的数据被接收(包含收到客户端发来的消息)。连接都不会被切断。但假如客户端一直没有数据回发,猜想应该还是会把连接切断。因为ping在没有收到回消息的时候不会再进行下一次ping。

通过查看注释也能应证代码的实现:

	// After having pinged for keepalive check, the server waits for a duration
// of Timeout and if no activity is seen even after that the connection is
// closed.
Timeout time.Duration // The current default value is 20 seconds.

只要在ping后timeout内有activity,连接就不会中断。还好这个业务client和server交互很频繁,在90秒内一般会有数据的交互。

立马变更,困扰我们很久的问题,用一种不是很优雅的方式解决了。

go grpc: connection reset by peer 的一种解决方案的更多相关文章

  1. connection reset by peer问题总结及解决方案

    找遍了 中英文网站,翻遍了能找的角落,发现了出现故障的原因和原理,及改如何处理,这里记录下,希望能帮助到有需要的小伙伴,少走点弯路, 以上就整理内容: connection reset by peer ...

  2. Doker GRPC "Connection reset by peer"

    https://success.docker.com/article/ipvs-connection-timeout-issue https://forums.docker.com/t/setting ...

  3. ”Connection reset by peer“引发的思考

    闲来无事,把之前写的一个游戏服务器框架(<一个java页游服务器框架>),部署到阿里云服务器上,测试运行了下,结果看到后台log中打印出了“Connection reset by peer ...

  4. Error -27780: [GENERAL_MSG_CAT_SSL_ERROR]connect to host "124.202.213.70" failed: [10054] Connection reset by peer [MsgId: MERR-27780]

    解决方案一: 备注: 此方案如果请求响应时间太长,勾选"WinInet replay instead of Sockets(Windows only)"将会导致如下错误:

  5. ab测试出现error: connection reset by peer的解决方案

    我们在使用一些开源程序之前,可能会使用ab工具在服务器或者本地进行一次性能评估,但是很多时候却总是会以失败告终,因为,服务器会拒绝你的ab工具发出的http请求, 出现 error: connecti ...

  6. gem install 出现Errno::ECONNRESET: Connection reset by peer - SSL_connect (https://api.rubygems.org

    在安装了rvm来管理多版本的ruby之后,想在不同环境下安装一些gems,结果gem install puma 之后,发现一次又一次失败. gem install 出现Errno::ECONNRESE ...

  7. OGG-01232 Receive TCP params error: TCP/IP error 104 (Connection reset by peer), endpoint:

    源端: 2015-02-05 17:45:49 INFO OGG-01815 Virtual Memory Facilities for: COM anon alloc: mmap(MAP_ANON) ...

  8. apache ab压力测试报错(apr_socket_recv: Connection reset by peer (104))

    apache ab压力测试报错(apr_socket_recv: Connection reset by peer (104))   今天用apache 自带的ab工具测试,当并发量达到1000多的时 ...

  9. java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)

    java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)

随机推荐

  1. XCTF练习题---MISC---stegano

    XCTF练习题---MISC---stegano flag:flag{1nv151bl3m3554g3} 解题步骤: 1.观察题目,下载附件 2.打开发现是一张PDF图片,尝试转换word无果后,想到 ...

  2. 深入理解mmap--内核代码分析及驱动demo示例

    mmap是一个很常用的系统调用,无论是分配内存.读写大文件.链接动态库文件,还是多进程间共享内存,都可以看到其身影.本文首先介绍了进程地址空间和mmap,然后分析了内核代码以了解其实现,最后通过一个简 ...

  3. Java 15 新特性:文本块

    大家好,我是DD,今天继续来学点Java的新特性! 假设有这样一个场景,我们需要做一个工具.用来自动生成项目文档,文档可以通过浏览器查看,所以最后产出物肯定是一堆html文件.为了让这些html文件更 ...

  4. 图文详解:小白也能看懂的 Kubernetes

    Kubernetes 这个单词来自于希腊语,含义是舵手或领航员 .其词根是 governor 和 cybernetic.K8s 是它的缩写,用 8 字替代了"ubernete". ...

  5. position与float

    position:fixed/absolute和float的关系:元素设置position:absolute / fixed后,float属性是没有效果的.对于position: absolute元素 ...

  6. Android添加布局和按键

    Android添加布局和按键 Android布局方式分为 1.LinearLayout (线性布局) 2.ConstraintLayout (约束布局) 3.FrameLayout (帧布局) 4.T ...

  7. MySQL8新增降序索引

    MySQL8新增降序索引 桃花坞里桃花庵,桃花庵里桃花仙.桃花仙人种桃树,又摘桃花卖酒钱. 一.MySQL5.7 降序索引 MySQL在语法上很早就已经支持降序索引,但实际上创建的却仍然是升序索引,如 ...

  8. Java学习笔记-基础语法Ⅶ-集合

    集合 集合类特点:提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变 这里需要回顾一下,因为数组和字符串一旦创建,就不可改变,需要区分一下 import java.util.ArrayLi ...

  9. C Primer Plus 学习笔记 -- 前六章

    记录自己学习C Primer Plus的学习笔记 第一章 C语言高效在于C语言通常是汇编语言才具有的微调控能力设计的一系列内部指令 C不是面向对象编程 编译器把源代码转化成中间代码,链接器把中间代码和 ...

  10. windows获取高精度时间戳 精度100ns

    #include <stdio.h> #include <Windows.h> int main(void){ LARGE_INTEGER ticks,Frequency; Q ...