【问题标题】:PHP fsockopen() painfully slowPHP fsockopen() 非常缓慢
【发布时间】:2011-03-06 16:14:19
【问题描述】:

我正在使用 fsockopen() 调用列表中的多个连接以查看各种 ip/host 和端口的在线状态...

<?php
$socket = @fsockopen($row[2], $row[3], $errnum, $errstr, 1);
if ($errnum >= 1) { $status = 'offline'; } else { $status = 'online';}
fclose($socket);

如果可行,我不会抱怨,但我有大约 15 个 ip/ports 正在列表中检索(php for() 命令..)。我想知道是否有更好的方法来做到这一点?这种方式很慢!?!服务器大约需要 1-2 分钟才能回复所有这些信息。

更新:

<?php
$socket = @fsockopen("lounge.local", "80", $errnum, $errstr, 30);
if ($errnum >= 1) { $status = 'offline'; } else { $status = 'online'; }
?>

它将显示在一个列表中:“ReadyNAS AFP readynas.local:548 online”

我不知道我还能告诉你什么?加载结果集合只需要很长时间......

【问题讨论】:

  • 感谢您减少示例代码。但是,请考虑提供一个完整的示例脚本(扫描stackoverflow.comexample.com 左右)。问题几乎肯定不在您发布的摘录中。另请注意,如果$socket === false,则不应调用 fclose。
  • 谢谢,自从上传了这个sn-p,我已经把它拿出来了。更新了完整的示例脚本
  • 如果有人感兴趣。我使用的是fsockopen("localhost"),速度非常慢(~1010 毫秒)。使用fsockopen("127.0.0.1") 会快得多(~11 毫秒)。

标签: php performance fsockopen


【解决方案1】:

根据我自己的经验:

这段代码:

$sock=fsockopen('www.site.com', 80);

较慢:

$sock=fsockopen(gethostbyname('www.site.com'), 80);

在 PHP 5.4 中测试。如果同时做多个连接,可以保留主机解析结果并重复使用,以进一步减少脚本执行时间,例如:

function myfunc_getIP($host) {
   if (isset($GLOBALS['my_cache'][$host])) {
      return $GLOBALS['my_cache'][$host];
   }

   return $GLOBALS['my_cache'][$host]=gethostbyname($host);
}

$sock=fsockopen(myfunc_getIP('www.site.com'), 80);

【讨论】:

    【解决方案2】:

    如果您打算“ping”某个 URL,我建议您使用 curl,为什么?您可以使用 curl 并行发送 ping,看看这个 -> http://www.php.net/manual/en/function.curl-multi-init.php。在之前的项目中,它应该向我们的服务器提供实时数据,我们过去常常 ping 主机以查看它们是否还活着,而 Curl 是唯一对我们有帮助的选项。 这是一个建议,可能不是解决您问题的正确方法。

    【讨论】:

    • 试图实现这一点,但事实证明这是一个挑战......如果我仍然迷路,会回复你:)
    【解决方案3】:

    您是否比较了fsockopen(servername)fsockopen(ip-address) 的结果?如果超时参数没有改变任何东西,那么问题可能出在您的名称服务器上。如果使用 IP 地址的 fsockopen 更快,则必须修复名称服务器,或将域添加到 /etc/hosts 文件。

    【讨论】:

    • 会调查的 - 谢谢!它只是在我的 mac mini XAMPP 服务器上运行... :)
    【解决方案4】:

    我建议这样做有点不同。 将此主机放在数据库中的表中,例如:

    ++++++++++++++++++++++++++++++++++++
    | host | port | status | timestamp |
    ++++++++++++++++++++++++++++++++++++
    

    并将状态检查部分移动到您每 5 分钟运行一次或您想要的频率运行一次的 cron 脚本中。 该脚本将检查主机:端口并更新每条记录的状态和时间戳,在您的页面中,您只需执行数据库查询并显示主机、其状态以及上次检查的时间(例如:1 分钟前等... ) 这样您的页面将加载得很快。

    【讨论】:

    • 我不会经常登录这个页面(为了查看状态),所以如果没有必要,我不想给服务器施加更多压力。但是我将阅读“cron”,看看它是否真的可以节省一些时间...谢谢您的意见!
    【解决方案5】:

    fsockopen() 的最后一个参数是超时时间,将此设置为较低的值可以使脚本更快地完成,如下所示:

    fsockopen('192.168.1.93', 80, $errNo, $errStr, 0.01)
    

    【讨论】:

    • 谢谢,但这也未能使脚本运行得更快...感谢您的帮助。
    【解决方案6】:

    根据phpmanual,有一个超时参数。尝试将其设置为较低的值。

    编辑:添加到丹尼尔的答案中,nmap 可能是最好的工具。使用 cron 作业对其进行设置,以每 X 分钟扫描和更新您的记录。像

    $ for ip in $(seq 6 8); 
    do 
         port_open=$(nmap -oG - -p 80 10.1.0.$ip|grep open|wc -l); 
         echo "10.1.0.$ip:$port_open"; 
    done
    
    10.1.0.6:1
    10.1.0.7:1
    10.1.0.8:0
    

    【讨论】:

    • 原来设置为1,没做任何事情,所以我把它放回默认的30...
    • 嗯,可能需要更多调试。如果可能,使用 tcpdump/wireshark 查看 tcp 流,看看 fsockopen 正在做什么。它是否试图重新发送?远程主机没有响应吗?是否有防火墙在工作?
    【解决方案7】:

    我遇到了一个问题,即 fsockopen 请求很慢,但 wget 真的很敏捷。就我而言,这是因为主机名同时具有 ipv4 和 ipv6 地址,但 ipv6 已关闭。因此,ipv6 的每个请求需要 20 秒左右才能超时。

    【讨论】:

      猜你喜欢
      • 2011-12-09
      • 2010-11-22
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      • 2019-08-11
      • 2010-10-31
      • 1970-01-01
      相关资源
      最近更新 更多