stream_select тайм-аут во вновь открытом сокете

Я использую клиент Thrift PHP для подключения к серверу Java Java. Но получил ошибку

TSocket: timed out writing 78 bytes from 10.0.1.151:1234

Я копаюсь в php источнике thrift и обнаруживаю, что это было вызвано таймаутом на функцию stream_select,

/**
* Write to the socket.
*
* @param string $buf The data to write
*/
public function write($buf)
{
$null = null;
$write = array($this->handle_);

// keep writing until all the data has been written
while (TStringFuncFactory::create()->strlen($buf) > 0) {
// wait for stream to become available for writing
$writable = @stream_select($null, $write, $null, $this->sendTimeoutSec_, $this->sendTimeoutUsec_);
if ($writable > 0) {
// write buffer to stream
$written = @stream_socket_sendto($this->handle_, $buf);
if ($written === -1 || $written === false) {
throw new TTransportException('TSocket: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes '.
$this->host_.':'.$this->port_);
}
// determine how much of the buffer is left to write
$buf = TStringFuncFactory::create()->substr($buf, $written);
} elseif ($writable === 0) {
throw new TTransportException('TSocket: timed out writing '.TStringFuncFactory::create()->strlen($buf).' bytes from '.
$this->host_.':'.$this->port_);
} else {
throw new TTransportException('TSocket: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes '.
$this->host_.':'.$this->port_);
}
}
}

Это означает, что сокет был заблокирован и не смог записать. Но розетка просто открыта и не должна быть заблокирована. Я пытаюсь выбрать сразу после pfsockopen

if ($this->persist_) {
$this->handle_ = @pfsockopen($this->host_,
$this->port_,
$errno,
$errstr,
$this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000));
} else {
$this->handle_ = @fsockopen($this->host_,
$this->port_,
$errno,
$errstr,
$this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000));
}

// Connect failed?
if ($this->handle_ === FALSE) {
$error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
if ($this->debug_) {
call_user_func($this->debugHandler_, $error);
}
throw new TException($error);
}

$write = array($this->handle_);
$writable = @stream_select($null, $write, $null, $this->sendTimeoutSec_, $this->sendTimeoutUsec_);
if ($writable === 0) {
die('123');
}

Результат показывает, что это блок сразу после его открытия!

При перезапуске php-fpm ошибка исчезнет на некоторое время и появится снова.

Вот код клиента:

$socket = new TSocket('10.0.1.151', 1234, true);
$framedSocket = new TFramedTransport($socket);
$transport = $framedSocket;
$protocol = new TCompactProtocol($transport);
$transport->open();
$client= new userservice\UserServiceProxyClient($protocol);
$result = $client->findUser($id);

Если я настрою конфигурацию php-fpm pm.max_children с 200 до 2 ошибка тоже исчезнет.

Я попытался увеличить время ожидания до 10 секунд, и это время ожидания через 10 секунд.

Есть идеи, что является причиной проблемы и как ее исправить?

0

Решение

Я модифицирую php thrift lib. Меняться от

$writable = @stream_select($null, $write, $null, $this->sendTimeoutSec_, $this->sendTimeoutUsec_);

в

$writable = 1;

И то же самое для чтения.

Проблема исправлена.

Это означает, что соединение установлено (я даже использую tcpdump, чтобы подтвердить, что соединение tcp установлено) и доступно для записи, но выберите время ожидания. Странные вещи!

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]