大神,请麻烦帮忙看下这个问题,
正常用 php start.php start 这种启动方式时 对某个uid 发送消息是没有问题的,
但是用 php start.php start -d 这种守护进程方式启动时 对某个uid发送信息 内容是错误的,比如正常应该发送300 但是发送的是100或200的值。
逻辑为 workerStart里写个定时器 定时从redis里取uid返回状态,
uid为key, value分别为 100, 200, 300
start_io.php
use Workerman\Worker;
use Workerman\WebServer;
use Workerman\Lib\Timer;
use PHPSocketIO\SocketIO;
include __DIR__ . '/vendor/autoload.php';
//redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 全局数组保存uid在线数据
$uidConnectionMap = [];
// PHPSocketIO服务
$sender_io = new SocketIO(2120);
// 客户端发起连接事件时,设置连接socket的各种事件回调
$sender_io->on('connection', function($socket) {
// 当客户端发来登录事件时触发
$socket->on('login', function($uid) use($socket) {
global $uidConnectionMap;
//已经登录过了
if(isset($uidConnectionMap)) {
return;
}
// 更新对应uid的在线数据
$uid = (string)$uid;
// 将这个连接加入到uid分组,方便针对uid推送数据
$socket->join($uid);
$socket->uid = $uid;
$uidConnectionMap = $uid;
});
// 当客户端断开连接是触发(一般是关闭网页或者跳转刷新导致)
$socket->on('disconnect', function () use($socket) {
global $uidConnectionMap;
if(isset($socket->uid)) {
unset($uidConnectionMap);
} else {
return;
}
});
});
// 当$sender_io启动后监听一个http端口,通过这个端口可以给任意uid或者所有uid推送数据
$sender_io->on('workerStart', function() {
// 监听一个http端口
$inner_http_worker = new Worker('http://0.0.0.0:2121');
// 执行监听
$inner_http_worker->listen();
// 一个定时器,定时向所有uid推送当前uid在线数及在线页面数
Timer::add(5, function() {
global $sender_io, $uidConnectionMap, $redis;
if(!empty($uidConnectionMap)) {
foreach($uidConnectionMap as $uid) {
$result = $redis->hget('workers', $uid);
$result = intval($result);
//$sender_io->to($uid)->emit('new_msg', json_encode());
// 对 uid 发送 message
if($result > 0) {
$sender_io->to($uid)->emit('new_msg', json_encode());
unset($uidConnectionMap);
}
}
}
});
});
if(!defined('GLOBAL_START')) {
Worker::runAll();
}
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);redis初始化放到onWorkerStart里试下,如果放在启动入口文件直接初始化redis连接则属于在主进程初始化了redis连接,每个子进程都复用这个连接会导致数据混乱。onWorkerStart里初始化连接这样属于每个子进程初始化连接,每个进程拥有自己的redis连接,互相不影响
问题好像解决了,我再观察下,非常感谢,辛苦了~