当前位置: 首页 > 后端技术 > PHP

《走在Swoole学习之路上》一个解耦的过程

时间:2023-03-30 03:32:26 PHP

Overview看了标题不知道作者想说什么。最近在看Swoole的内容,在封装框架的时候遇到一个关于解耦的问题。脱钩对大家来说并不陌生。这次解耦是一个关于监控事件和心跳检测的demo。我们直接来看问题。解决方案在swoole启动的时候,我想添加一些事件监听,比如RPC中的注册中心,我启动和提供什么服务和类似的场景等等,但是这只是一种事件监听,如果有超过一?比如我收到请求后,收到消息后,连接关闭后等等,你需要创建很多时间监控。此时,您可以在启动时注册所有事件。接下来,让我们看看代码有多简单。大致实现了。watch=[CONFIG_PATH,FRAME_PATH,APP_PATH];$reload->md5Flag=$reload->getMd5();#主动收集已经有事收集Listener目录$this->collecEvent();//定时器swoole_timer_tick(3000,function()use($reload){if($reload->reload()){$this->server->reload();//重新启动}});事件::触发('开始',['sss']);}/***收集事件*/publicfunctioncollecEvent(){$files=glob(EVENT_PATH."/*.php");如果(!empty($files)){foreach($filesas$dir=>$fileName){include"{$fileName}";$fileName=explode('/',$fileName);$className=explode('.',end($fileName))[0];$nameSpace='App\\Listener\\'.$类名;#可以放到配置文件中if(class_exists($nameSpace)){$obj=new$nameSpace;#获取自己定义的事件名,使用反射读取类文档注解$re=new\ReflectionClass($obj);if(strlen($re->getDocComment())<2){thrownew\Exception('事件名称未按规范定义');}else{preg_match("/@Listener\((.*)\)/i",$re->getDocComment(),$eventName);if(empty($eventName)){thrownew\Exception('事件名称未按规范定义');}#注册事件Event::register($eventName[1],[$obj,'handle']);}}}}}...}Swoole启动时,会调用collecEvent方法。collecEvent负责收集、注册指定目录,命名空间EVENT_PATH=APP_PATH.'/listener'下的方法循环遍历目录下的所有文件获取文件名拼接命名空间(命名空间可以放在Config等配置文件中)class_exists检查类是否存在ReflectionClass这里通过反射加注解的形式判断是否符合getDocComment()获取评论内容。/@Listener\((.*)\)/i匹配需要监听的事件。执行Event::register($event,$callback)进行事件注册接下来看Event类:classEvent{publicstatic$events=[];//事件注册/***@param$event事件名称*@param$callback事件回调*/publicstaticfunctionregister($event,$callback){$event=strtolower($event);//不区分大小写if(!isset(self::$events[$event])){self::$events[$event]=[];}self::$events[$event]=['callback'=>$callback];}//事件触发publicstaticfunctiontrigger($event,$params=[]){$event=strtolower($event);//不区分大小写if(isset(self::$events[$event])){call_user_func(self::$events[$event]['callback'],$params);返回真;}返回假;}}事件包含2个静态方法:事件注册,事件触发事件注册就是把一些事件放到$event属性中事件触发:验证事件是否存在,call_user_func()执行回调函数再看如何声明一个事件文件:upgrade('/');if($ret){//Config::get()$data=['method'=>'注册','serviceName'=>"Server",'ip'=>'0.0.0.0','port'=>9800,];$cli->push(json_encode($data));//心跳处理swoole_timer_tick(3000,函数()使用($cli){if($cli->errCode==0){$cli->push('11',WEBSOCKET_OPCODE_PING);}});}});}}这里应该继承一个接口类,必须实现handle()方法。您可以自己实现handle()方法。这里实现了一个类似于通知注册中心注册服务swoo的功能。le_timer_tick()使用毫秒级别的定时器处理心跳文档注释,并提供给反射捕获/***ClassStartListener*@packageApp\Listener*@Listener(start)*/callpublicfunctionstart(){...#主动收集已有事件收集监听器目录$this->collecEvent();...事件::触发('开始',['sss']);}感谢观看感谢您的耐心观看,希望对您有所帮助,也希望大家能提出不同的意见,找到更有效的完成方式,共同学习,谢谢!