PHP молча не может отправить данные в graphite по UDP, используя fsockopen и fwrite

Код

Я отправляю метрики в graphite через UDP, используя как php, так и python. .

Мой клиент 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)

Выход:

некоторые.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

Я делаю то же самое через интерфейс командной строки, используя 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-клиент никогда не общается с углеродом. Даже если я использую другой порт, где приложение не слушает, мой PHP просто говорит мне, что все в порядке. если я сделаю то же самое на своем клиенте Python, я получу сетевую ошибку.

Согласно документам PHP, fsockopen никогда не дает сбоев при использовании UDP из-за характера протокола, но я должен получить сообщение об ошибке при выполнении fwrite. В моем случае fwrite всегда возвращает len() сообщения $ независимо от того, какой хост/порт я использую при открытии сокета.

Если я использую неправильный порт с netcat или клиентом python, я получаю сетевую ошибку, как и ожидалось.

PHP-cli имеет error_display = On и error_reporting = E_ALL. Я тестировал это на PHP 5.4.4-14 в Debian 7.1 и PHP 5.5 в Windows 7.

Кто-нибудь сталкивался с чем-то подобным? Я почти уверен, что с моей графитовой или сетевой конфигурацией проблем нет, поэтому держу пари, что это как-то связано с PHP.


person Orestes    schedule 09.08.2013    source источник
comment
Не могу воспроизвести проблему. Но вы пытались установить тайм-аут для fsockopen?   -  person tlenss    schedule 09.08.2013
comment
@tienss, какую версию php и ОС вы использовали? Вы получили ошибку при выполнении fwrite? Я пытался использовать тайм-аут, это не меняет того факта, что fwrite продолжает работать, как будто ничего плохого не происходит :/   -  person Orestes    schedule 14.08.2013
comment
Я посмотрю на реальный код.   -  person tlenss    schedule 14.08.2013
comment
возможный дубликат сокет PHP не отправляет   -  person tlenss    schedule 15.08.2013


Ответы (1)


Проверьте, открыт ли у вас UDP-порт (по умолчанию он выключен). Код (упрощенная версия), который я использовал для тестирования (использует TCP)

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

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

fclose($fp);
person tlenss    schedule 14.08.2013
comment
fsockopen всегда будет давать сбой при подключении к порту, который не открыт, если вы используете TCP, но не если вы используете UDP. - person Orestes; 15.08.2013
comment
Конечно! Но проверили ли вы, что в вашей системе действительно есть открытый порт UDP (2003)? - person tlenss; 15.08.2013
comment
Да, у меня есть, и вы можете видеть, что я могу отправлять данные через свой собственный инструмент Python или netcat, моя единственная проблема заключается в использовании php... - person Orestes; 18.08.2013
comment
В Python вы используете TCP... в PHP вы используете UDP - person tlenss; 20.08.2013
comment
Блин, ты прав, даже с помощью netcat я делаю это через TCP! D: Спасибо, что настаиваете на этом! - person Orestes; 25.08.2013
comment
Я был в отпуске. Я пришел домой, проверил, и вот, ENABLE_UDP_LISTENER был установлен на False на /opt/graphite/conf/carbon.conf, я изменил его на True, перезапустил Carbon-Cache, и все заработало. Большое спасибо @tlenss! Что касается того, что PHP не дает сбой при выполнении fwrite для недопустимого ресурса, я не могу понять, почему такое странное поведение:/ - person Orestes; 29.08.2013