浅谈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 相关文章推荐
建立动态的WML站点(三)
Oct 09 PHP
PHP编程中字符串处理的5个技巧小结
Nov 13 PHP
PHP 程序员应该使用的10个组件
Oct 31 PHP
PHP新手入门学习方法
May 08 PHP
php设计模式 Command(命令模式)
Jun 26 PHP
PHP中__get()和__set()的用法实例详解
Jun 04 PHP
PHP定时任务延缓执行的实现
Oct 08 PHP
php实现ip白名单黑名单功能
Mar 12 PHP
PHP 用session与gd库实现简单验证码生成与验证的类方法
Nov 15 PHP
centos 7.2下搭建LNMP环境教程
Nov 20 PHP
php实现多站点共用session实现单点登录的方法详解
Sep 18 PHP
PHP实现长轮询消息实时推送功能代码实例讲解
Feb 26 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删除记录操作代码
2008/06/07 PHP
phpMyAdmin链接MySql错误 个人解决方案
2009/12/28 PHP
php文件上传的简单实例
2013/10/19 PHP
深入理解PHP 数组之count 函数
2016/06/13 PHP
thinkphp整合微信支付代码分享
2016/11/24 PHP
jQuery与JS加载事件用法分析
2016/09/04 Javascript
jQuery实现单击按钮遮罩弹出对话框效果(2)
2017/02/20 Javascript
JS实现的Unicode编码转换操作示例
2017/04/28 Javascript
javascript+html5+css3自定义提示窗口
2017/06/21 Javascript
node使用promise替代回调函数
2018/05/07 Javascript
element-ui表格数据转换的示例代码
2018/08/24 Javascript
layUI实现前端分页和后端分页
2019/07/27 Javascript
python中Flask框架简单入门实例
2015/03/21 Python
python使用htmllib分析网页内容的方法
2015/05/08 Python
Python 数据结构之旋转链表
2017/02/25 Python
彻底搞懂Python字符编码
2018/01/23 Python
Python实现OpenCV的安装与使用示例
2018/03/30 Python
python getpass实现密文实例详解
2019/09/24 Python
Python enumerate函数遍历数据对象组合过程解析
2019/12/11 Python
Python基础之函数基本用法与进阶详解
2020/01/02 Python
最小二乘法及其python实现详解
2020/02/24 Python
使用TensorBoard进行超参数优化的实现
2020/07/06 Python
python pymysql库的常用操作
2020/10/16 Python
基于Python组装jmx并调用JMeter实现压力测试
2020/11/03 Python
写一个函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度
2015/11/18 面试题
Servlet的实例是在生命周期什么时候创建的?配置servlet最重要的是什么?
2012/05/30 面试题
医学生求职自荐信
2013/10/25 职场文书
工作自我评价怎么写
2014/01/29 职场文书
2014爱耳日宣传教育活动总结
2014/03/09 职场文书
高三毕业典礼主持词
2014/03/27 职场文书
政府信息公开实施方案
2014/05/09 职场文书
工商行政管理专业求职书
2014/05/23 职场文书
幼儿园小班教师个人工作总结
2015/02/06 职场文书
春季运动会加油词
2015/07/18 职场文书
python playwright 自动等待和断言详解
2021/11/27 Python
python开发制作好看的时钟效果
2022/05/02 Python