Discuz贴子打开缓慢的原因分析

[文章作者:磨延城 转载请注明原文出处: https://mo2g.com/view/139/ ]
前一阵子,就感觉到基于Discuz搭建的会员互动社区打开贴子异常缓慢(响应时间1到10几秒不等),别的页面却是正常的(响应时间200ms左右).浏览一个贴子需要等待好几秒,我自己使用起来都挺上火的,更何况其他活跃的会员?今天就抽出时间,分析导致Discuz贴子打开缓慢的原因.
前一阵子,就感觉到基于Discuz搭建的会员互动社区打开贴子异常缓慢(响应时间1到10几秒不等),别的页面却是正常的(响应时间200ms左右)。浏览一个贴子需要等待好几秒,我自己使用起来都挺上火的,更何况其他活跃的会员?今天就抽出时间,分析导致Discuz贴子打开缓慢的原因。
除了PHP守护进程,正常情况下PHP程序的运行时间不会太慢,基本都是以ms为单位的。如果出现秒级的响应,很多时候都是sql语句不合理导致的。
然而我在MariaDB的慢日志中并没有找到相关的记录,看来只能老老实实的分析Xdebug日志,看看Discuz究竟慢在哪了。
Xdebug日志中显示,/source/module/forum/forum_viewthread.php文件中第284行代码运行了长达10,900ms!
list($seccodecheck, $secqaacheck) = seccheck('post', 'reply');再往下分析,就找到了/source/class/helper/helper_seccheck.php文件第300行代码$return[0] = captcha::isneed();运行耗时10,571ms,代码如下:
public static function seccheck($rule, $param = array()) {
        global $_G;
        if($_G['uid'] && !checkperm('seccode')) {
            return array();
        }
        if(method_exists('helper_seccheck', 'rule_'.$rule)) {
            $return = call_user_func(array('helper_seccheck', 'rule_'.$rule), $param);
            if(!isset($_G['cookie']['seccloud'])) {
                if($_G['setting']['seccodedata']['cloudip'] && !$return[0]) {
                    $return[0] = captcha::isneed();
                    if($return[0]) {
                        dsetcookie('seccloud', 1);
                    }
                }
            } else {
                $return[0] = true;
            }
            return $return;
        } else {
            return array();
        }
    }很明显,这条语句是根据条件来判断是否运行的,当看到$_G['setting']['seccodedata']['cloudip']的时候,我突然想起了,好像以前在后台开启了某些“云”功能。
果然,找到Discuz后台的 防水墙->验证码->云端IP库检测,然后选择否,提交保存。现在重新打开贴子,响应时间就恢复到了200ms左右。

云端IP库检测:启用后当用户的登录 IP 在云端可疑 IP 库中时,用户的注册、登录、发表等操作会自动启用验证码。Discuz官方是这么描述这个功能的。
有兴趣的朋友,可以继续往下看,我的跟踪记录。
其实captcha::isneed();就是调用了/source/function/function_filesock.php文件中定义的_dfsockopen()函数,从某个API获取数据。
因为68行代码运行了10,559ms,所以我为了获取导致响应缓慢的API地址,就在68行后添加了一些判断代码
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
$data = curl_exec($ch);
$time = time();
if( $time - $_SERVER['REQUEST']  > 5) {
    echo $scheme.'://'.($ip ? $ip : $host).($port ? ':'.$port : '').$path;
}运行后,输出类似如下
http://api.discuz.qq.com:80/captcha/isNeed?appId=321122415&clientIp=10.0.0.87&dzVersion=X3.2&openId=44A2245222FE28B91D0D0B969312686E&sId=34707439&uid=2279&ver=1.0&ts=1416967960&sig=eb6a3333d37cc7f556873841732d8d18
所以贴子响应慢,就是因为这个提供IP检测的API接口性能太差导致的。
上一篇:并发编程,简单理解就GO了

我来说两句: