CDB 的控制台的超时雪崩问题

作者:蒋鹏

问题结论

由于web接入层在调用后方逻辑层接口,使用的调用方法concurrent_curl没有设置超时(默认200s),会由于后台单点故障,导致调用没返回而一直等待,引发雪崩,使web接入层的php也被占满未释放空闲,导致所有cdb的web控制台服务都不可访问。

问题场景

近日,测试同学 R 反馈整个测试环境,CDB的相关页面都不能访问了,实在找不到问题原因。表现如下:

1、三套cdb的测试环境都拉取不出页面,页面一直弹登录框,登录态校验失败。

2、做账户的登录态、用户信息校验等,校验接口大概率超时。

3、浏览器抓包,发现许多cgi请求一直处于pending状态。

问题分析过程

1、3套环境都这样,首先考虑是机器底层网络有问题?

-----通过与其他FT的测试环境运行情况,发现就只有CDB的环境这样,排除一种可能。

2、页面一直弹登录框,首先需要定位登录校验失败问题,难道是官网组件运行异常?

-----同样查看其他ft的环境,是否有登录的问题存在,发现不存在问题。那么排查CDB的环境是否连接鉴权的地址不正确?环境不通?

首先解决鉴权失败问题:

[2017-07-26 09:37:37,139][21563][ERROR][/data/release/websites/cdb.qcloud.com/module/helpers/common_helper.php:http_curl:162][curl_e
xec error|url=http://cgateway.qcloud.itd.com/interfaces/interface.php|request='{"regionId":"1","version":1,"componentName":"MC_CDB",
"eventId":1570119608,"seqId":"205b990c-4755-5fc4-5f9b-5977f2a2b680","spanId":"http:\\/\\/cdb.qcloud.com\\/cdb->http:\\/\\/cdb.qcloud
.com\\/cdb\\/getlist;1","interface":{"interfaceName":"qcloud.Qconfig.batchGetWhiteList","para":{"typeList":["CDB_CAM_USER_LIST"],"wh
iteList":["3227991405"]},"common":{"regionId":"1","appId":0,"uin":0,"ownerUin":0}}}'|timeout=6|error=Operation timed out after 6000
milliseconds with 0 bytes received]

*通过日志发现,鉴权相关接口出现超时, timeout=6|error=Operation timed out after 6000milliseconds with 0 bytes received

提取请求单独curl测试,发现请求一直不返回,那么我们往后端继续定位,发现被请求组件cgw的日志展示,鉴权的接口是正常处理,没有失败的情况。

mc:我发起请求正常 ——————————cgw:我处理请求也是正常,内部没有超时

这时候,问题的关键点就在mc到cgw之间了,他们直接的距离就是nginx+php,由于经验nginx的转发能力是很强大的,这里考虑php慢,结合定位cgw的日志,cgw逻辑耗时正常,这里考虑php的进程占用满了。

1、看php进程数量

2、查看/usr/local/services/php-fpm-5.6.30/etc/php-fpm.conf中max_children

3、该问题场景,两者数量相等,于是考虑php的进程占满。

尝试解决php问题,重启下php,刷新页面,出现下面情况:

页面可以正常刷新出来,多次刷新后,又陷入了大量超时失败,浏览器请求pending。

判断php重启不是根本办法,要定位出具体的是什么导致了线程急速耗费完。

于是我就去看ngnix 的请求处理日志了(要看nginx所有的请求日志):

 /usr/local/services/tnginx_1_0_0-1.0/log]# tail -f * -n 0

通过tail发现打印内容很久才会有一条,这里我们要知道一点:

nginx是在php处理返回后,返回内容给请求端时候才会打印请求的日志。

于是修改nginx的日志打印规则,看看请求具体耗用时间,设置规则参考nginx日志规则配置。通过在access_log中查询‘request_time 2’、‘request_time 1’等看看超过1s的请求处理。得到了如下的情况:

