使用多Aerospike Java客户端出现超时,切换单客户端解决原因问询
为什么切换为单客户端复用能解决超时问题
- Aerospike Java客户端本身自带内置连接池,单个客户端实例初始化时就会和集群所有节点预先建立一批长连接,统一托管在内部连接池中。所有读写事务都会复用池中的已有连接,无需每次请求都重新建立TCP连接,大幅降低额外开销。
- 每个事务新建客户端实例时,每次初始化都要重新和所有集群节点完成TCP三次握手、集群节点信息同步等操作,单是初始化耗时就很容易超过你设置的1000ms超时阈值,触发报错:
报错中Aerospike Error: (9) Client timeout: timeout=1000 iterations=1 failedNodes=0 failedConns=0failedNodes=0 failedConns=0也能验证这一点:请求还没完成客户端初始化和建连流程,就已经触发了超时,还没到实际发送读写请求的步骤。 - 高频新建客户端会导致连接数短时间暴涨,一方面会触达Aerospike服务端的连接数上限,新的连接请求会被拒绝或排队;另一方面会占满操作系统层面的文件描述符配额,无法创建新的socket连接,进一步加剧超时问题。复用单客户端时,连接池的连接总数长期维持在稳定的合理值,不会出现资源耗尽的情况。
为什么之前的连接不会自动关闭
- Aerospike客户端设计上默认保持长连接:只要你不显式调用
AerospikeClient.close()方法主动释放资源,客户端会一直维持和集群节点的长连接,定期发心跳保活,避免重复建连的开销,不会主动断开连接。 - TCP连接属于操作系统层面的堆外资源,JVM的垃圾回收只能回收堆内的
AerospikeClient对象实例,不会主动清理底层关联的socket文件描述符。就算客户端对象被GC回收,对应的socket连接还会在操作系统层面保留很长时间,通常处于TIME_WAIT状态,短时间大量创建又不主动关闭的情况下,操作系统的回收速度远赶不上创建速度,连接数就会持续堆积。
内容的提问来源于stack exchange,提问作者KANARAM BHARI
相关产品推荐
相关产品推荐

