2016-02-19 27 views
0

我使用thrift php客戶端連接到java thrift服務器。但得到的在新打開的套接字上的stream_select超時

TSocket: timed out writing 78 bytes from 10.0.1.151:1234 

我鑽進去節儉的PHP源代碼的錯誤,並發現它是由超時值函數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); 

如果我從200到2調整PHP-FPM配置pm.max_children,誤差也消失。

我試着增加超時到10秒,超過10秒後超時。

有什麼想法解決問題的原因以及如何解決它?

回答

0

我修改了php thrift lib。改變從

$writable = 1; 

與同爲讀。

問題得到解決。

這意味着連接建立(我甚至使用tcpdump來確認tcp連接建立)並且可寫,但是選擇超時。奇怪的東西!