我的需求是根據(jù)需求給客戶端某個(gè)用戶推送消息,代碼如下:
<?php
use Workerman\Worker;
include_once __DIR__ . DIRECTORY_SEPARATOR . '../config.php';
require_once WORKERMAN_WEBSOCKET_API_ROOT . '/Workerman/Autoloader.php';
require_once ROOT_DIR . 'lib/FileMonitor.php';
include_once ROOT_DIR . 'lib/config.php';
include_once ROOT_DIR . 'lib/MySQL.php';
include_once ROOT_DIR . 'lib/SysException.php';
include_once ROOT_DIR . 'lib/ActionException.php';
include_once ROOT_DIR . 'lib/common.php';
include_once H5_API_ROOT . 'include/function.php';
include_once H5_API_ROOT . 'include/action.php';
include_once H5_API_ROOT . 'include/verifyRequest.php';
//方便監(jiān)控WorkerMan進(jìn)程狀態(tài)
Worker::$pidFile = ROOT_DIR . 'logs/workerman.pid';
//輸出日志, 如echo,var_dump等
Worker::$stdoutFile = ROOT_DIR . 'logs/stdout.log';
//workerman自身相關(guān)的日志,包括啟動(dòng)、停止等,不包含任何業(yè)務(wù)日志
Worker::$logFile = ROOT_DIR . 'logs/workerman.log';
// 創(chuàng)建一個(gè)Worker監(jiān)聽(tīng)2345端口,使用http協(xié)議通訊
$worker = new Worker('websocket://' . $ws_server_config['host'] . ':' . $ws_server_config['port']);
// 啟動(dòng)4個(gè)進(jìn)程對(duì)外提供服務(wù)
$worker->count = 4;
$worker->name = 'MyWebsocketWorker';
// 新增加一個(gè)屬性,用來(lái)保存uid到connection的映射
$uuidConnections = [];
$worker->onWorkerStart = function ($worker) {
echo "Worker " . $worker->id . " starting...\n";
};
$worker->onConnect = function ($connection) {
echo "new connection " . $connection->worker->id . ' : ' . $connection->id . " from ip " . $connection->getRemoteIp() . "\n";
};
$worker->onMessage = function ($connection, $data) use ($worker) {
$data = parseClientContentToArray($data);
//print_r($data);
if (empty($data['sid'])) {
echo 'sid 參數(shù)缺失' . "\r\n";
return;
}
global $uuidConnections;
$uuidConnections[$data['sid']] = $connection;
print_r(array_keys($uuidConnections));
//require_once 'action.php';
switch ($data['act']) {
case 'push_msg_to_individual':
print_r(array_keys($uuidConnections));
if (isset($uuidConnections[$data['data']['tsid']])) {
$result = $uuidConnections[$data['data']['tsid']]->send($data['data']['content']);
if ($result === true) {
echo "消息發(fā)送成功\r\n";
} else if ($result === false) {
echo "消息發(fā)送失敗\r\n";
} else {
echo "發(fā)生未知錯(cuò)誤\r\n";
}
} else {
echo "目標(biāo)用戶已下線,消息發(fā)送失敗\r\n";
}
break;
default:
//echo "未匹配到方法\r\n";
break;
}
$connection->send('OK!');
};
$worker->onClose = function ($connection) {
echo "connection " . $connection->id . " closed\n";
};
$worker->onError = function ($connection, $code, $msg) {
echo $connection->id . " error $code $msg\n";
};
// 運(yùn)行worker
Worker::runAll();
我有一個(gè)客戶端頁(yè)面用的 js websocket 連接著這個(gè)服務(wù),代碼就不上了,另外一個(gè)測(cè)試頁(yè)面代碼如下:
sendMessageBySidV1([
'sid' => '111111111',
'gid' => '',
'type' => '',
'errcode' => 0,
'msg' => '給某個(gè)用戶推送消息',
'act' => 'push_msg_to_individual',
'data' => ['tsid' => '1624441757325-0.05429327573496745', 'content' => 'hello ??!']
]);
我期望的結(jié)果是我刷新我這個(gè)測(cè)試頁(yè)面會(huì)向我的那個(gè)客戶端頁(yè)面推送消息。
現(xiàn)在的問(wèn)題是當(dāng)我把 $worker->count 設(shè)置為大于 1 的時(shí)候,會(huì)有一定的幾率推送消息失敗,設(shè)置為1不會(huì)有問(wèn)題,看下圖:
我知道大概是進(jìn)程的問(wèn)題,但是我現(xiàn)在那個(gè) $uuidConnections 是個(gè)超全局變量吧,難道每個(gè) worker 讀取 $uuidConnections 的值的時(shí)候結(jié)果會(huì)不一樣嗎?