入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

高并发下session_start超时导致的访问失败问题

创建时间:2016-10-19 投稿人: 浏览次数:2410

    在开发微信平台功能时,微信菜单设置为链接时,如:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid."&redirect_uri=http://xxx.com/xxx&response_type=code&scope=snsapi_base&state=1234#wechat_redirect

链接被附加code后,跳转回redirect_uri。此时页面需要做微信远程code验证,获取openid,从而自动登陆。

如下代码所示:

$code  =$_GET["code"];
while(true){
    //获取openid
    $url_op="https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecret."&code=".$code
            ."&grant_type=authorization_code";//将code参数整合到此链接中
    $ope=json_decode(curlGet($url_op),true);
    if( $ope["errcode"]>0 || empty($ope["openid"]) ){    
        continue;    
    }else{
        $openid=$ope["openid"];
        break;
    }
}
function curlGet($url){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)");
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $temp = curl_exec($ch);
    curl_close($ch);
    return $temp;
}


    当访问量小时, 似乎正常。然而,当访问量上升时,便出现了nginx服务器的502报错,curlGet取不到值,结果使程序进入死循环。

开始以为是服务器的问题,提高了php-fpm的进程数和linux内核打开文件数量,却发现问题依旧。

于是将openid存于session,不在频繁去获取,似乎可以缓解这种症状。


if( empty($_SESSION["openid"]) ){
    //获取openid
    $url_op="https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecret."&code=".$code
           ."&grant_type=authorization_code";//将code参数整合到此链接中
    $ope=json_decode(curlGet($url_op),true);
    if( $ope["errcode"]>0 || empty($ope["openid"]) ){
        echo "<script>";
        echo "window.location.replace("https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid
            ."&redirect_uri=http://xxx.com/xxx&response_type=code&scope=snsapi_base&state=1234#wechat_redirect")";
        echo "</script>"; 
        exit;
    }
    $openid=$ope["openid"];
    $_SESSION["openid"]=$openid;
}else{
    $openid=$_SESSION["openid"];
}

----------------------------------问题终结线------------------------------------------

后期查询nginx慢日志时,发现大量session_start()记录,继续追踪原因。

网站使用了Yar远程调用框架,后来将接口服务器端并入了thinkPHP的控制器中, 远程调用时会自动启动session。

这样, 如果一个页面未执行完毕,session会被锁死, 后面的接口调用一直处于阻塞状态。结果就是网站好慢,页面打不开了。


最后的解决方案:在接口的入口处关闭session.

session_write_close();

声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。