当前位置:首页 > WebSocket > 正文内容

workerman中捕获notice错误并抛出异常

陈杰4个月前 (01-15)WebSocket937

在workerman中出现了notice错误并不会中断程序运行,这是抛出一个无关紧要的提示,这显然与我们的程序设计初衷不符。

例如我们去获取数组中的一个key-value值,当key不存在的时候只是提示一个notice,而我们要把这个弄成一个异常。


研究了一下,set_error_handler方法可以实现我们想要的功能,来看一下代码吧。


在events.php中的代码

<?php
/**
 * 用于检测业务代码死循环或者长时间阻塞等问题
 * 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
 * 然后观察一段时间workerman.log看是否有process_timeout异常
 */

//declare(ticks=1);


use App\Service\MemberService;
use App\Service\InterviewService;
use \GatewayWorker\Lib\Gateway;
use think\facade\Db;
use \App\Library\MyException;
use  \App\Library\Rdb;

define('ping', 1);//ping 心跳  返回1
define('bind', 2);//bind 绑定  返回2
define('interview_admin_bind', 999);//集合室后台管理账户绑定


define('interview_member_join', 1001);//集合室-用户进入集合室
define('interview_member_leave', 1002);//集合室-用户离开集合室
define('interview_change_attribute', 1011);//集合室切换fixed 自由座位 和固定座位
define('interview_seat_order', 1012);//集合室座位排序
define('interview_seat_order_rand', 1013);//集合室座位排序-随机
define('interview_seat_change', 1014);//集合室座位排序-交换
define('interview_member_ban', 1015);//集合室-踢出用户
define('interview_member_voice', 1016);//集合室-用户禁言
define('interview_topic', 1017);//集合室出题
define('interview_voice_order', 1018);//传递麦序

define('interview_update', 1050);//集合室-更新频道属性
define('interview_send_msg', 1051);//集合室发送消息

class Events
{
    use \App\Library\Tools;

    public static function onWorkerStart()
    {
        \set_error_handler(function ($type, $msg) {
            var_dump($type, $msg);
            throw new MyException(400, $msg);
        }, E_NOTICE);

        Db::setConfig(\App\Config\Config::$db_config);
        Rdb::getInstance()->flushAll();
    }

    public static function onConnect($client_id)
    {
    }


    public static function onMessage($client_id, $message)
    {

        try {
            $message = json_decode($message, true);
            if (!is_array($message))
                return Gateway::sendToCurrentClient(self::error(400, '参数类型错误'));

            if ($message['type'] > 1000 and !isset($_SESSION['member_id'])) {
                return Gateway::closeClient($client_id, self::error(400, '未登录'));
            }

            switch ($message['type']) {
                case interview_admin_bind:
                    InterviewService::admin_bind($client_id, $message);
                    break;
                case interview_voice_order:
                    InterviewService::voice_order($client_id, $message);
                    break;
                case interview_topic:
                    InterviewService::topic($client_id, $message);
                    break;
                case interview_member_voice:
                    InterviewService::member_voice($client_id, $message);
                    break;
                case interview_member_ban:
                    InterviewService::member_ban($client_id, $message);
                    break;
                case interview_seat_change:
                    InterviewService::seat_change($client_id, $message);
                    break;
                case interview_seat_order_rand:
                    InterviewService::seat_order_rand($client_id, $message);
                    break;
                case interview_seat_order:
                    InterviewService::seat_order($client_id, $message);
                    break;
                case interview_send_msg:
                    InterviewService::send_msg($client_id, $message);
                    break;
                case interview_change_attribute:
                    InterviewService::change_attribute($client_id, $message);
                    break;
                case interview_update:
                    InterviewService::update($client_id, $message);
                    break;
                case interview_member_leave:
                    InterviewService::leave($client_id);
                    break;
                case interview_member_join:
                    InterviewService::join($client_id, $_SESSION['member_id'], $_SESSION['member'], $message);
                    break;
                case bind:
                    MemberService::bind($client_id, $message);
                    break;
                default :
                    return Gateway::sendToCurrentClient(self::success(1));
                    break;
            }

        } catch (Throwable $exception) {
            if ($exception instanceof MyException) {
                return Gateway::sendToCurrentClient(self::error($exception->type, $exception->getMessage(), $exception->getCode(), $exception->data));
            } else {
                return Gateway::sendToCurrentClient(self::error(400, $exception->getMessage()));
            }
        }
    }

    public static function onClose($client_id)
    {
        InterviewService::leave($client_id);
    }
}


Events.php文件主要看onMessage回调,我们通过传递给服务器的不同type参数作为路由凭据,然后调用不同的方法,处理业务。


在最外层有一个try catch来捕捉异常。注意是捕捉的Throwable 。这是Exception和Error两个不同异常的父类接口,但是并不包含notice和warning这类的错误,所以不能捕获。

所以一旦出现了这类错误并不会中断掉程序,那么要来判断例如key-value是否存在的这类情况就太痛苦了,到处都是isset。。。


    public static function onWorkerStart()
    {
        \set_error_handler(function ($type, $msg) {
            var_dump($type, $msg);
            throw new MyException(400, $msg);
        }, E_NOTICE);

        Db::setConfig(\App\Config\Config::$db_config);
        Rdb::getInstance()->flushAll();
    }


在来分析一下onWorkerStart()方法中,我们用set_error_handler来设置E_NOTICE类型的错误交给一个闭包来处理,该闭包抛出一个MyExcepetion异常,这个异常就是继承了Throwable接口,是可以被正常捕获的。同时中断程序。



扫描二维码至手机访问

扫描二维码推送至手机访问。

版权声明:本文由何烦过虎溪发布,如需转载请注明出处。

转载请注明出处:http://95shouyou.com/?id=32

分享给朋友:

相关文章

uniapp的websocket无法监听到onSocketClose和onSocketError

项目框架使用的前端uniapp+后端laravel+workerman websocket写的,主要功能是聊天室系统。但是在开发完成实际体验过程中发现了一个有趣的现象。websocket老是无缘无故的...

申研社websocket通信规定

一、建立连接和维持连接 1、建立连接 测试地址ws://api.shenyanshe.95shouyou.com/websocket 2、约定客户端发送数据格式为 json字符串,...

laravel利用websocket搭建一个简单的实时聊天系统

laravel利用websocket搭建一个简单的实时聊天系统

主要实现功能就是用户之间的的实时聊天。理一下业务逻辑:用户A给用户B发送消息>如果用户B在线,直接通过websocket推送消息,用户B接受到消息后写入前端数据库,并归档数据>如果用户B不...

workerman拆分events文件,实现常规编程习惯

workerman拆分events文件,实现常规编程习惯

wokerman的gateway很好用,自动解决了扩展性,分布式等较底层的东西。所有的逻辑代码只需要专注于events.php文件就行了,但是作者对于events编程的介绍比较少,如果从业多年的老手自...

nginx下反向代理开启websocket的wss服务

nginx下反向代理开启websocket的wss服务

通过nginx配置好网站的ssl证书后添加   location /wss  {    proxy_pass http://127.0.0.1:828...

Workerman-写一个简单的websocket双向通信并实现MVC,用来开发游戏服务器

最近在看Workerman,发现这是一个真的很好用的东西。文档相当丰富,而且大神walker很贴心,有问必答。下面记一下一个简单的基于GatewayWorker框架写的websocket的程序。传统的...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。