請問為什麼,sendBufferToWorker函數無法將資料送出?

0

在處理連續命令時,有些連續命令遺失,最後發現在sendBufferToWorker這個函數並沒有將收到的命令送到Worker去,好像在前一個命令處理完後即調用closeInnerClient($fd)將連線關閉。導致sendBufferToWorker沒有將命令送出去。


protected function sendBufferToWorker($bin_data)
{

print_r("\nsendBufferToWorker:".$this->currentDealFd);

if($this->currentDealFd = array_rand($this->workerConnections))
{
$this->sendToClient($bin_data);
echo("\nsend success!!!!");
}else{
echo("\nsend fault!!!!");
}
}

為什麼會發生這種情況?
謝謝。

已邀请:

walkor

赞同来自:

workerman长连接应用刚启动时,Gateway于BusinessWorker之间会建立连接,在连接没建立好时,会有数据丢失情况。workerman启动到建立连接完毕大概需要1-2秒的时间,也就是说目前长连接应用要等workerman启动后需要等待1-2秒才能正常工作,后面会针对这个问题做优化


如果不是上述问题导致,可以尝试或者检查以下项目:


1、请确认下配置是与线上一致,尤其是 persistent_connection ,max_requests
2、查看workerman/log/date/server.log 看是否有进程异常退出的日志
3、检查php日志是否有FatalError等致命错误

flimulus - Hello~

赞同来自:

您好,承上面的問題,我的程式是由 底下的 這個地方关闭链接,因為 $this->workerConnections 已經清空了,導致後下一個命令無法送至Worker。


為什麼,會出現 if('' == $buffer && '' == ($buffer = fread($connection, $this->recvBuffers))) 這個狀態,然後關閉連線呢?


謝謝,您的回覆。


public function recvTcp($connection, $flag, $fd = null)
{
$this->currentDealFd = $fd;
$buffer = stream_socket_recvfrom($connection, $this->recvBuffers);

// 出错了
if('' == $buffer && '' == ($buffer = fread($connection, $this->recvBuffers)))
{

if(!feof($connection))
{
return;
}

// 如果该链接对应的buffer有数据,说明发生错误
if(!empty($this->recvBuffers))
{
$this->statusInfo++;
$this->notice("INNER_CLIENT_CLOSE\nCLIENT_IP:".$this->getRemoteIp()."\nBUFFER:\n");
}

// 关闭链接
$this->closeInnerClient($fd);
if($this->workerStatus == self::STATUS_SHUTDOWN)
{
$this->stop();
}
return;
}

$this->recvBuffers .= $buffer;

$remain_len = $this->dealInnerInput($this->recvBuffers);
// 包接收完毕
if(0 === $remain_len)
{
// 执行处理
try{
// 内部通讯业务处理
$this->innerDealProcess($this->recvBuffers);
}
catch(\Exception $e)
{
$this->notice('CODE:' . $e->getCode() . ' MESSAGE:' . $e->getMessage()."\n".$e->getTraceAsString()."\nCLIENT_IP:".$this->getRemoteIp()."\nBUFFER:\n");
$this->statusInfo ++;
}
$this->recvBuffers = array('buf'=>'', 'remain_len'=>GatewayProtocol::HEAD_LEN);
}
// 出错
else if(false === $remain_len)
{
// 出错
$this->statusInfo++;
$this->notice("INNER_PACKET_ERROR\nCLIENT_IP:".$this->getRemoteIp()."\nBUFFER:\n");
$this->closeInnerClient($fd);
}
else
{
$this->recvBuffers = $remain_len;
}

// 检查是否是关闭状态或者是否到达请求上限
if($this->workerStatus == self::STATUS_SHUTDOWN )
{
// 停止服务
$this->stop();
// EXIT_WAIT_TIME秒后退出进程
pcntl_alarm(self::EXIT_WAIT_TIME);
}
}

walkor

赞同来自:

当对方主动关闭连接时,本地对应的socket会得到一个可读状态,但是读取的数据是空的。
出现socket可读并且读到的数据为空时,还需要用feof判断下是否对方真的关闭了连接,如果对方关闭了连接,则本地也需要执行关闭操作。

flimulus - Hello~

赞同来自:

我找到這個問題的原因,因為在做測試 將啟動行程數量改為1,您的BusinessWorker連接為
短连接,所以每處理一次命令就會中斷與 GateWay 的連線 , 在發送連續命令時剛好碰到
$this->workerConnections 連線數為零,就沒將數據送出。
您是否能設計保險一點,增加一個Queues,來保存沒有送出的命令。


protected function sendBufferToWorker($bin_data)
{
if($this->currentDealFd = array_rand($this->workerConnections))
{
$this->sendToClient($bin_data);
}else{
// 加到 佇列 Queues 等候再發送。
}
}

謝謝您。

walkor

赞同来自:

BusinessWorker必须设置为长连接,除了listen选项,其他配置最好和线上版本的配置一致。

flimulus - Hello~

赞同来自:

了解,謝謝您的回答。

walkor

赞同来自:

不客气

要回复问题请先登录注册