【问题标题】:PHP silently fails sending data to graphite over UDP using fsockopen and fwritePHP 使用 fsockopen 和 fwrite 通过 UDP 将数据静默发送到石墨失败
【发布时间】:2013-08-09 11:34:55
【问题描述】:

代码

我正在使用 php 和 python 通过 UDP 向 graphite 发送指标。

我的 python 客户端是这样的

#!/usr/bin/python
import time
from socket import socket

sock = socket()
try:
  sock.connect( ('127.0.0.1', 2003) )
except:
  print 'network error'
  sys.exit(12)

message = ("some.custom.metric.python 1 %d\n" % (int( time.time() )))
print message
sock.sendall(message)

输出:

some.custom.metric.python 1 1376045467

而我的php客户端是这样的

<?php

try {
    $fp = fsockopen("udp://127.0.0.1", 2003, $errno, $errstr);

    if (!empty($errno)) echo $errno;
    if (!empty($errstr)) echo $errstr;

    $message = "some.custom.metric.php 1 ".time().PHP_EOL;
    $bytes = fwrite($fp, $message);
    echo $message;
} catch (Exception $e) {
    echo "\nNetwork error: ".$e->getMessage();
}

输出:

一些.custom.metric.php 1 1376042961

测试

我开始 carbon 启用调试输出:

/opt/graphite/bin/carbon-cache.py --debug start

当我运行我的 python 客户端时,它工作得很好,我可以在调试输出中看到它

09/08/2013 13:13:05 :: [listener] MetricLineReceiver connection with 127.0.0.1:58134 established
09/08/2013 13:13:05 :: [listener] MetricLineReceiver connection with 127.0.0.1:58134 closed cleanly

我通过 CLI 使用 netcat

做同样的事情
echo "some.custom.metric.netcat 1 `date +%s`" | nc -w 1 127.0.0.1 2003

我可以在调试输出中看到连接

09/08/2013 13:17:46 :: [listener] MetricLineReceiver connection with 127.0.0.1:58136 established
09/08/2013 13:17:48 :: [listener] MetricLineReceiver connection with 127.0.0.1:58136 closed cleanly

问题

我的 php 客户端从不与 carbon 通信。即使我使用没有应用程序监听的不同端口,我的 PHP 也只会告诉我一切都很好。如果我在我的 python 客户端上做同样的事情,我会得到一个网络错误。

根据 PHP 文档,由于协议的性质,使用 UDP 时 fsockopen never 会失败,但在执行 fwrite 时应该会出错。在我的情况下,无论我在打开套接字时使用哪个主机/端口,fwrite 总是返回 $message 的 len()。

如果我在 netcat 或 python 客户端中使用了错误的端口,我会得到预期的网络错误。

PHP-cli 有error_display = Onerror_reporting = E_ALL。我已经在 debian 7.1 上的 PHP 5.4.4-14 和 Windows 7 上的 PHP 5.5 上对此进行了测试。

有没有人遇到过类似的情况?我几乎可以肯定我的石墨或网络配置没有问题,所以我敢打赌它与 PHP 有关。

【问题讨论】:

  • 无法真正重现该问题。但是您是否尝试过为fsockopen 设置超时?
  • @tienss 你用的是哪个php版本和操作系统?执行 fwrite 时是否出错?我尝试使用超时,它并没有改变 fwrite 继续工作的事实,就像没有发生任何错误一样:/
  • 我来看看实际代码.. 操作系统:debian squeeze (2.6.32-5) PHP: 5.3.23
  • PHP socket doesn't send的可能重复

标签: php udp graphite


【解决方案1】:

检查您是否有一个开放的 UDP 端口(默认情况下它是关闭的)。我用于测试的代码(简化版)(使用TCP)

$line = "foo.bla 1 " . time() . "\n";

$fp = fsockopen('127.0.0.1', 2003, $err, $errc, 1);
fwrite($fp, $line);

fclose($fp);

【讨论】:

  • fsockopen 在连接到未打开的端口时总是会失败,如果您使用 TCP,但如果您使用 UDP,则不会。
  • 当然!但是您是否检查过您的系统上实际上有一个开放的 UDP 端口(2003)?
  • 在 Python 中你使用 TCP... 在 PHP 中你使用 UDP
  • 该死,你是对的,即使使用 netcat 我也是通过 TCP 做的! D:谢谢你的坚持!
  • 我去度假了。我回家检查了一下,发现ENABLE_UDP_LISTENER/opt/graphite/conf/carbon.conf 上设置为False,我将其更改为True,重新启动carbon-cache,一切正常。非常感谢@tlens!至于 PHP 在对无效资源执行 fwrite 时没有失败,我不知道为什么会出现这种奇怪的行为:/
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-25
  • 2010-10-15
  • 1970-01-01
  • 2011-11-15
  • 2013-09-29
  • 1970-01-01
  • 2015-08-24
相关资源
最近更新 更多