[转] PHP读取HTTP接口如何处理超时
|
原文地址:https://www.jianshu.com/p/446ea7aaea86 最近在工作中遇到一个读取 HTTP 接口慢的问题(使用的是 PHP 服务器端语言),所以想谈谈服务器端读取外部资源超时机制的问题,谨以此文做个笔记。 在 Web 开发中,需要有大量的外部资源进行交互,比如说 Mysql、Redis、Memcached、HTTP 接口,这些资源具备这样一些特点:
对于资源的调用方来说,个人建议有以下的处理原则:
本文主要谈谈服务器程序读取 HTTP 接口超时机制问题,为什么强调服务器程序,主要是因为客户端 JavaScript 读取 HTTP 接口在处理机制上有很大的不同(或者说应用场景不同)。 超时应该设置多少超时可以细分为连接超时和读取超时,设置多少,取决于两方面,第一是 HTTP 接口的承若,比如说微信公众平台接口,其速度和可用性要求应该是极高的,虽然官方没有说明,但是我相信对于微信内部来说,单个接口响应速度不可能超过 1 秒。第二就是使用者的考虑,比如说队列程序读取接口超时可以设置高一点,而其他程序相应超时时间不能设置太长,取决于程序、应用的性质和服务能力。 说句题外话,假如 HTTP 接口出现故障,响应很慢,但是你的程序调用超时设置很大(假如再加上重试),就会进一步加重 HTTP 接口服务的可用性,可能会形成雪崩效应。 default_socket_timeout那么如何设置超时呢,PHP 流机制可以通过 default_socket_timeout 指令来配置。 流是 PHP 中很重要的一个特性,以后可以说一说,简单的理解就是在 PHP 中,不管是读取磁盘文件、HTTP 接口,都可以认为是一种流(socket/stream)。 说明下, socket/stream 的等待时间是不包括在 PHP 最大执行时间内的。
比如说在 现在重点来了,原来自己认为超时时间假如为 m 秒,那么访问接口最终响应(包括网络传输时间)超过 m 秒,调用程序就会报错。实际并不是这样,只要在 m 秒数据包一直在传输,那么调用程序就不会报错。 通过程序来演示下,先看接口代码,模拟网络传输慢的情况: 现在看看调用代码,可以看出虽然接口最后输出需要 6 秒,但由于数据库包一直在传输,代码并不报错。 <span class="hljs-keyword">global $url;var_dump(file_get_contents($url)); } <span class="hljs-function"><span class="hljs-keyword">function <span class="hljs-title">e_fopenfgets<span class="hljs-params">(){
} e_filegetcontents(); 还是让我们使用 cURL 扩展来处理超时控制吧假如你想更精确的处理超时,就使用 cURL 扩展,它可以设置连接超时和读取超时(CURLOPT_TIMEOUT,CURLOPT_CONNECTTIMEOUT)。 假如希望控制 HTTP 接口必须在毫秒级别返回,还可以使用 CURLOPT_TIMEOUT_MS and CURLOPT_CONNECTTIMEOUT_M 常量。
注意假如使用这两个常量,必须设置 神奇的来了,cURL 扩展机制很特别,在指定的读取时间获取到多少数据就返回多少,然后调用也终止,程序并不报错 通过代码看一下: 服务端模拟代码: (1(=0; <60; ++ (' ',1024*64(1 客户端读取代码: ="https://api.sopans.com/stream.php"("default_socket_timeout",3 (( = (('http'=> 'timeout' => 3.0,</span><span style="color: #800080">$handle</span> = <span style="color: #008080">fopen</span>(<span style="color: #800080">$url</span>,"r",<span style="color: #0000ff">true</span>,<span style="color: #800080">$context</span><span style="color: #000000">);
</span><span style="color: #0000ff">if</span> (<span style="color: #800080">$handle</span><span style="color: #000000">) {
</span><span style="color: #0000ff">while</span> ((<span style="color: #800080">$buffer</span> = <span style="color: #008080">fgets</span>(<span style="color: #800080">$handle</span>,4096)) !== <span style="color: #0000ff">false</span><span style="color: #000000">) {
}
</span><span style="color: #008080">fclose</span>(<span style="color: #800080">$handle</span><span style="color: #000000">);
}
} (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
