Hyperf-事件机制+异常处理
Hyperf-事件机制+异常处理
标签(空格分隔): php, hyperf
异常处理器
在 Hyperf 里,业务代码都运行在 Worker 进程 上,也就意味着一旦任意一个请求的业务存在没有捕获处理的异常的话,都会导致对应的 Worker 进程 被中断退出,这对服务而言也是不能接受的,捕获异常并输出合理的报错内容给客户端也是更加友好的。
我们可以通过对各个 server 定义不同的 异常处理器(ExceptionHandler),一旦业务流程存在没有捕获的异常,都会被传递到已注册的 异常处理器(ExceptionHandler) 去处理。
异常记录到日志
// 日志类
<?php
declare(strict_types=1);
namespace App\Utils;
class NativeLog
{
private $dirPath;
public function __construct()
{
$this->dirPath = BASE_PATH . '/runtime/logs/' . date("Ymd") . '/';
if (!is_dir($this->dirPath)) {
mkdir($this->dirPath, 0777, true);
}
}
public function error(string $data) : bool
{
$data = "[ ERROR ] [" . date("Y-m-d H:i:s") . "] " . $data . PHP_EOL;
file_put_contents($this->dirPath . "error.log", $data, FILE_APPEND);
return true;
}
}
hyperf 本身就实现了异常类的接管,如果有异常会打印到控制台输出。

// 增加异常信息的记录日志
/**
* 记录文本异常日志
* @param Throwable $throwable
*/
public function writeLog(Throwable $throwable)
{
$AppExceptionLog['server'] = "http";
$AppExceptionLog['method'] = $this->request->getMethod();
$AppExceptionLog['path'] = $this->request->url();
$AppExceptionLog['params'] = $this->request->all();
$AppExceptionLog['file'] = $throwable->getFile();
$AppExceptionLog['line'] = $throwable->getLine();
$AppExceptionLog['message'] = $throwable->getMessage();
(new NativeLog())->error(json_encode($AppExceptionLog));
}
日志记录效果

