问题

查看服务时,发现某服务中存在一个closewait状态的tcp连接,而且一直无法断开连接

所有服务均为k8s pod 方式部署

分析

查看远端ip

bash-4.3$ netstat -tpn|grep 58142
tcp        1      0 10.5.165.124:58142      10.5.185.11:8080        CLOSE_WAIT  1/java
bash-4.3$ netstat -tp|grep 58142
tcp        1      0 kanche-platform-gateway-9685cbdd7-wqhkg:58142 service-order-search.default.svc.cluster.local:http-alt CLOSE_WAIT  1/java

本机ip为10.5.165.124,远端ip为10.5.185.11并且该服务为kanche-platform-gateway;查询该服务,发现该服务对应的10.5.185.11的pod已销毁。

故猜测原因为pod销毁导致连接未关闭

查看该tcp连接创建时间

  • 58142转为16进制为E31E
  • 查看该tcp连接,发现inode为3526526042
bash-4.3$ cat /proc/net/tcp |grep E31E
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
  3: 7CA5050A:E31E 0BB9050A:1F90 08 00000000:00000001 00:00000000 00000000     2        0 3526526042 1 ffff9d1a02528000 20 4 28 10 -1
  • 查询该inode(3526526042)对应的fd
bash-4.3$ ls -all /proc/1/fd/ |grep socket|grep 3526526042
lrwx------    1 daemon   daemon          64 Jan 29 10:41 192 -> socket:[3526526042]

即该连接创建时间为 1月29日10点41分

tcp close wait分析

close wait的原因为被动关闭连接时,已应答主动方,但是未向主动方发送fin报文,故一直处于close wait

当service-order-search向kanche-platform-gateway发送FIN包时,tcp协议返回ACK并将此tcp的状态更改为本地CLOSE_WAIT并通知http客户端(即应用层java程序)关闭套接字,但是应用程序不响应(没有线程使用套接字, 连接实际上是空闲的),那么连接仍处于CLOSE_WAIT状态

为什么没有线程使用套接字

假如现存zuul网关服务zuul及后端微服务s1

  1. 当zuul转发(SimpleHostRoutingFilter.forward)请求至s1时,会通过AbstractConnPool.lease()返回的Future.get(final long timeout, final TimeUnit tunit)方法获取connection;

WX20210201-155618@2x

  1. 在get方法中,会在connection pool中获取一个有效的连接

  2. 然后通过validate(leasedEntry)方法从连接中读取字符判断该连接的状态,如果读取到-1,则表示该连接的另一端已关闭,如果未读取到-1则阻塞读取,直到超时(此处超时时间为1ms,详情见BasicConnPool.validate(final BasicPoolEntry entry) -> BHttpConnectionBase.isStale())

  3. 如果读取到-1,则将该连接关闭。

上述过程部分代码如图
上述过程部分代码

  • updated为上次变更的时间戳
  • validateAfterInactivity表示tcp连接免校验的时长,默认为2000ms
  • 即 假如tcp更新2s内,不验证是否已关闭
  • 假如超过2s,则进入第3步校验过程,调用关系如下

WX20210129-170317

如果远程s1已关闭该tcp连接,但是zuul中未获取该连接,即不会read -1,故不会触发close方法,所以会存在close_wait的线程,直到zuul服务发现线程达到一定数量,主动关闭线程

上述问题只会遗留部分close_wait tcp连接,并不会导致程序严重问题,所以并没有好的解决方案

参考