性能文章>【全网首发】Tablestore-OTSClient连接池连接无法复用分析>

【全网首发】Tablestore-OTSClient连接池连接无法复用分析原创

851628

问题现象

某应用在压测过程中,发现OTSClient与OTS服务端之间的TCP连接有大量处于TIME_WAIT状态。
查看与OTS服务端进行交互的不同TCP连接状态的数量:

netstat -ant | grep 10.4.170.39 | awk '/^tcp/{++state[$NF]};END{for(key in state) print key,state[key]}'

image.png

分析过程

TIME_WAIT

image.png
OTSClient连接处于TIME_WAIT状态,由上图可知TCP连接是由OTSClient主动关闭的,所以OTSClient为什么要频繁的关闭TCP连接?在什么情况下关闭的?

tcpdump

通过tcpdump抓包可以清楚OTSClient与OTS服务端通讯协议及建立连接、传输数据、断开连接的过程。
OTSClient与OTS服务端通讯协议是HTTP1.1,HTTP1.1默认开启长连接,所以代码在某个地方主动断开了连接,接下来是找到代码中什么地方主动关闭的连接。

OTSClient

OTSClient构造方法中用于构造与OTS服务端通讯的代码如下:

public OTSClient(String endpoint, String accessKeyId,
                     String accessKeySecret, String instanceName,
                     ClientConfiguration config, OTSServiceConfiguration otsConfig, String stsToken) {
	... ...
	this.client = new AsyncServiceClient(config);
	... ...
}

AsyncServiceClient构造方法如下:
image.png

IdleConnectionEvictor

image.png

场景回顾

应用中配置的socketTimeout=50ms,根据上面逻辑closePeriod=20ms,即当TCP连接空闲20ms的时候就主动关闭,主动关闭造成的现象是大量连接处于TIME_WAIT状态。

对系统的影响

  • 连接无法复用,每次请求OTS服务端都要新建TCP连接/关闭连接,造成客户端和服务端资源浪费
  • 频繁新建/关闭连接,更容易造成响应时间的毛刺
  • 大量连接处于TIME_WAIT状态,消耗系统内存、文件描述符等资源

QA

Q:是否可以调大socketTimeout来避免TIME_WAIT的问题?
A:不合适,该应用在线上访问OTS服务端平均响应时间是5ms,如果设置的过大,当与OTS服务端交互发生超时的时候,线程需要等待更长的时间会造成整个接口超时(业务要求该查询接口响应时间在60ms以下,线上平均响应时间是30ms)。

解决办法

查看了OTSClient 5.13.7的实现,与当前版本实现逻辑一致,所以更新OTSClient版本并不能解决这个问题。

<dependency>
	<groupId>com.aliyun.openservices</groupId>
	<artifactId>tablestore</artifactId>
	<version>5.13.7</version>
</dependency>

已经向阿里反馈该问题,估计阿里的改动如下:

  • 将IdleConnectionEvictor定时间隔参数开放出来,让业务可以配置
  • 将IdleConnectionEvictor空闲时间参数开发出来,让业务可以配置

参看资料

Apache HttpClient Connection eviction policy
Apache HttpClient IdleConnectionEvictor
TimingWheels

点赞收藏
大禹的足迹

在阿里搬了几年砖的大龄码农,头条号:大禹的足迹

请先登录,查看2条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步
8
2