背景
最近有用户报使用PHP客户端predis
访问阿里云Redis
(原KVStore
)时,会出现connection refused
错误,用户怀疑是因为后端连接数超了,导致连接被拒绝,但是监控看连接数并没有超过阈值,进而怀疑是后端redis的连接数限制逻辑有问题,经过排查发现连接数限制逻辑并没有问题,下面说下具体的排查过程。
排查过程
通常通过socket
进行网络通信,出现connection refused
错误,主要是由于以下原因引起的,
- 目标端口没有打开,可能是监听端口的进程的已经挂了
- 有防火墙阻塞连接,客户端发过来的包直接被丢弃掉
- 监听端口对应的tcp backlog已经满了
- 网络质量问题
用户怀疑报connection refused
是因为后端连接数限制逻辑有问题,首先来排除这个原因。
实际上根据后端实现,当连接数超限时,会向客户端返回明确的错误信息,实际测试也可以发现,predis抛出的异常信息不是connection refused
,而是比较直观的错误信息,如下,
max number of clients reached
后端Redis挂了,这个可能性很小,直接看redis日志即可排除。防火墙的问题,在目前云Redis服务上也不存在相关设置,可以排除。
监听端口对应的tcp backlog
满了,这个是一个可能性比较大的原因,之前也确实出现过因为backlog
设置的过小导致连接拒绝的情况,执行netstat -s | grep -i listen
,如果有如下信息且数字还在增长,就基本可以确定是backlog的问题了,更具体的信息可以通过tcpdump
抓包获取,
10809 times the listen queue of a socket overflowed
10809 SYNs to LISTEN sockets ignored
但是之前我们就在异常实例的机器上调整过系统的somaxconn
参数和redis本身的backlog
参数到一个比较大的数值,所以发生connection refused
并非是因为tcp backlog满了。
那基于排除法,应该是网络本身的异常导致的问题了,这个时候就要借助于我们强大的后台监控系统天象
了,依托天象,我们可以看到,客户机到后端DB机器,在指定时间段内的网络质量情况,从天象上可以看到如下信息,
我们可以看到在连接拒绝期间,没有listen drop和listen overflow的情况,但是TCP重传率很高,有此可以肯定是在TCP建立连接时,三次握手超时导致出现connection refused
错误。
总结
当问题出现时,细心排查很重要,但是如果有一个强大的后台支撑系统,能够提供各种实时和历史信息,辅助我们进行排查,往往可以起到事半功倍的效果。况且很多时候,发现问题时,问题已经是过去式了,这个时候借助于这种平台可能就是排查问题的必须条件了,这里必须要赞下我们强大的天象系统了!