【问题标题】:PHP 5.5.3 on Win32 - cURL takes 400ms+ to resolve all domain names, even localhostWin32 上的 PHP 5.5.3 - cURL 需要 400 毫秒以上才能解析所有域名,甚至是 localhost
【发布时间】:2013-09-19 06:58:38
【问题描述】:

自从我将服务器从 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") );

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

【问题讨论】:

  • 你检查过机器上的DNS设置吗?
  • 我非常怀疑问题与 curl 相关,请使用 nslookup(或任何其他命令行实用程序)检查您的 DNS 设置,应该很容易检测到 400 毫秒。
  • nslookup 立即返回。这是一台 Windows Azure 机器,Azure VM 使用 DHCP 来分配 DNS 服务器。
  • 如果您的配置中有超过 1 个 DNS 服务器,请尝试交换它们的顺序。
  • 只配置了 1 个 DNS 服务器。

标签: php curl


【解决方案1】:

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

有 3 种可能的解决方案:

  1. 更新您的 php_curl.dll(当前 windows php 二进制文件 5.5.4);
  2. 安装本地 DNS 服务器并将其配置为使用 hosts 文件并将您的网络配置为使用 127.0.0.1 作为 DNS 服务器;
  3. 将 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 相同(对于写入 hosts 文件中的任何记录)。所以,我绝对确定这不是 PHP 问题:

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

【讨论】:

  • 我更新了我的 PHP 5.5.4 但这并没有解决问题。我认为 cURL 甚至根本没有自己的 DNS 缓存,因为连续两次请求相同的主机名需要同样的时间。
  • 我的答案略有改进。
猜你喜欢
  • 2015-06-20
  • 2015-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-22
相关资源
最近更新 更多