Win32 上的 PHP 5.5.3 - cURL 需要 400ms+ 来解析所有域名,甚至是本地主机


PHP 5.5.3 on Win32 - cURL takes 400ms+ to resolve all domain names, even localhost

自从我将服务器从 PHP 5.3.x 升级到 PHP 5.5.3 以来,我在使用 PHP Web 服务客户端时遇到了问题。

我有这个函数来计时 cURL 执行请求所需的时间:

function makeRequest($method, $uri) {
    global $requests;
    addTime("makeRequest");
    $curl = curl_init($uri);
    curl_setopt($curl, CURLOPT_HEADER    , true ); 
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true );
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true );
    curl_setopt($curl, CURLOPT_MAXREDIRS     , 10   );
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST , $method);
    //////////////////////////////
    addTime("curl_exec");
    $responseContent = curl_exec($curl);
    remTime("curl_exec");
    addTime("curl_getInfo");
    $responseInfo = curl_getinfo($curl);
    remTime("curl_getInfo");
    array_push( $requests, var_export( $responseInfo, true ) );
    remTime("makeRequest");
}

addTimeremTime是记录microtime(true)以准确测量方法执行的函数。我还记录了curl_getinfo报告的不同时间)。见下文。

我用一堆不同的 URI 尝试过。这些是我的结果:

https://api1.mywebservice.com/methodCall

  • total_time - 0.406
  • namelookup_time - 0.0406
  • connect_time - 0.406
  • pretransfer_time - 0.406
  • starttransfer_time - 0.406
  • redirect_time - 0

makeRequest时间: 0.402

https://api2.mywebservice.com/methodCall

api2.mywebservice.com 被硬编码到计算机的%windir%'system32'drivers'etc'hosts文件中以127.0.0.1因此它永远不会为此访问DNS服务器

  • total_time - 0.406
  • namelookup_time - 0.0406
  • connect_time - 0.0406
  • pretransfer_time - 0.0406
  • starttransfer_time - 0.0406
  • redirect_time - 0

makeRequest时间:0.402

https://localhost/methodCall

  • total_time - 0.406
  • namelookup_time - 0.406
  • connect_time - 0.406
  • pretransfer_time - 0.406
  • starttransfer_time - 0.406
  • redirect_time - 0

makeRequest时间: 0.403

https://127.0.01/methodCall

  • total_time - 0
  • namelookup_time - 0
  • connect_time - 0
  • pretransfer_time - 0
  • starttransfer_time - 0
  • redirect_time - 0

makeRequest时间:0.006

服务器的DNS服务器只有大约5ms的距离,但无论如何都应该缓存名称。它获得相同时间api2.mywebservice.com的事实表明这不是DNS服务器超时的问题,而是cURL内部腐烂的问题。

我也尝试了CURLOPT_RESOLVE但没有效果:

curl_setopt( $c, CURLOPT_RESOLVE, array("api1.mywebservice.com:443:127.0.01") );

为什么 cURL 在最新(当然也是最好的?)版本的 PHP 中需要这么长时间才能检索结果?

似乎您的 libcurl 是使用它自己的名称解析器而不是系统名称解析器构建的。在这种情况下,它根本不使用主机文件。

有 3 种可能的解决方案:

  1. 更新您的php_curl.dll(当前的Windows PHP二进制文件5.5.4);
  2. 安装本地 DNS 服务器并将其配置为使用
  3. 主机文件,并将网络配置为使用 127.0.0.1 作为 DNS 服务器;
  4. 将CURLOPT_DNS_USE_GLOBAL_CACHE设置为 true(默认打开),CURLOPT_DNS_CACHE_TIMEOUT设置为更大的值(默认为 2 分钟);

此外:来自 php.net 的 php 5.5.4 Windows 二进制文件使用 curl 的系统解析器。它使用内部缓存(当与CURLOPT_DNS_USE_GLOBAL_CACHE一起使用时)和系统DNS缓存。我已经通过一些测试进行了检查。A 还通过 curl 检查了名称解析的速度 - 它与 localhost 相同(对于写入主机文件的任何记录)。所以,我绝对认为这不是PHP问题:

    在这种情况下,
  1. https://127.0.01/methodCall必须https://127.0.0.1/methodCall 中存在错误。 在这种情况下,curl 总是返回 total_time = 0。
  2. 首先尝试请求静态内容,如空文件,并使用HTTP而不是HTTPS。
  3. 禁用所有防火墙并卸载所有防病毒软件(在某些情况下,停止防病毒软件是不够的)。
  4. 检查Web服务器的虚拟主机配置,并查看您请求的内容。
  5. 检查curl_getinfo($curl)的所有字段,尤其是"primary_ip"