浅谈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文件读写操作之文件写入代码
Jan 13 PHP
PHP curl_setopt()函数实例代码与参数分析
Jun 02 PHP
php遍历数组的方法分享
Mar 22 PHP
PHP判断图片格式的七种方法小结
Jun 03 PHP
php调用自己java程序的方法详解
May 13 PHP
[原创]php实现子字符串位置相互对调互换的方法
Jun 02 PHP
PHP编写daemon process详解及实例代码
Sep 30 PHP
php遍历、读取文件夹中图片并分页显示图片的方法
Nov 15 PHP
YII2自动登录Cookie总是失效的解决方法
Jun 28 PHP
PHP使用Redis长连接的方法详解
Feb 12 PHP
PHP实现的解汉诺塔问题算法示例
Aug 06 PHP
Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析
May 15 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读取excel文件示例分享(更新修改excel)
2014/02/27 PHP
PHP中的替代语法介绍
2015/01/09 PHP
php写入数据到CSV文件的方法
2015/03/14 PHP
基于pthread_create,readlink,getpid等函数的学习与总结
2013/07/17 Javascript
调试JavaScript中正则表达式中遇到的问题
2015/01/27 Javascript
原生Js实现简易烟花爆炸效果的方法
2015/03/20 Javascript
jQuery+jsp下拉框联动获取本地数据的方法(附源码)
2015/12/03 Javascript
jQuery validate验证插件使用详解
2016/05/11 Javascript
javascript用正则表达式过滤空格的实现代码
2016/06/14 Javascript
微信小程序 选择器(时间,日期,地区)实例详解
2016/11/16 Javascript
JS实现数组去重复值的方法示例
2017/02/18 Javascript
原生js实现简单的焦点图效果实例
2017/12/14 Javascript
JavaScript设计模式之单例模式简单实例教程
2018/07/02 Javascript
微信小程序分享海报生成的实现方法
2018/12/10 Javascript
详解vue-cli3多环境打包配置
2019/03/28 Javascript
微信小程序版本自动更新的方法
2019/06/14 Javascript
微信小程序实现选择地址省市区三级联动
2020/06/21 Javascript
vue 计算属性和侦听器的使用小结
2021/01/25 Vue.js
[01:59]DOTA2首部纪录片《Free to play》预告片
2014/03/12 DOTA
[01:04:30]Fnatic vs Mineski 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
简单理解Python中基于生成器的状态机
2015/04/13 Python
浅谈python jieba分词模块的基本用法
2017/11/09 Python
python定时按日期备份MySQL数据并压缩
2019/04/19 Python
Python企业编码生成系统之主程序模块设计详解
2019/07/26 Python
Python在centos7.6上安装python3.9的详细教程(默认python版本为2.7.5)
2020/10/15 Python
HTML5 Canvas实现平移/放缩/旋转deom示例(附截图)
2013/07/04 HTML / CSS
5分钟实现Canvas鼠标跟随动画背景
2019/11/18 HTML / CSS
Brasty罗马尼亚:购买手表、香水、化妆品、珠宝
2020/04/21 全球购物
水污染治理专业毕业生推荐信
2013/11/14 职场文书
学习十八届三中全会精神实施方案
2014/02/17 职场文书
工程质量承诺书
2014/03/27 职场文书
多媒体编辑专业毕业生求职信
2014/06/13 职场文书
二年级学生期末评语
2014/12/26 职场文书
介绍信应该怎么开?
2019/04/03 职场文书
深度学习小工程练习之垃圾分类详解
2021/04/14 Python
Mongo服务重启异常问题的处理方法
2021/07/01 MongoDB