浅谈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 相关文章推荐
ezSQL PHP数据库操作类库
May 16 PHP
PHP XML操作的各种方法解析(比较详细)
Jun 17 PHP
PHP 中检查或过滤IP地址的实现代码
Nov 27 PHP
Linux环境下搭建php开发环境的操作步骤
Jun 17 PHP
PHP用身份证号获取星座和生肖的方法
Nov 07 PHP
PHP语法自动检查的Vim插件
Aug 11 PHP
UPUPW 更新 64 位 Apache 系列 PHP 7.0 正式版
Dec 08 PHP
基于PHP实现等比压缩图片大小
Mar 04 PHP
PHP实现的简单异常处理类示例
May 04 PHP
PHP基于GD库实现的生成图片缩略图函数示例
Jul 05 PHP
php ajax confirm 删除实例详解
Mar 06 PHP
thinkPHP5使用Rabc实现权限管理
Aug 28 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搜索时首页分页和搜索页保持条件分页的方法
2014/12/05 PHP
PHP针对redis常用操作实例详解
2019/08/17 PHP
Javascript操纵Cookie实现购物车程序
2007/02/15 Javascript
jQuery弹层插件jquery.fancybox.js用法实例
2016/01/22 Javascript
NodeJs——入门必看攻略
2016/06/27 NodeJs
正则表达式替换html元素属性的方法
2016/11/26 Javascript
vue日期组件 支持vue1.0和2.0
2017/01/09 Javascript
Java与JavaScript中判断两字符串是否相等的区别
2017/03/13 Javascript
Vue.js 60分钟快速入门教程
2017/03/28 Javascript
简单谈谈关于 npm 5.0 的新坑
2017/06/08 Javascript
jQuery 实现双击编辑表格功能
2017/06/19 jQuery
VueRouter导航守卫用法详解
2017/12/25 Javascript
vue slot 在子组件中显示父组件传递的模板
2018/03/02 Javascript
linux系统使用python监控apache服务器进程脚本分享
2014/01/15 Python
python实现倒计时的示例
2014/02/14 Python
Python查看多台服务器进程的脚本分享
2014/06/11 Python
Python实现子类调用父类的方法
2014/11/10 Python
python文件写入write()的操作
2019/05/14 Python
用python求一个数组的和与平均值的实现方法
2019/06/29 Python
python爬虫神器Pyppeteer入门及使用
2019/07/13 Python
将pytorch转成longtensor的简单方法
2020/02/18 Python
基于python纯函数实现井字棋游戏
2020/05/27 Python
python如何提升爬虫效率
2020/09/27 Python
怎样实现H5+CSS3手指滑动切换图片的示例代码
2019/05/05 HTML / CSS
html5利用canvas实现颜色容差抠图功能
2019/12/23 HTML / CSS
《走一步再走一步》教学反思
2014/02/15 职场文书
党员干部民主生活会议批评与自我批评材料
2014/09/20 职场文书
小学生通知书评语
2014/12/31 职场文书
大学生个人年度总结范文
2015/02/15 职场文书
证婚人致辞精选
2015/07/28 职场文书
2016高中社会实践心得体会范文
2016/01/14 职场文书
Python还能这么玩之用Python修改了班花的开机密码
2021/06/04 Python
MySQL中连接查询和子查询的问题
2021/09/04 MySQL
Python进程间的通信之语法学习
2022/04/11 Python
winserver2019安装软件一直卡在应用程序正在为首次使用做准备
2022/06/10 Servers
css3手动实现pc端横向滚动
2022/06/21 HTML / CSS