浅谈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 相关文章推荐
基于mysql的bbs设计(三)
Oct 09 PHP
《PHP编程最快明白》第七讲:php图片验证码与缩略图
Nov 01 PHP
php后退一页表单内容保存实现方法
Jun 17 PHP
php实现12306余票查询、价格查询示例
Apr 17 PHP
ThinkPHP模型详解
Jul 27 PHP
PHP动态地创建属性和方法, 对象的复制, 对象的比较,加载指定的文件,自动加载类文件,命名空间
May 06 PHP
PHP实现自动识别原编码并对字符串进行编码转换的方法
Jul 13 PHP
微信支付的开发流程详解
Sep 13 PHP
PHP实现统计所有字符在字符串中出现次数的方法
Oct 17 PHP
Laravel中9个不经常用的小技巧汇总
Apr 16 PHP
4种Windows系统下Laravel框架的开发环境安装及部署方法详解
Apr 06 PHP
详解Laravel服务容器的优势
May 29 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
PHP3 safe_mode 失效漏洞
2006/10/09 PHP
PHP生成唯一订单号
2015/07/05 PHP
php实现面包屑导航例子分享
2015/12/19 PHP
PHP FileSystem 文件系统常用api整理总结
2019/07/12 PHP
tp5 sum某个字段相加得到总数的例子
2019/10/18 PHP
JavaScript基础教程之alert弹出提示框实例
2014/10/16 Javascript
禁止按回车键提交表单的方法
2015/06/11 Javascript
javascript框架设计之框架分类及主要功能
2015/06/23 Javascript
asp.net中oracle 存储过程(图文)
2015/08/12 Javascript
纯JS打造网页中checkbox和radio的美化效果
2016/10/13 Javascript
js实现颜色阶梯渐变效果(Gradient算法)
2017/03/21 Javascript
利用pm2部署多个node.js项目的配置教程
2017/10/22 Javascript
基于vue配置axios的方法步骤
2017/11/09 Javascript
解决vue 更改计算属性后select选中值不更改的问题
2018/03/02 Javascript
Vue中使用vue-i18插件实现多语言切换功能
2018/04/25 Javascript
微信小程序利用swiper+css实现购物车商品删除功能
2019/03/06 Javascript
微信分享invalid signature签名错误踩过的坑
2020/04/11 Javascript
Vue.js桌面端自定义滚动条组件之美化滚动条VScroll
2020/12/01 Vue.js
[59:15]EG vs LGD 2018国际邀请赛淘汰赛BO3 第一场 8.26
2018/08/29 DOTA
用Python写冒泡排序代码
2016/04/12 Python
Python2.7下安装Scrapy框架步骤教程
2017/12/22 Python
在Python中获取操作系统的进程信息
2019/08/27 Python
基于Python的Jenkins的二次开发操作
2020/05/12 Python
Python基于pandas绘制散点图矩阵代码实例
2020/06/04 Python
div或img图片高度随宽度自适应的方法
2020/02/06 HTML / CSS
英国最大的专业户外零售商:Mountain Warehouse
2018/06/06 全球购物
澳大利亚宠物食品和用品商店:PETstock
2020/01/02 全球购物
卫校毕业生自我鉴定
2013/10/31 职场文书
职业规划书如何设计?
2014/01/09 职场文书
个人房屋转让协议书范本
2014/10/26 职场文书
大学生见习报告范文
2014/11/03 职场文书
求职自荐信怎么写
2015/03/04 职场文书
2015年城管个人工作总结
2015/05/15 职场文书
委托开发合同书(标准版)
2019/08/07 职场文书
JavaScript实现班级抽签小程序
2021/05/19 Javascript
Python获取指定日期是"星期几"的6种方法
2022/03/13 Python