浅谈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 相关文章推荐
shopex中集成的站长统计功能的代码简单分析
Aug 11 PHP
解析:php调用MsSQL存储过程使用内置RETVAL获取过程中的return值
Jul 03 PHP
ThinkPHP的Widget扩展实例
Jun 19 PHP
html静态页面调用php文件的方法
Nov 13 PHP
php文件上传简单实现方法
Jan 24 PHP
7个鲜为人知却非常实用的PHP函数
Jul 01 PHP
PHP环境中Memcache的安装和使用
Nov 05 PHP
Yii清理缓存的方法
Jan 06 PHP
thinkphp3.2.3 分页代码分享
Jul 28 PHP
PHP观察者模式示例【Laravel框架中有用到】
Jun 15 PHP
PHP defined()函数的使用图文详解
Jul 20 PHP
php微信小程序解包过程实例详解
Mar 31 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
PHP实现多图片上传类实例
2014/07/26 PHP
php计算函数执行时间的方法
2015/03/20 PHP
PHP更安全的密码加密机制Bcrypt详解
2017/06/18 PHP
详解laravel安装使用Passport(Api认证)
2018/07/27 PHP
List the UTC Time on a Computer
2007/06/11 Javascript
js判断是否为数组的函数: isArray()
2011/10/30 Javascript
js中如何把字符串转化为对象、数组示例代码
2013/07/17 Javascript
js实现文本上下来回滚动
2017/02/03 Javascript
jQuery实现鼠标滑过预览图片大图效果的方法
2017/04/26 jQuery
基于Vue的文字跑马灯组件(npm 组件包)
2017/05/24 Javascript
利用VS Code开发你的第一个AngularJS 2应用程序
2017/12/15 Javascript
vue-自定义组件传值的实例讲解
2018/09/18 Javascript
jQuery实现的3D版图片轮播示例【滑动轮播】
2019/01/18 jQuery
微信小程序使用npm包的方法步骤
2019/08/13 Javascript
JS用最简单的方法实现四舍五入
2019/08/27 Javascript
Angular之jwt令牌身份验证的实现
2020/02/14 Javascript
使用python开发vim插件及心得分享
2014/11/04 Python
Python中文字符串截取问题
2015/06/15 Python
Python 的类、继承和多态详解
2017/07/16 Python
Python中如何导入类示例详解
2019/04/17 Python
python中selenium操作下拉滚动条的几种方法汇总
2019/07/14 Python
python字符串替换re.sub()方法解析
2019/09/18 Python
Python2 与Python3的版本区别实例分析
2020/03/30 Python
python图片指定区域替换img.paste函数的使用
2020/04/09 Python
基于python 凸包问题的解决
2020/04/16 Python
如何使用scrapy中的ItemLoader提取数据
2020/09/30 Python
化石印度尼西亚在线商店:Fossil Indonesia
2019/03/11 全球购物
高中政治教学反思
2014/01/18 职场文书
建筑个人求职信范文
2014/01/25 职场文书
展会邀请函范文
2014/01/26 职场文书
会计系毕业生求职信
2014/05/28 职场文书
学生检讨书怎么写
2014/10/09 职场文书
离婚协议书范本
2015/01/26 职场文书
大班下学期个人总结
2015/02/13 职场文书
党支部审查意见
2015/06/02 职场文书
寻找成龙观后感
2015/06/12 职场文书