浅谈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 相关文章推荐
用户的详细注册和判断
Oct 09 PHP
windows下开发并编译PHP扩展的方法
Mar 18 PHP
基于PHP中的常用函数回顾
Jul 11 PHP
php定义数组和使用示例(php数组的定义方法)
Mar 29 PHP
PHP Session机制简介及用法
Aug 19 PHP
浅谈php正则表达式中的非贪婪模式匹配的使用
Nov 25 PHP
php将图片文件转换成二进制输出的方法
Jun 10 PHP
PHP面向对象详解(三)
Dec 07 PHP
Laravel5中防止XSS跨站攻击的方法
Oct 10 PHP
PHP 用session与gd库实现简单验证码生成与验证的类方法
Nov 15 PHP
PHP实现统计所有字符在字符串中出现次数的方法
Oct 17 PHP
利用PHP获取汉字首字母并且分组排序详解
Oct 22 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
让这部DC动画新作刷新你的认知
2020/03/03 欧美动漫
PHP去除数组中重复的元素并按键名排序函数
2008/08/18 PHP
PHP 5.3和PHP 5.4出现FastCGI Error解决方法
2015/02/12 PHP
PHP输入流php://input实例讲解
2015/12/22 PHP
PHP数字前补0的自带函数sprintf 和number_format的用法(详解)
2017/02/06 PHP
解决laravel 5.1报错:No supported encrypter found的办法
2017/06/07 PHP
php设计模式之正面模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
javascript开发随笔二 动态加载js和文件
2011/11/25 Javascript
Jquery日期选择datepicker插件用法实例分析
2015/06/08 Javascript
javascript中传统事件与现代事件
2015/06/23 Javascript
JavaScript中字面量与函数的基本使用知识
2015/10/20 Javascript
JS+Canvas 实现下雨下雪效果
2016/05/18 Javascript
移动端点击图片放大特效PhotoSwipe.js插件实现
2016/08/25 Javascript
AngularJS实现数据列表的增加、删除和上移下移等功能实例
2016/09/05 Javascript
jQuery基于正则表达式的表单验证功能示例
2017/01/21 Javascript
JS获取url参数,JS发送json格式的POST请求方法
2018/03/29 Javascript
微信小程序定位当前城市的方法
2018/07/19 Javascript
Vue数据绑定实例写法
2019/08/06 Javascript
[01:00:17]DOTA2-DPC中国联赛 正赛 SAG vs Dynasty BO3 第二场 1月25日
2021/03/11 DOTA
浅谈Python中的闭包
2015/07/08 Python
用python生成(动态彩色)二维码的方法(使用myqr库实现)
2019/06/24 Python
python飞机大战pygame游戏背景设计详解
2019/12/17 Python
python基于opencv检测程序运行效率
2019/12/28 Python
python3 xpath和requests应用详解
2020/03/06 Python
200行python代码实现贪吃蛇游戏
2020/04/24 Python
CSS实现进度条和订单进度条的示例
2020/11/05 HTML / CSS
阿联酋团购网站:Groupon阿联酋
2016/10/14 全球购物
英文版网络工程师求职信
2013/10/28 职场文书
服务员岗位责任制
2014/02/11 职场文书
保险专业求职信
2014/07/07 职场文书
班组拓展活动方案
2014/08/14 职场文书
小学运动会报道稿
2014/10/04 职场文书
反对四风自我剖析材料
2014/10/07 职场文书
应届生简历自我评价
2015/03/11 职场文书
上学路上观后感
2015/06/16 职场文书
Python 视频画质增强
2022/04/28 Python