golang tcp keepalive

缘起: grpc-client 连接 grpc-server后,空闲连接的情况下,server端会每隔15s向client发送一个keepalive数据包; 从grpc-server的配置中没有找到这个15s的配置,有的只是一个2小时发送一次的应用层的ping包。为啥呢?

分析:

  1. 该数据包可能是系统自己发送的,查看一下sysctl -a|grep tcp |grep keepalive 如下:
    按照这个配置,应该是75s一次才对,和实际的15s不符;难道不是系统发出来的?
  2. kill -19 PID后,发现间隔15s的数据包依然发送,说明肯定是系统发出来的
  3. 由于MacOS上的netstat 无法查看连接的Timer信息,于是使用Linux进行测试,发现keepalive的timer果然是从15s递减至0后就会发送该数据包(这里还发现当时间小于10s时,ss显示的时间单位是错的,把s写成了ms)。
  4. 一定是golang设置了一个和系统默认值不一样的keepalive; 那么是在什么时候设置的呢?从server端的Accept看起吧,发现Listen的时候有一个无法自定义的ListenerConfig,这里面有

 

 

@ net/dialog.go

Listen的时候,KeepAlive是0值,但是在newTcpConn的时候,检测如果是0值,就参考下面的默认值。

@ net/tcpsock.go

 

其实,在grpc/server.go 的grpc.Server.Serve()方法中已经特别说明了这个事情(而且仅就此问题做了说明):

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据