Worker储存客户端连接、跨进程通讯的问题研究

Worker储存客户端连接、跨进程通讯的问题研究

1.首先,该wiki是基于公司的项目《[[室内导航解决方案]]》的构架上,对服务端代码的更改。

2. 其次本人是ue4、c++出生,对php从来没有了解过。在了解workman之前我对php的认识只是知道使用php连接数据库,然后通过get返回数据给c++使用。对php的语法,代码规范等都不了解。所以有哪些地方不对的欢迎指正。

一:worker单进程时,数组变量的共用问题

需求:我们在处理客户端的连接时需要将客户端链接分为微信端和Web端两大类,同时它们是一一对应的,即一个微信端需要对应一个web端。
思路:我们的思路是建立两个数组($WX=array();$Web=array())。将所有的微信连接存在$WX里面,将所有的Web连接存在Web里面。
遇到的问题:这两个数组并没有一直存储起来。连接到来时明确的存进了数组里面,但消息到来时这两个数组都为空。

解决办法:①将这两个数组定义到worker类里面去。②:在自己的运行类中每个函数的第一句加上“global $ws_worker;”使我们的$ws_worker成为全局的。(用c++的语法,简直难以理解这种写法!)

//在库文件worker.php里面添加、声明两个数组
//定义两个数组用于存储所有的WX连接,所有的Web连接
    public $WX=array();
    public $Web=array();
//在我们自己写的run.php里面
//每个函数里面申明我们的全局worker
$ws_worker->onMessage = function($connection, $data)
{
   global $ws_worker;
   ......       
}
      我们在这样处理后,可以很好的保存这些链接,方便当一个wx客户端消息到来时,我们找到对应的Web进行消息转发。但是还是只是局限于$ws_worker->count = 1;开启一个进程时。

二: worker多个进程时,进程间的相互通讯

需求:我们在利用worker做服务端时,针对连接量比较少时,采用$ws_worker->count = 1;完全可以处理。但是如果说遇到连接量比较大项目,那么$ws_worker->count = 4;还是很有必要的。
思路:采用基于worker的组件 Channel进行各个线程间的通讯。Channel就是两个php文件Client.php、Server.php。下载就可以用了
解决办法:①:在worker进程启动时“onWorkerStart”这个函数里面进行事件的注册(我理解为注册)。②在需要线程间通讯时我们对注册的对应事件进行调用“\Channel\Client::publish('Findandclose', $event_data);”   
// 每个worker进程启动时(这个函数是进程间通讯,事件注册用)
$ws_worker->onWorkerStart = function($ws_worker)
{
    //需要跨线程做的事都写在这里
    // Channel客户端连接到Channel服务端
    Channel\Client::connect('127.0.0.1', 2206);
    // 注册"Findandforward"事件,用于消息转发时当前进程找不到对应连接时调用
    Channel\Client::on('Findandforward', function($event_data)use($ws_worker){
      if($event_data->type == 'Message')
      {
        if($event_data->from == 'WX')
        {
               foreach ($ws_worker->Web as $everyweb) 
               {
                 if($event_data->openid == $everyweb['openid'])
                 {
                   $everyweb['connect']->send($event_data->data);
                   break;
                 }
		       }
        }
      }
    });
    // 注册"Findandclose"事件,用于连接断开时当前进程找不到对应连接
      Channel\Client::on('Findandclose', function($event_data)use($ws_worker){
      if($event_data['Who_closed']== 'WX_closed')
      {
          foreach( $ws_worker->Web as $key => $value ) {
            if($value['openid'] ==$event_data['openid'])
            {
              $ws_worker->Web[$key]['connect']->close();
              array_splice($ws_worker->Web,$key,1);//重置数组
              var_dump($ws_worker->Web);
              savelog("在其它进程找到了需要关闭的Web连接"."  ".$event_data['openid']);
              break;
            }
          }
      }
      if($event_data['Who_closed']== 'Web_closed')
      {
          foreach( $ws_worker->WX as $key => $value ) {
            if($value['openid'] ==$event_data['openid'])
            {
              $ws_worker->WX[$key]['connect']->close();
              array_splice($ws_worker->WX,$key,1);//重置数组
              var_dump($ws_worker->WX);
              savelog("在其它进程找到了需要关闭的WX连接"."  ".$event_data['openid']);
              break;
            }
          }
      }  
    });
};
//调用我们的跨线程事件
      if($jsondata->from == 'WX')
      {          
          savelog("WX is sen Message the WX id is"."   ".$jsondata->openid);
           //循环$Web匹配本次消息的openid对应有就将小程序的消息转发给web
            $isfind_theweb=false;//定义一个Bool变量,判断在当前线程是否找到对应的连接
            foreach ($ws_worker->Web as $everyweb) {
  			if($jsondata->openid == $everyweb['openid'])
            {
              $isfind_theweb=true;//当前线程找到了对应连接
                $everyweb['connect']->send($jsondata->data);
                break;
            }
		}
        if(!$isfind_theweb)//如果在这个进程没有找到对应的web,我们发送全局事件
        {
          savelog("当前进程未找到匹配连接");
          $event_data = $jsondata;
          // 向所有worker进程发布Findandforward事件
          \Channel\Client::publish('Findandforward', $event_data);//Findandforward是我们要调用的事件名,$event_data是我们要传递的参数
        }   
      }

 总结

      workerman使用好了可以为我们的很多项目服务,之后websocket通讯这块,服务端基本都会用到,还是非常有用的一个东西。当然这只是很小的部分。本人初次接触php,如果大家关于上面的问题有更好的解决办法,欢迎给我留言。关于其它方面的东西希望大家多多记录多多分享。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萤火1129

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值