但是有个问题,try catch 捕获的代码如果有异常就不会记录
引入事件机制
事件模式是一种经过了充分测试的可靠机制,是一种非常适用于解耦的机制,分别存在以下 3 种角色:
事件(Event) 是传递于应用代码与 监听器(Listener) 之间的通讯对象
监听器(Listener) 是用于监听 事件(Event) 的发生的监听对象
事件调度器(EventDispatcher) 是用于触发 事件(Event) 和管理 监听器(Listener) 与 事件(Event) 之间的关系的管理者对象
用通俗易懂的例子来说明就是,假设我们存在一个 UserService::register() 方法用于注册一个账号,在账号注册成功后我们可以通过事件调度器触发 UserRegistered 事件,由监听器监听该事件的发生,在触发时进行某些操作,比如发送用户注册成功短信,在业务发展的同时我们可能会希望在用户注册成功之后做更多的事情,比如发送用户注册成功的邮件等待,此时我们就可以通过再增加一个监听器监听 UserRegistered 事件即可,无需在 UserService::register() 方法内部增加与之无关的代码。
代码示例
// 新增异常事件
<?php
declare(strict_types=1);
namespace App\Event;
/**
* 系统异常事件
* Class AppException
* @package App\Event
*/
class AppException
{
public $throwable;
public function __construct($throwable)
{
$this->throwable = $throwable;
}
}
// 新增异常事件监听器
<?php
declare(strict_types=1);
namespace App\Listener;
use App\Event\AppException;
use App\Utils\NativeLog;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
use Hyperf\HttpServer\Contract\RequestInterface;
/**
* 异常事件监听器
* Class AppExceptionListener
* @package App\Listener
* @Listener()
*/
class AppExceptionListener implements ListenerInterface
{
/**
* @Inject()
* @var RequestInterface
*/
private $request;
/**
* @Inject()
* @var NativeLog
*/
private $nativeLog;
/**
* @inheritDoc
*/
public function listen(): array
{
// TODO: Implement listen() method.
// 返回一个该监听器要监听的事件数组,可以同时监听多个事件
return [
AppException::class,
];
}
/**
* @param object $throwable
*/
public function process(object $throwable)
{
$throwable = $throwable->throwable;
$request = $this->request;
$AppExceptionLog['server'] = "http";
$AppExceptionLog['method'] = $request->getMethod();
$AppExceptionLog['path'] = $request->url();
$AppExceptionLog['params'] = $request->all();
$AppExceptionLog['file'] = $throwable->getFile();
$AppExceptionLog['line'] = $throwable->getLine();
$AppExceptionLog['message'] = $throwable->getMessage();
$this->nativeLog->error(json_encode($AppExceptionLog));
}
}
// 控制器
<?php
declare(strict_types=1);
namespace App\Admin\Controller;
use App\Admin\Model\UserModel;
use App\Admin\Service\UserService;
use App\Event\AppException;
use App\Rpc\Inter\UserServiceInter;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\Utils\Context;
use Psr\EventDispatcher\EventDispatcherInterface;
use function _HumbugBoxa5be08ba8ddb\React\Promise\Stream\first;
/**
* 用户控制器
* Class UserController
* @package App\Admin\Controller
* @AutoController()
*/
class UserController extends AdminBaseController
{
/**
* @Inject
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* 异常测试
*/
public function exception()
{
try {
array_column();
} catch (\Throwable $throwable) {
$this->eventDispatcher->dispatch(new AppException($throwable));
}
}
Hyperf-事件机制+异常处理的更多相关文章
- 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)
前言 这篇博客有点长,如果你是高手请您读一读,能对其中的一些误点提出来,以免我误人子弟,并且帮助我提高 如果你是javascript菜鸟,建议您好好读一读,真的理解下来会有不一样的收获 在下才疏学浅, ...
- tkinter事件机制
一.tkinter.Event tkinter的事件机制跟js是一样的,也是只有一个Event类,这个类包罗万象,集成了键盘事件,鼠标事件,包含各种参数. 不像java swing那种强类型事件,sw ...
- [解惑]JavaScript事件机制
群里童鞋问到关于事件传播的一个问题:“事件捕获的时候,阻止冒泡,事件到达目标之后,还会冒泡吗?”. 初学 JS 的童鞋经常会有诸多疑问,我在很多 QQ 群也混了好几年了,耳濡目染也也收获了不少,以后会 ...
- Atitit 数据库的事件机制--触发器与定时任务attilax总结
Atitit 数据库的事件机制--触发器与定时任务attilax总结 1.1. 事件机制的图谱1 2. 触发器的类型2 3. 实现原理 After触发器 Vs Instead Of触发器2 3.1. ...
- 深入浅出iOS事件机制
原文地址: http://zhoon.github.io/ios/2015/04/12/ios-event.html 本文章将讲解有关iOS事件的传递机制,如有错误或者不同的见解,欢迎留言指出. iO ...
- Java 事件机制
java事件机制包括三个部分:事件.事件监听器.事件源. 1.事件.一般继承自java.util.EventObject类,封装了事件源对象及跟事件相关的信息,用于listener的相应的方法之中,作 ...
- Angular $scope和$rootScope事件机制之$emit、$broadcast和$on
Angular按照发布/订阅模式设计了其事件系统,使用时需要“发布”事件,并在适当的位置“订阅”或“退订”事件,就像邮箱里面大量的订阅邮件一样,当我们不需要时就可以将其退订了.具体到开发中,对应着$s ...
- JavaScript 详说事件机制之冒泡、捕获、传播、委托
DOM事件流(event flow )存在三个阶段:事件捕获阶段.处于目标阶段.事件冒泡阶段. 事件捕获(event capturing):通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会 ...
- DOM事件机制进一步理解
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
随机推荐
- DEDECMS:删除DEDE自带的织梦链方法
在include/taglib/flinktype.lib.php里删除掉如下代码: $dedecms = false; $dedecms->id = 999; $dedecms->typ ...
- 用到的API整理
时间 淘宝 http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp 获取时间戳,调用效果 { "api" ...
- STM32通过rosserial接入ROS通讯开发
作者:良知犹存 转载授权以及围观:欢迎添加微信公众号:羽林君 前言 主题:串口是一种设备间常用的通讯接口,rosserial将串口字符数据转发到标准ROS网络,并输出到rosout和其日志文件.本文将 ...
- Codeforces Round #647 (Div. 2) - Thanks, Algo Muse! C. Johnny and Another Rating Drop (规律,二进制)
题意:有一个正整数\(n\),要求写出所有\(1\)~\(n\)的二进制数,统计相邻的两个二进制同位置上不同数的个数. 题解:打表找规律,不难发现: \(00000\) \(00001\) ...
- Balanced Numbers SPOJ - BALNUM
代码+注释 1 //我感觉这道题最扯的就是我因为输入而TLE了半天,懵逼死了,想破脑袋也没想到因为输入TLE了半天 2 //题意:求区间内数字满足"奇数各数出现偶数次,偶数各数出现奇数次&q ...
- 国产网络测试仪MiniSMB - 利用Ctrl+c/Ctrl+v/Ctrl+a快速编辑数据流
国产网络测试仪MiniSMB(www.minismb.com)是复刻smartbits的IP网络性能测试工具,是一款专门用于测试智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此以太 ...
- Redis 穿透 & 击穿 & 雪崩
原文:https://www.cnblogs.com/binghe001/p/13661381.html 缓存穿透 如果在请求数据时,在缓存层和数据库层都没有找到符合条件的数据,也就是说,在缓存层和数 ...
- woj1005-holding animals-01pack woj1006-Language of animals-BFS
title: woj1005-holding animals-01pack date: 2020-03-05 categories: acm tags: [acm,woj,pack] 01背包.中等题 ...
- anaconda python3.7 安装 tensorflow-gpu 2.0.0 beta1 配置PyCharm
参考tensorflow 公众号<tensorflow2.0 安装指南> https://mp.weixin.qq.com/s/7rNXFEC5HYe91RJ0-9CKdQ # 1. NV ...
- codeforces 1036B - Diagonal Walking v.2【思维+构造】
题目:戳这里 题意:起点(0,0),终点(n,m),走k步,可以走8个方向,问能不能走到,能走到的话最多能走多少个斜步. 解题思路:起点是固定的,我们主要分析终点.题目要求走最多的斜步,斜步很明显有一 ...