某天下午,提交了代码的我正在测试环境狠狠地测试刚完成的新功能,把业务流程走了一遍没发现什么问题,美滋滋地准备享受下午茶,但突然发现页面上有的接口打开速度变慢了,要好几秒,刚开始以为是自己的网卡了,刷新后又测试了几下,发现确实有时候接口会变慢,于是开始了漫漫排查之路!
一、问题
在页面上表现出来的效果是:测试环境下的接口偶尔出现变慢的情况。经过统计发现一定规律:平均调用十次的情况下,差不多每隔三到四次就会出现一次抖动,并且时间基本在3秒多。
二、开始排查
1.接口
接口变慢首先肯定就要排查接口本身,但是前段时间还好着,今天突然就这样了。再加上出于对自己的自信,我是没觉得是接口的问题,但为了严谨,该有的流程还是得有,于是用Apifox测试了部分会变慢的接口,经过排查,接口的响应速度很正常,并没有出现抖动现象。
2.数据库
排除了接口本身,就往更深一层的数据库去考虑了。通过对接口的测试,我们就已经可以排除慢SQL的可能,但我们要排查是否会出现高CPU、高I/O(虽然通常情况下,它们也是由慢SQL引起的),但是还有别的因素可能也会影响,比如数据缓冲池的大小 (如果数据不在缓冲池中,那么MySQL就需要从磁盘中读取数据,并将其放入缓冲池中,这就涉及到磁盘I/O操作。对于写操作,如果数据页不在缓冲池中,那么MySQL会先将数据页读入缓冲池,然后在缓冲池中进行修改,最后由后台线程异步地将修改后的数据页写回磁盘。)等。
因此,对于这里的排查就显得有必要了,这里我们会用到一个小工具------iotop,它可以实时监控磁盘I/O情况,它的安装和使用也非常简单:
bash
# 步骤一:安装iotop,根据自己的系统选择对应的安装命令
sudo apt-get install iotop -y
# 步骤二:查找MySQL的进程ID
ps aux | grep mysql
# 步骤三:使用iotop监控MySQL进程
sudo iotop -p <mysql_pid>
虽然当时在这个环节信心满满地以为找到了问题,但很可惜,MySQL的I/O没有问题,并且通过对服务器的可视化监控,CPU和磁盘也都很正常,没出现过高占用的情况。
3.k8s
回到最开始的问题,通过统计数据不难看出,接口抖动现象的发生呈现出了周期性和规律性,因此我在想会不会是它们共同依赖的某个基础服务或接口出现了问题,因为它们都依赖了用户相关的接口,于是我对用户相关的接口又进行了一次统一的测试,但很无奈,它们呈现出了和其他接口相同的问题,但也说明:是比用户服务还要更基础的底层服务或接口出了问题。
那不就是API网关了嘛,突然就想通了问题所在,我们的测试环境并没有装API网关(出于成本考虑),在几天前,测试环境下的节点里每个服务都有一个对外暴露的IP,当外部的API请求发送到这个节点,再由节点里的服务根据域名去匹配服务,再由服务转发到相应的pod。
但也是出于成本考虑,运维同学将公网IP只留了一个,API请求发送过来后,由节点根据SLB(负载均衡)的轮询策略去轮询pod,而我们这个节点有四个pod,真正的后端服务其实只有一个,其他的就当成空的pod吧,那么在轮询策略下,自然而然地就出现了周期性变慢。
我画了一个草图来进行说明,但这种做法并不被官方推荐,最起码还是配置一下Ingress,我们这里只是为了图方便这么做(毕竟是测试环境),这里我们的做法是在这个节点里去掉了其他的pod,问题解决!