浅谈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 is_dir() 判断给定文件名是否是一个目录
May 10 PHP
php中++i 与 i++ 的区别
Aug 08 PHP
php开发文档 会员收费1期
Aug 14 PHP
php错误级别的设置方法
Jun 17 PHP
PHP和MySql中32位和64位的整形范围是多少
Feb 18 PHP
Zend Framework教程之请求对象的封装Zend_Controller_Request实例详解
Mar 07 PHP
ThinkPHP框架安全实现分析
Mar 14 PHP
PHP用FTP类上传文件视频等的简单实现方法
Sep 23 PHP
PHP处理bmp格式图片的方法分析
Jul 04 PHP
PHP编程快速实现数组去重的方法详解
Jul 22 PHP
PHP实现的数组和XML文件相互转换功能示例
Mar 15 PHP
laravel框架与其他框架的详细对比
Oct 23 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
解析coreseek for sphinx的使用
2013/06/21 PHP
php中的观察者模式简单实例
2015/01/20 PHP
Thinkphp关闭缓存的方法
2015/06/26 PHP
PHP基于自增数据如何生成不重复的随机数示例
2017/05/19 PHP
PHP实现基本留言板功能原理与步骤详解
2020/03/26 PHP
thinkphp5 框架结合plupload实现图片批量上传功能示例
2020/04/04 PHP
基于jquery的跨域调用文件
2010/11/19 Javascript
IE的有条件注释判定IE版本详解(附实例代码)
2012/01/04 Javascript
js有序数组的连接问题
2013/10/01 Javascript
Javascript call和apply区别及使用方法
2013/11/14 Javascript
jQuery实现下拉框左右选择的简单实例
2014/02/22 Javascript
javascript 对象数组根据对象object key的值排序
2015/03/09 Javascript
BOM系列第一篇之定时器setTimeout和setInterval
2016/08/17 Javascript
seajs学习教程之基础篇
2016/10/20 Javascript
ionic cordova一次上传多张图片(类似input file提交表单)的实现方法
2016/12/16 Javascript
jQuery基于ajax实现页面加载后检查用户登录状态的方法
2017/02/10 Javascript
基于element-ui组件手动实现单选和上传功能
2018/12/06 Javascript
vue.js实现的幻灯片功能示例
2019/01/18 Javascript
[45:59]EG vs OG 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
读取本地json文件,解析json(实例讲解)
2017/12/06 Python
Python Flask前后端Ajax交互的方法示例
2018/07/31 Python
python+pyqt5实现图片批量缩放工具
2019/03/18 Python
django的ORM操作 增加和查询
2019/07/26 Python
docker-py 用Python调用Docker接口的方法
2019/08/30 Python
完美解决pycharm导入自己写的py文件爆红问题
2020/02/12 Python
python如何遍历指定路径下所有文件(按按照时间区间检索)
2020/09/14 Python
利用HTML5绘制点线面组成的3D图形的示例
2015/05/12 HTML / CSS
详解Canvas 跨域脱坑实践
2018/11/07 HTML / CSS
智能电子秤、手表和健康监测仪:Withings(之前为诺基亚健康)
2018/10/30 全球购物
研究生求职推荐信范文
2013/11/30 职场文书
销售行政专员职责
2014/01/03 职场文书
2015年科普工作总结
2015/07/23 职场文书
2015年小学语文教师工作总结
2015/10/23 职场文书
Mysql实现主从配置和多主多从配置
2021/06/02 MySQL
Python基础之变量的相关知识总结
2021/06/23 Python
Vue-Element-Admin集成自己的接口实现登录跳转
2021/06/23 Vue.js