目录
第一步 重启并抢先占一个连接
第二步 记录全部客户端
第四步 定位服务并把锅扔过去
记一次 Redis 连接超限问题排查经过.
文章地址:
项目起不来了!
... 项目又起不来了!
... 又双叒叕???!!!
上周经常听到组里同事说项目又双叒叕挂了, Redis 连不上, 笔者在另一套正常的环境忙着开发新需求, 没空关心这个问题.(PS: 反正我的环境能用 (´)σ , 先忙完我的再说).
于是乎, 看了一眼日志, 连接数过多... emmm, 顺手帮同事把 Redis 配置里连接数上限加了个 0, 问题排查什么的等忙完再说.
ERR max number of clients reached
终于... 该来的总逃不掉, 笔者用的环境也被搞崩了, 而且是莫名其妙地就凉了.
不过... 因吹斯汀 !
修改连接数上限毕竟治标不治本, 本来连接数上限就是 10000 , 微服务总共才几十个, 按理说根本用不完.
肯定有人没关连接, 查他.
已知:
Redis 服务重启后, 用一段时间连接就又满了.
服务总共几十个, 配置的一万连接数正常情况下不大可能用完.
第一步 重启并抢先占一个连接
笔者重启了 Redis 后, 立即连接到 Redis, 查看客户端数量 (晚了就连不上了):
- $ docker exec -it $(docker ps | grep Redis | awk '{print $1}') Redis-cli -a {
- pwd
- }
- 127.0.0.1:6379> info
- ...
- # Clients
- connected_clients:391
- ...
- tips:
info 命令能查看关于 Redis 服务器的各种信息和统计数值.
第二步 记录全部客户端
几分钟后再次查看:
- 127.0.0.1:6379> info
- ...
- # Clients
- connected_clients:10002
- ...
此时, 连接已经被全部占满了.
将全部客户端信息保存到文件准备抓出这个搞事情的老哥.
- 127.0.0.1:6379> client list
- id=7863 addr=172.18.0.104:56836 fd=6150 name= age=72 idle=72 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
- id=7864 addr=172.18.0.50:56262 fd=6151 name= age=72 idle=72 flags=N db=9 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
- id=7865 addr=172.18.0.104:56840 fd=6152 name= age=72 idle=72 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
- ...
tips:
client list : 列出全部客户端信息.
第三步 找出异常 IP
有了全部的客户端连接信息, 就能找出到底是谁的锅了. 使用命令输出连接数前五的 IP:
- $ cat client-list | awk '{print $2}' | awk -F "[=:]" '{print $2}' | sort | uniq -c | sort -k1,1nr | head -5
- 5432 172.18.0.50
- 4244 172.18.0.104
- 43 172.18.0.59
- 40 172.18.0.54
- 32 172.18.0.55
到目前为止, 锁定了 172.18.0.50 和 172.18.0.104 两个 IP. 这两个都是 docker 内部网络的地址.
tips:
awk '{print $2} : 输出第二列, 即 IP. addr=172.18.0.104:56836 .
awk -F "[=:]" '{print $2}' : 通过等号和冒号拆分 addr=172.18.0.104:56836 , 并输出中间的 IP.
sort : 排序.
uniq -c : 统计数量并在每列旁边显示该行重复出现的次数.
第四步 定位服务并把锅扔过去
拿到了 IP 就离目标不远了, 通过 docker inspect 能输出 docker 实例的信息, 其中就包括 IP.
- $ docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq) | grep 172.18.0.50
- /docker_xxxxx-service - 172.18.0.50
- $ docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq) | grep 172.18.0.104
- /docker_yyyyy-service - 172.18.0.104
- tips:
docker inspect : 获取容器 / 镜像的元数据.
--format : 用模板格式化输出.
至此, 定位到了 xxxxx 和 yyyyy , 嗯... 隔壁 Py (thon) 组的服务. 来, 锅给你.
来源: http://www.tuicool.com/articles/NvQfUv7