有请求耗时达到了200s,浏览器的请求也在200s后返回,这里需要从代码角度考虑,有哪些场景可能导致耗时很长:

1、代码中可能存在大的循环。

2、代码中出现阻塞,一直等待。

通过在代码中打桩,插入return语句,发现在如下的concurrent_curl函数前后打桩,浏览器分别会正常返回或者一直pending,所以考虑是这个函数的问题。

通过代码调用实现中,没有看到关于time_out的设置,而使用了默认的超时时间,并与研发对齐,的确是没有超时设置。初步定位到由于这里没有超时,而有一些php逻辑一直在等待后台返回,导致了web接入层机器的php进程耗用完。

这里又有问题了,什么情况导致concurrent_curl一直等待未返回,用同样上面方法了解,有一台逻辑层cgw组件机器,php也耗用满了,导致web接入层请求逻辑层cgw一直waiting,nginx没有返回。这样由于一台机器的问题,而影响到web接入层,从而扩散CDB控制台所有用户都不能使用。

补充问题1:nginx为何没有返回?

location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SERVER_NAME $http_host;
fastcgi_ignore_client_abort on;
fastcgi_connect_timeout 600s;
fastcgi_send_timeout 600s;
fastcgi_read_timeout 600s;
}

nginx配置代理转发,cgi超时时间是10分钟,大于我们concurrent_curl的200s而没有出错。

补充问题2:在定位过程中,多次点击列表拉取按钮,每次会触发两个cgi访问,其中一个会pending,当点击到第六次后,两个cgi都会pending,场景必现。

第一次刷新
request A   返回200
request B   pengding
第二次刷新
request A   返回200
request B   pengding
第三次刷新
request A   返回200
request B   pengding
第四次刷新
request A   返回200
request B   pengding
第五次刷新
request A   返回200
request B   pengding
第六次刷新
request A   pengding
request B   pengding

这个主要是浏览器本身限制了单域名的连接个数,定位环境使用chrome,限制个数为6个连接。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张小波的专栏

CDN 学习中的一点小思考

近段时间学习CDN,同时也在尝试着做一些项目,熟悉腾讯云的基本产品知识,在学习的过程中,也串联和扩展思考了一下,例如想搞清楚一些很容易犯迷糊的问题,例如回源ho...

6441
来自专栏大壮

iOS 网络常识

1425
来自专栏祝威廉

StreamingPro 基于Spark 2.1.1版本 支持Spark Streaming

很多人吐槽StreamingPro构建实在太麻烦了。看源码都难。然后花了一天时间做了比较大重构,这次只依赖于ServiceFramework项目。具体构建方式如...

642
来自专栏王磊的博客

聊聊excel生成图片的几种方式

目录     I:需求。    II:实现思路。     III:实现方式。     IV:优缺点分析。     V:结论。     VI:wps安装与配置。 ...

33711
来自专栏阿杜的世界

Java Web技术经验总结(十一)

672
来自专栏PHP技术

什么是CGI、FastCGI、PHP-CGI、PHP-FPM、Spawn-FCGI?

什么是CGI CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种...

3029
来自专栏蓝天

thrift使用小记

    Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL...

721
来自专栏刘望舒

Android系统架构与系统源码目录

前言 技术博客终于可以恢复正常的更新速度了,原因是我编写的进阶书籍的初稿已经完成,窃以为它将会是Android应用书籍中最有深度的一本,可以说是《Android...

2038
来自专栏恰同学骚年

.NET Core微服务之基于EasyNetQ使用RabbitMQ消息队列

  “消息”是在两台计算机间传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象。消息被发送到队列中,“消息队列”是在消息的传...

1525
来自专栏WindCoder

在Python中用Celery安排管理后台工作流

还好这次没来ios的,刚接触了下dubbo的分布实现,没想到就被推了一篇python的分布实现技术,分享给大家吧,顺便自己也了解下。原文如下:

641

扫码关注云+社区