GlobalData组件无法在不同的客户端中共享变量?

adminppper

[/Controller/ImServer.php] CLI启动,并且onWorkerStart 会启动3次,因为我设置了worker->count=3;

 public function onWorkerStart($worker){
        FaceLog::info('[server]TCP/管道Channel服务启动:|当前进程池编号:'.$worker->id);

        try{
            new ImGlobalDataBase($worker);
        }catch (\Exception $e){
            FaceLog::error('[error]'.$e->getMessage().'[line]'.$e->getLine().'[file]'.$e->getFile());
        }

    }

[/logic/ImGlobalDataBase.php]

<?php
declare(strict_types=1);
namespace app\tcp\logic;
use GlobalData\Client;
use think\Exception;

/**
 * Class ImGlobalDataBase
 * @package app\tcp\logic
 * 每个进程启动,$this->worker->count次
 */
class ImGlobalDataBase
{
    public static $port=2116;

    private  $G;

    public function __construct($worker)
    {
        $this->G=new Client('0.0.0.0:'.self::$port);
        $this->Init($worker);
    }

    /**
     * @param $worker
     * @throws \Exception
     * 初始化进程 渲染workers,与 UserToken
     */
    public  function Init($worker){
        FaceLog::warning('[GlobalData]添加进程->'.$worker->name.$worker->id);
        $c_worker=[
            $worker->name.$worker->id
        ];
        if(!isset($this->G->workers)){
            FaceLog::info('[GlobalData]未设置->workers,现在开始设置');
            $this->G->workers=$c_worker;
            $this->G->TokenUser=[];

            var_dump($this->G->workers);
            return true;
        }

        FaceLog::info('[GlobalData]已设置->workers,现在开始新增worker');

        $_workers=$this->G->workers;
        $_workers[]=$c_worker;
        $this->G->workers=$_workers;
        return true;
//        if(!isset($this->G->workers)){
//            //init
//
//            if(!$this->G->add('workers',$c_worker)){
//                throw new Exception(workers__FUNCTION__.'失败workers[init first]');
//            }
//            FaceLog::info('添加workers[init first]');
//            if(!$this->G->add('TokenUser',[])){
//                throw new Exception(__FUNCTION__.'失败TokenUser');
//            }
//
//            FaceLog::info('添加TokenUser[init first]');
//        }else{
//            $_workers=$this->G->workers;
//            $_workers[]= $worker->name.$worker->id;
//            if(!$this->G->cas('workers',$this->G->workers,$_workers)){
//                throw new Exception(__FUNCTION__.'失败workers');
//            }
//            FaceLog::info('添加workers[]');
//        }
    }
?>

调试结果,貌似 每一个 被独立 实例化的ImGlobalDataBase 无法共享(new GlobalData('0.0.0.0:2223'))->workers

2315 1 0
1个回答

adminppper

顺便问下 这个论坛的 walkor是谁啊

已经解决:
原因:onWorkerStart 会启动三次,就是因为三次并发导致add无法进行原子写入。()
解决办法:

<?php
declare(strict_types=1);
namespace app\tcp\logic;
use GlobalData\Client;
use think\Exception;

/**
 * Class ImGlobalDataBase
 * @package app\tcp\logic
 * 每个进程启动,$this->worker->count次
 */
class ImGlobalDataBase
{
    public static $port=2116;
    private  $global;

    public function __construct($worker)
    {
        $this->global=new Client('0.0.0.0:'.self::$port);
        $this->Init($worker);
    }

    /**
     * @param $worker
     * @throws \Exception
     * 初始化进程 渲染workers,与 UserToken
     */
    public  function Init($worker){
        do{
            $_old=$_new=$this->global->workers;
            $_new[]=[
                'worker_id'=>$worker->id,
                'worker_name'=>$worker->name,
                'worker_ip'=>gethostbyname(gethostname())
            ];
            $apand=$this->global->cas('workers',$_old,$_new);
        }while($apand==false);
        FaceLog::info('添加workers[]');
    }

    //TokenUser
    public  function AddTokenUser($conn){
        do{
            $old=$new=$this->global->TokenUser;
            $_new=[
                'uid'=>$conn->_uid,
                'channel_subscript'=>$conn->id,
                'worker_id'=>$conn->worker->name.$conn->worker->id,
                'this_server_ip'=>gethostbyname(gethostname())
            ];
            $new[]=$_new;
            FaceLog::info('[GlobalData] '.__FUNCTION__.'添加(如果发现内容重复请注意BUG)'.jsen($_new));
        }while(!$this->global->cas('TokenUser',$old,$new));

        unset($old);
        unset($_new);
        unset($new);
    }

    /**
     * @param $conn
     * @throws \Exception
     * 移除所有的 TokenUser->[]['uid']= $conn->_uid
     */
    public  function RemoveTokenUser($conn){
        do{
            $old=$new=$this->global->TokenUser;

            foreach ($new as $k=>$v){
                if($v['uid']==$conn->_uid){
                    FaceLog::info('[GlobalData] '.__FUNCTION__.'移除(如果发现内容重复请注意BUG)'.jsen($new[$k]));
                    unset($new[$k]);
                }
            }
        }while(!$this->global->cas('TokenUser',$old,$new));

    }

}
年代过于久远,无法发表回答
🔝