浅谈php处理后端&接口访问超时的解决方法


Posted in PHP onOctober 29, 2016

【HTTP访问】

一般我们访问HTTP方式很多,主要是:curl, socket, file_get_contents() 等方法。

如果碰到对方服务器一直没有响应的时候,我们就悲剧了,很容易把整个服务器搞死,所以在访问http的时候也需要考虑超时的问题。

[ CURL 访问HTTP]

CURL 是我们常用的一种比较靠谱的访问HTTP协议接口的lib库,性能高,还有一些并发支持的功能等。

CURL:

curl_setopt($ch, opt) 可以设置一些超时的设置,主要包括:

*(重要) CURLOPT_TIMEOUT 设置cURL允许执行的最长秒数。

*(重要) CURLOPT_TIMEOUT_MS 设置cURL允许执行的最长毫秒数。 (在cURL 7.16.2中被加入。从PHP 5.2.3起可使用。 )

CURLOPT_CONNECTTIMEOUT 在发起连接前等待的时间,如果设置为0,则无限等待。

CURLOPT_CONNECTTIMEOUT_MS 尝试连接等待的时间,以毫秒为单位。如果设置为0,则无限等待。  在cURL 7.16.2中被加入。从PHP 5.2.3开始可用。

CURLOPT_DNS_CACHE_TIMEOUT 设置在内存中保存DNS信息的时间,默认为120秒。

curl普通秒级超时:

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,$url);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_TIMEOUT, 60);   //只需要设置一个秒的数量就可以

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

curl_setopt($ch, CURLOPT_USERAGENT, $defined_vars['HTTP_USER_AGENT']);

curl普通秒级超时使用:

curl_setopt($ch, CURLOPT_TIMEOUT, 60);

curl如果需要进行毫秒超时,需要增加:

curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);

或者是:

curl_setopt ( $ch,  CURLOPT_NOSIGNAL, true); 是可以支持毫秒级别超时设置的

curl一个毫秒级超时的例子:

<?php
if (!isset($_GET['foo'])) {
    
// Client
    $ch = curl_init('http://example.com/');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1);  
//注意,毫秒超时一定要设置这个
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200); 
//超时毫秒,cURL 7.16.2中被加入。从PHP 5.2.3起可使用
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);
 
    if ($curl_errno > 0) {
        echo "cURL Error ($curl_errno): $curl_error\n";
    } else {
        echo "Data received: $data\n";
    }
} else {
    
// Server
    sleep(10);
    echo "Done.";
}
?>

其他一些技巧:

1. 按照经验总结是:cURL 版本 >= libcurl/7.21.0 版本,毫秒级超时是一定生效的,切记。

2. curl_multi的毫秒级超时也有问题。。单次访问是支持ms级超时的,curl_multi并行调多个会不准

[流处理方式访问HTTP]

除了curl,我们还经常自己使用fsockopen、或者是file操作函数来进行HTTP协议的处理,所以,我们对这块的超时处理也是必须的。

一般连接超时可以直接设置,但是流读取超时需要单独处理。

自己写代码处理:

$tmCurrent = gettimeofday();
$intUSGone = ($tmCurrent['sec'] - $tmStart['sec']) * 1000000
+ ($tmCurrent['usec'] - $tmStart['usec']);
if ($intUSGone > $this->_intReadTimeoutUS) {
return false;
}

或者使用内置流处理函数 stream_set_timeout() 和 stream_get_meta_data() 处理:

<?php 
// Timeout in seconds 
$timeout = 5; 
$fp = fsockopen("example.com", 80, $errno, $errstr, $timeout); 
if ($fp) { 
    fwrite($fp, "GET / HTTP/1.0\r\n"); 
    fwrite($fp, "Host: example.com\r\n"); 
    fwrite($fp, "Connection: Close\r\n\r\n"); 
    stream_set_blocking($fp, true);  
//重要,设置为非阻塞模式
    stream_set_timeout($fp,$timeout);  
//设置超时
    $info = stream_get_meta_data($fp); 
    while ((!feof($fp)) && (!$info['timed_out'])) { 
        $data .= fgets($fp, 4096); 
        $info = stream_get_meta_data($fp); 
        ob_flush; 
        flush(); 
    } 
    if ($info['timed_out']) { 
        echo "Connection Timed Out!"; 
    } else { 
        echo $data; 
    } 
}

file_get_contents 超时:

<?php
$timeout = array(
  'http' => array(
    'timeout' => 5 
//设置一个超时时间,单位为秒
  )
);
$ctx = stream_context_create($timeout);
$text = file_get_contents("http://example.com/", 0, $ctx);
?>

