You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@thrift.apache.org by 黄雅冠 <hu...@gmail.com> on 2016/02/20 03:33:09 UTC

Error while using php client : TSocket: timed out writing xx bytes from xx.xx.xx.xx:xxxx

I use thrift php client to connect to java thrift server. But got the error
of

TSocket: timed out writing 78 bytes from 10.0.1.151:1234

I dig into the php source of thrift and find it was caused from timeout on
function 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_);
        }
    }
}

That means the socket was blocked and was not able to write. But the socket
is just open and should not be blocked. I try select immediately after
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');
}

The result show that it is block right after it is opened!

When restart php-fpm, the error disappear for a while and come up again.

Here is the client code:

$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);

If I adjust the php-fpm configuration pm.max_children from 200 to 2, the
error also disappear.

I tried increase timeout to 10 seconds and it timeout after 10 seconds.

Any idea for what’s the cause of the problem and how to fix it?
​