php实现curl重试机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php实现curl重试机制相关的知识,希望对你有一定的参考价值。

Failed connect to www.xxx.com:80; Connection timed out

做了一下几点尝试:

  1. 抓包分析,也没有分析出个所以然。

  2. 以为是尝试连接的等待时间太小了,于是通过调整增大CURLOPT_CONNECTTIMEOUT参数,发现也无济于事。

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); //在尝试连接时等待的秒数

重试机制 由于之前的工作经历中,经常遇到各种偶发无法连接服务的情况如mysql等等,都是通过增加重试连接的方式解决的。

于是根据过往经验,干脆写了个curl请求重试机制,轻松解决了问题。特此分享一下:

    $ch = curl_init($url);
    //curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
    //curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-type:application/json;charset=utf-8"));
    curl_setopt($ch, CURLOPT_TIMEOUT, 1800);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); //在尝试连接时等待的秒数

    if (!empty($options)) 
        curl_setopt_array($ch, $options);
    

    $data = curl_exec($ch);
    $curlErrno = curl_errno($ch);


    //curl增加重试机制
    $retryTimes=0;
    $maxRetryTimes=10;
    if($curlErrno)
    
        for($retryTimes=0;$retryTimes<$maxRetryTimes;$retryTimes++)
        
            $retryTimes++;

            $data = curl_exec($ch);
            $curlErrno = curl_errno($ch);
            if(!$curlErrno)
            
                error_log("CURL重试$retryTimes次后成功".addslashes(json_encode(curl_getinfo($ch), JSON_UNESCAPED_UNICODE)));
                break;
            
            sleep(1);
        
    

	//错误监控告警
    if ($curlErrno) 
        //curl请求异常,往上层抛出异常信息
        $errorMessage = CURL请求出错了!;
        $errorMessage .= 【地址】: . $url . 。;
        $errorMessage .= 【方法】: GET。;
        $errorMessage .= 【参数】: . addslashes(json_encode($postdata, JSON_UNESCAPED_UNICODE)) . 。;
        $errorMessage .= 【错误信息】: . curl_error($ch) . "($curlErrno).";
        $errorMessage .= 【CURL_INFO】: . addslashes(json_encode(curl_getinfo($ch), JSON_UNESCAPED_UNICODE)) . 。;

        #增加调用信息
        $backtrace = "";
        $backtraceList = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
        foreach ($backtraceList as $v) 
            $fileName = $v[file] ?? ;
            $lineNo = $v[line] ?? 0;
            $className = $v[class] ?? ;
            $functionName = $v[function] ?? ;
            $backtrace .= "$fileName - $lineNo - $className::$functionName()" . 。;
        
        $errorMessage .= 【调用】: . $backtrace;
        $errorMessage .= 【重试次数】: . $retryTimes;
        $errorMessage .= 【处理服务器】: . gethostname();


        $errorMessage = str_replace(array("\\r\\n", "\\r", "\\n", "   "), , $errorMessage);
	
	  //告警通知
        qywx_robot_error_notice($errorMessage);
        unset($errorMessage, $backtrace, $backtraceList);

        //throw new \\Exception(curl_error($ch),$errorNo);
        //return false;
    

    curl_close($ch);

    return $data;

以上是关于php实现curl重试机制的主要内容,如果未能解决你的问题,请参考以下文章

一个带重试次数的curl 函数

Spring Cloud Feign 重试机制-如何实现请求重试

Azure 存储队列 - 重试机制实现

利用feign的重试机制刷新过期的请求Token

rabbitmq~消息失败后重试达到 TTL放到死信队列(事务型消息补偿机制)

spring-retry重试机制使用