fopen 超时:

<?php
$timeout = array(
  'http' => array(
    'timeout' => 5 
//设置一个超时时间,单位为秒
  )
);
$ctx = stream_context_create($timeout);
if ($fp = fopen("http://example.com/", "r", false, $ctx)) {
 while( $c = fread($fp, 8192)) {
  echo $c;
 }
 fclose($fp);
}
?>

以上就是小编为大家带来的浅谈php处理后端&接口访问超时的解决方法全部内容了,希望大家多多支持三水点靠木~

PHP 相关文章推荐
有关 PHP 和 MySQL 时区的一点总结
Mar 26 PHP
PHP开发过程中常用函数收藏
Dec 14 PHP
php 获取本机外网/公网IP的代码
May 09 PHP
11个PHP 分页脚本推荐
Aug 15 PHP
PHP filter_var() 函数 Filter 函数
Apr 25 PHP
PHP-Fcgi下PHP的执行时间设置方法
Aug 02 PHP
如何取得中文字符串中出现次数最多的子串
Aug 08 PHP
PHP以mysqli方式连接类完整代码实例
Jul 15 PHP
php比较相似字符串的方法
Jun 05 PHP
php实现的验证码文件类实例
Jun 18 PHP
PHP文件操作之获取目录下文件与计算相对路径的方法
Jan 08 PHP
yii2.0整合阿里云oss删除单个文件的方法
Sep 19 PHP
完美解决phpexcel导出到xls文件出现乱码的问题
Oct 29 #PHP
php通过PHPExcel导入Excel表格到MySQL数据库的简单实例
Oct 29 #PHP
浅谈PHP定义命令空间的几个注意点(推荐)
Oct 29 #PHP
php+mongodb判断坐标是否在指定多边形区域内的实例
Oct 28 #PHP
PHP创建多级目录的两种方法
Oct 28 #PHP
PHP查询大量数据内存耗尽问题的解决方法
Oct 28 #PHP
遍历指定目录,并存储目录内所有文件属性信息的php代码
Oct 28 #PHP
You might like
短波问题解答
2021/02/28 无线电
discuz Passport 通行证 整合笔记
2008/06/30 PHP
简单PHP上传图片、删除图片实现代码
2010/05/12 PHP
PHP中实现生成静态文件的方法缓解服务器压力
2014/01/07 PHP
PHP内置加密函数详解
2016/11/20 PHP
php 可变函数使用小结
2018/06/12 PHP
Javascript写了一个清除“logo1_.exe”的杀毒工具(可扫描目录)
2007/02/09 Javascript
js下通过prototype扩展实现indexOf的代码
2010/12/08 Javascript
js判断iframe内的网页是否滚动到底部触发事件
2014/03/18 Javascript
Javascript前端UI框架Kit使用指南之kitjs的对话框组件
2014/11/28 Javascript
jQuery取消特定的click事件
2016/02/29 Javascript
AngularJS国际化详解及示例代码
2016/08/18 Javascript
JavaScript实现图像模糊化的方法实例
2017/01/15 Javascript
浅析Vue.js中v-bind v-model的使用和区别
2018/12/04 Javascript
微信小程序实现多个按钮的颜色状态转换
2019/02/15 Javascript
countUp.js实现数字滚动效果
2019/10/18 Javascript
浅谈vuex的基本用法和mapaction传值问题
2019/11/08 Javascript
vue-cli设置publicPath小记
2020/04/14 Javascript
Python MD5加密实例详解
2017/08/02 Python
Python+request+unittest实现接口测试框架集成实例
2018/03/16 Python
spark: RDD与DataFrame之间的相互转换方法
2018/06/07 Python
Python实现去除列表中重复元素的方法总结【7种方法】
2019/02/16 Python
python使用tomorrow实现多线程的例子
2019/07/20 Python
详解Django配置JWT认证方式
2020/05/09 Python
常用的10个Python实用小技巧
2020/08/10 Python
LookFantastic丹麦:英国美容护肤精品在线商城
2016/08/18 全球购物
安全标准化汇报材料
2014/02/03 职场文书
质检部经理岗位职责
2014/02/19 职场文书
中职生求职信
2014/07/01 职场文书
2014年学校国庆主题活动方案
2014/09/16 职场文书
党员群众路线教育实践活动学习笔记
2014/11/05 职场文书
初中家长评语大全
2014/12/26 职场文书
大学生助学金感谢信
2015/01/21 职场文书
土地租赁协议书
2015/01/29 职场文书
获奖感言一句话
2015/07/31 职场文书
浅谈Python数学建模之整数规划
2021/06/23 Python