laravel框架使用gateway-client時,調(diào)用isUidOnline等諸多方法時,偶爾會出現(xiàn)卡頓5秒的情況。
經(jīng)過排查源碼,發(fā)現(xiàn)是gatewayclient/Gateway.php這個文件的如下圖方法中,陷入死循環(huán),到了超時時間5秒后退出循環(huán)。不知道是什么原因?qū)е滤姥h(huán)
//摘自源碼
protected static function getBufferFromGateway($gateway_buffer_array)
{
$client_array = $status_data = $client_address_map = $receive_buffer_array = $recv_length_array = array();
// 批量向所有g(shù)ateway進(jìn)程發(fā)送請求數(shù)據(jù)
foreach ($gateway_buffer_array as $address => $gateway_buffer) {
$client = stream_socket_client("tcp://$address", $errno, $errmsg, static::$connectTimeout);
if ($client && strlen($gateway_buffer) === stream_socket_sendto($client, $gateway_buffer)) {
$socket_id = (int)$client;
$client_array[$socket_id] = $client;
$client_address_map[$socket_id] = explode(':', $address);
$receive_buffer_array[$socket_id] = '';
}
}
// 超時5秒
$timeout = 5;
$time_start = microtime(true);
// 批量接收請求
while (count($client_array) > 0) {
$write = $except = array();
$read = $client_array;
if (@stream_select($read, $write, $except, $timeout)) {
foreach ($read as $client) {
$socket_id = (int)$client;
$buffer = stream_socket_recvfrom($client, 65535);
if ($buffer !== '' && $buffer !== false) {
$receive_buffer_array[$socket_id] .= $buffer;
$receive_length = strlen($receive_buffer_array[$socket_id]);
if (empty($recv_length_array[$socket_id]) && $receive_length >= 4) {
$recv_length_array[$socket_id] = current(unpack('N', $receive_buffer_array[$socket_id]));
}
if (!empty($recv_length_array[$socket_id]) && $receive_length >= $recv_length_array[$socket_id] + 4) {
unset($client_array[$socket_id]);
}
} elseif (feof($client)) {
unset($client_array[$socket_id]);
}
}
}
if (microtime(true) - $time_start > $timeout) {
break;
}
}
$format_buffer_array = array();
foreach ($receive_buffer_array as $socket_id => $buffer) {
$local_ip = ip2long($client_address_map[$socket_id][0]);
$local_port = $client_address_map[$socket_id][1];
$format_buffer_array[$local_ip][$local_port] = unserialize(substr($buffer, 4));
}
return $format_buffer_array;
}
希望各位大佬幫忙看看,是什么原因?qū)е逻M(jìn)入死循環(huán),有什么優(yōu)化解決的方法。
啟動web服務(wù)后,不確定的時間之后,無論調(diào)用調(diào)用isUidOnline還是getAllClientIdCount 等方法,都會走到那個死循環(huán)5秒后超時退出。于此同時,另一個項目卻可以正常的調(diào)用,調(diào)用的都是這同一個gateway-worker
centos7
lumen5.8+laravelS加速
gatewayclient3.0.12
gatewayworker3.0.19
個人還有個懷疑的地方,就是代碼片段中
$buffer = stream_socket_recvfrom($client, 65535);
這一行中65535這個值,我調(diào)整過服務(wù)器的ulimit值,不知道是不是因為這個原因
卡5秒是因為有g(shù)ateway進(jìn)程一直沒返回數(shù)據(jù)
可能的原因有
1、gateway所在服務(wù)器沒有安裝event擴(kuò)展(php start.php status 結(jié)果里需要有event字樣),單個進(jìn)程連接數(shù)超過1024時超出的連接無法響應(yīng),包括內(nèi)部接口調(diào)用的連接。安裝擴(kuò)展后需要restart重啟才能生效,reload不生效。
2、進(jìn)程可打開文件數(shù)設(shè)置過低,當(dāng)連接數(shù)超過進(jìn)程可打開文件數(shù)后,一些連接可能無法響應(yīng)數(shù)據(jù)。更改內(nèi)核配置需要restart重啟才能生效,reload不生效。
3、跨服務(wù)器的話也可能是網(wǎng)絡(luò)抖動導(dǎo)致