浅谈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程序的方法
Mar 09 PHP
PHP递归返回值时出现的问题解决办法
Feb 19 PHP
php事务处理实例详解
Jul 11 PHP
php类自动加载器实现方法
Jul 28 PHP
php实现概率性随机抽奖代码
Jan 02 PHP
使用ltrace工具跟踪PHP库函数调用的方法
Apr 25 PHP
浅谈PHP Cookie处理函数
Jun 10 PHP
PHP实现的自定义数组排序函数与排序类示例
Nov 18 PHP
PHP正则+Snoopy抓取框架实现的抓取淘宝店信誉功能实例
May 17 PHP
[原创]PHP实现SQL语句格式化功能的方法
Jul 28 PHP
PHP addAttribute()函数讲解
Feb 03 PHP
php 中self,this的区别和操作方法实例分析
Nov 04 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
thinkphp实现附件上传功能
2017/05/26 PHP
PHP对称加密算法(DES/AES)类的实现代码
2017/11/14 PHP
使用vs code编辑调试php配置的方法
2019/01/29 PHP
IE 缓存策略的BUG的解决方法
2007/07/21 Javascript
不用AJAX和IFRAME,说说真正意义上的ASP+JS无刷新技术
2008/09/25 Javascript
JQuery 选择器 xpath 语法应用
2010/05/13 Javascript
使用node.js半年来总结的 10 条经验
2014/08/18 Javascript
js简单正则验证汉字英文及下划线的方法
2016/11/28 Javascript
AngularJS实现给动态生成的元素绑定事件的方法
2016/12/14 Javascript
js实现把图片的绝对路径转为base64字符串、blob对象再上传
2016/12/29 Javascript
原生js实现简单的链式操作
2017/07/04 Javascript
在vue项目中引入highcharts图表的方法(详解)
2018/03/05 Javascript
Angular Renderer (渲染器)的具体使用
2018/05/03 Javascript
vue-cli 如何打包上线的方法示例
2018/05/08 Javascript
解决Vue中mounted钩子函数获取节点高度出错问题
2018/05/18 Javascript
JS实现点击按钮可实现编辑功能
2018/07/03 Javascript
小程序实现左滑删除功能
2018/10/30 Javascript
详解小程序设置缓存并且不覆盖原有数据
2019/04/15 Javascript
解决layui的radio属性或别的属性没显示出来的问题
2019/09/26 Javascript
使用jquery实现轮播图效果
2021/01/02 jQuery
Vue中强制组件重新渲染的正确方法
2021/01/03 Vue.js
零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers
2014/11/05 Python
解决Tensorflow安装成功,但在导入时报错的问题
2018/06/13 Python
Python之list对应元素求和的方法
2018/06/28 Python
python爬虫刷访问量 2019 7月
2019/08/01 Python
python+selenium select下拉选择框定位处理方法
2019/08/24 Python
Python 爬虫实现增加播客访问量的方法实现
2019/10/31 Python
html5 自定义播放器核心代码
2013/12/20 HTML / CSS
Jdbc数据访问技术面试题
2012/03/30 面试题
转党组织关系介绍信
2014/01/08 职场文书
自考生自我评价分享
2014/01/18 职场文书
七年级生物教学反思
2014/01/30 职场文书
节约用水的口号
2014/06/20 职场文书
团日活动总结模板
2014/06/25 职场文书
承诺书范本大全
2015/05/04 职场文书
合理化建议书范文
2015/09/14 职场文书