浅谈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创建多级目录代码
Jun 05 PHP
用php将任何格式视频转为flv的代码
Sep 03 PHP
php数据库抽象层 PDO
May 07 PHP
thinkphp实现like模糊查询实例
Oct 29 PHP
php查询ip所在地的方法
Dec 05 PHP
基于linnux+phantomjs实现生成图片格式的网页快照
Apr 15 PHP
php实现的微信红包算法分析(非官方)
Sep 25 PHP
Symfony2实现从数据库获取数据的方法小结
Mar 18 PHP
详谈PHP程序Laravel 5框架的优化技巧
Jul 18 PHP
Yii框架实现的验证码、登录及退出功能示例
May 20 PHP
PHP用户注册邮件激活账户的实现代码
May 31 PHP
php DES加密算法实例分析
Sep 18 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中批量删除Mysql中相同前缀的数据表的代码
2011/07/01 PHP
防止本地用户用fsockopen DDOS攻击对策
2011/11/02 PHP
PHP开发微信支付的代码分享
2014/05/25 PHP
PHP新建类问题分析及解决思路
2015/11/19 PHP
PHP简单实现欧拉函数Euler功能示例
2017/11/06 PHP
laravel 执行迁移回滚示例
2019/10/23 PHP
JavaScript 放大镜 放大倍率和视窗尺寸
2011/05/09 Javascript
jQuery实现Email邮箱地址自动补全功能代码
2015/11/03 Javascript
详解JavaScript逻辑Not运算符
2015/12/04 Javascript
神奇!js+CSS+DIV实现文字颜色渐变效果
2016/03/16 Javascript
jQuery实现鼠标选文字发新浪微博的方法
2016/04/02 Javascript
[原创]Javascript 实现广告后加载 可加载百度谷歌联盟广告
2016/05/11 Javascript
JavaScript简单下拉菜单特效
2016/09/13 Javascript
Javascript计算二维数组重复值示例代码
2016/12/18 Javascript
Bootstrap源码解读导航条(7)
2016/12/23 Javascript
微信小程序 支付功能实现PHP实例详解
2017/05/12 Javascript
JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题
2017/06/30 Javascript
Vue侧滑菜单组件——DrawerLayout
2017/12/18 Javascript
axios post提交formdata的实例
2018/03/16 Javascript
angularJs中ng-model-options设置数据同步的方法
2018/09/30 Javascript
JavaScript解析及序列化JSON的方法实例分析
2019/01/04 Javascript
微信小程序实现授权登录
2019/05/15 Javascript
node静态服务器实现静态读取文件或文件夹
2019/12/03 Javascript
Python爬虫:通过关键字爬取百度图片
2017/02/17 Python
使用pyecharts在jupyter notebook上绘图
2020/04/23 Python
Django框架实现逆向解析url的方法
2018/07/04 Python
django 简单实现登录验证给你
2019/11/06 Python
使用python实现回文数的四种方法小结
2019/11/24 Python
keras 使用Lambda 快速新建层 添加多个参数操作
2020/06/10 Python
python遍历路径破解表单的示例
2020/11/21 Python
爱淘宝:淘宝网购物分享平台
2017/04/28 全球购物
大学生毕业自我评价范文分享
2013/11/07 职场文书
经典促销广告词大全
2014/03/19 职场文书
大学生学习十八届五中全会精神心得体会
2016/01/05 职场文书
详解TypeScript的基础类型
2022/02/18 Javascript
JavaScript正则表达式实现注册信息校验功能
2022/05/30 Java/Android