浅谈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 相关文章推荐
解析posix与perl标准的正则表达式区别
Jun 17 PHP
两种设置php载入页面时编码的方法
Jul 29 PHP
对PHP新手的一些建议(PHP学习经验总结)
Aug 20 PHP
帝国cms常用标签汇总
Jul 06 PHP
PHP实现的通过参数生成MYSQL语句类完整实例
Apr 11 PHP
php blowfish加密解密算法
Jul 02 PHP
PHP实现表单提交时去除斜杠的方法
Dec 26 PHP
Yii框架通过请求组件处理get,post请求的方法分析
Sep 03 PHP
Laravel Eloquent ORM 多条件查询的例子
Oct 10 PHP
Thinkphp5.0框架的Db操作实例分析【连接、增删改查、链式操作等】
Oct 11 PHP
TP3.2框架分页相关实现方法分析
Jun 03 PHP
详解使用php-cs-fixer格式化代码
Sep 16 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 pcntl_fork和pcntl_fork 的用法
2009/04/13 PHP
php $_SERVER[&quot;REQUEST_URI&quot;]获取值的通用解决方法
2010/06/21 PHP
ThinkPHP自动验证失败的解决方法
2011/06/09 PHP
PHP使用数组实现队列
2012/02/05 PHP
Laravel timestamps 设置为unix时间戳的方法
2019/10/11 PHP
javascript之AJAX框架使用说明
2010/04/24 Javascript
突发奇想的一个jquery插件
2010/11/19 Javascript
JavaScript实现跨浏览器的添加及删除事件绑定函数实例
2015/08/04 Javascript
JS实现自动定时切换的简洁网页选项卡效果
2015/10/13 Javascript
JavaScript SweetAlert插件实现超酷消息警告框
2016/01/28 Javascript
JSON字符串转换JSONObject和JSONArray的方法
2016/06/03 Javascript
JS原型链 详解及示例代码
2016/09/06 Javascript
微信公众号菜单配置微信小程序实例详解
2017/03/31 Javascript
vue中的非父子间的通讯问题简单的实例代码
2017/07/19 Javascript
浅谈vue自定义全局组件并通过全局方法 Vue.use() 使用该组件
2017/12/07 Javascript
AngularJS创建一个上传照片的指令实例代码
2018/02/24 Javascript
在vue项目中使用sass语法问题
2019/07/18 Javascript
通过angular CDK实现页面元素拖放的步骤详解
2020/07/01 Javascript
详解ES6中class的实现原理
2020/10/03 Javascript
Python中对列表排序实例
2015/01/04 Python
Python中的迭代器与生成器高级用法解析
2016/06/28 Python
动态规划之矩阵连乘问题Python实现方法
2017/11/27 Python
Python面向对象基础入门之编码细节与注意事项
2018/12/11 Python
Python操作rabbitMQ的示例代码
2019/03/19 Python
python中的subprocess.Popen()使用详解
2019/12/25 Python
django实现后台显示媒体文件
2020/04/07 Python
jupyter lab文件导出/下载方式
2020/04/22 Python
CSS3实现圆角、阴影、透明效果并兼容各大浏览器
2014/08/08 HTML / CSS
CSS3制作hover下划线动画
2017/03/27 HTML / CSS
CSS3 实现发光边框特效
2020/11/11 HTML / CSS
SEPHORA丝芙兰捷克官网:购买香水、化妆品和护肤品
2018/11/26 全球购物
俞敏洪励志演讲稿
2014/04/29 职场文书
酒店工程部的岗位职责汇总大全
2019/10/23 职场文书
Java基于字符界面的简易收银台
2021/06/26 Java/Android
解决Jenkins集成SonarQube遇到的报错问题
2021/07/15 Java/Android
Ruby序列化和持久化存储 Marshal和Pstore介绍
2022/04/18 Ruby