k8s环境下由predis初始化连接缓慢引起的一次问题排查
背景最近业务上在做同城双中心。原本的机房使用的是swarm集群,新机房使用的是k8s集群。业务迁移到新机房的主要工作集中在:库、redis、es等底层服务的迁移;redis由原来的vip单点模式,切换为redis-cluster,由于phpredis1官方版本暂时不支持带auth的cluster模式,所以选择了predis链接redis;将之前的swarm集群,迁移到k8s集群;现象...
背景
最近业务上在做同城双中心。原本的机房使用的是swarm集群,新机房使用的是k8s集群。业务迁移到新机房的主要工作集中在:
- 库、redis、es等底层服务的迁移;
- redis由原来的vip单点模式,切换为redis-cluster,由于phpredis1官方版本暂时不支持带auth的cluster模式,所以选择了predis链接redis;
- 将之前的swarm集群,迁移到k8s集群;
现象
部署完成之后发现,首页加载很慢,打开network,发现ajax请求普遍比老机房慢2-3秒。业务已经上了redis缓存,仍是如此。
排查思路
浏览器并发数
首先考虑浏览器同域下请求并发数问题,由于浏览器对于同域的并发数有限制,当同域的请求过多是,后续的请求会出现stock情况。通过network中的waterfall基本排除了该种可能:
服务端profiling
基本排除了客户端问题之后,开始服务端profiling(性能剖析)。项目使用的是php的CodeIgniter框架,之前自己动手写过一个profiling的框架。所以引入框架后开始分析,以下是首页众多ajax请求中的一个:
然而单独调试这个接口的时候,结果却是这样:
对比两个结果,可以看出几点:
- 多处耗时较长,包括初始化框架、sql查询和redis初始化;
- 单独请求接口时,比在首页众多请求中请求接口,性能有很大提升;
此时,我进入了一个误区。我尝试针对各个耗时的操作逐一排查。于是就开始从初始化redis(因为我觉得这里最蹊跷)开始,开始调试predis源码,各种优化连接参数。然而折腾了很久,只是发现调试的过程中一切执行都正常,但是就随着代码执行,耗时出奇的高。
直到,我意识到一个问题:是不是并发越高,相应越慢?
并发情况下资源等待
我依次在本机使用ab,测试了100次请求下,不同并发下接口的响应情况:
-
并发1的情况:
-
并发10的情况:
紧接着,我又测试了在有无压测的情况下,在浏览器上profiling单个接口,结果果然如我所料,在压测情况下,接口耗时慢很多。
其实到这里,原因基本可以猜到了,就是k8s中container的资源限制。由于资源limit配置不当(cpu设置limit:200m),导致随着并发请求的处理,很多操作在等待cpu资源,所以最终表现的情况就是,并发越大,请求越慢。
在我移除cpu限制之后,请求基本正常。
结论
这个问题的排查过程,给了一类接口请求慢问题的排查思路:当发现程序运行基本正常,而大部分整体耗时较长的情况下,可以考虑是否是机器/操作系统的资源限制造成的。
就是php的redis扩展,以前的名字叫phpredis,最近好像更名为redis了,估计是为了防止歧义吧,链接在:http://pecl.php.net/package/redis ↩︎
更多推荐
所有评论(0)