最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • static 静态变量引起 Laravel 中队列一个 Bug

    正文概述 转载于:掘金(WaitMoonMan)   2021-07-06   407

    环境

    php_VERSION=7.4
    laravel/framework: ^7.0
    

    静态变量

    • 很多编程语言对于静态变量的解释都是: 与程序有着相同生命周期的变量, 只初始化一次
    • 不过由于PHP的常用运行环境是php-fpm模式,每次请求结束进程就会被回收, 静态变量不会常驻内存(只会在此次请求生效)
    • PHP 官网是这么介绍的

    前言

    • 项目中有以下伪代码逻辑: 因为数据库中的json_data是一个json字符串,所以不必每次获取都解析, 使用static变量修饰符使得下一次访问不需要再次解析
    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class AttributeRequestLog extends Model
    {
    
        public function getJsonData($key)
        {
            static $jsonData;
            if (is_null($jsonData)) {
                $jsonData = json_decode($this->attributes['json_data'], true);
            }
    
            return $jsonData[$key] ?? null;
        }
    }
    
    

    因为之前没上队列处理异步任务, 程序一直没问题. 直到某一天上了队列之后, 有同事反馈, 有异常数据上报. 赶紧排查了一下日志, 发现队列中的日志打点数据有问题,随后增加更多打点, 最后定位到了这个地方.

    • 由于Laravel的队列采用CLI运行模式, 这时候处理的任务都是后台运行
    • 队列启动时载入代码, 直到队列进程被杀死, 否则代码也不会更新,

    分析源码

    • 队列的启动命令: php artisan queue:work
    • 找到启动文件src\Illuminate\Queue\Console\WorkCommand.php是一个继承于Illuminate\Console\Command的类,运行artisan的时候, 会运行其的handle方法

    static 静态变量引起 Laravel 中队列一个 Bug static 静态变量引起 Laravel 中队列一个 Bug

    • 实际上是拿到队列的驱动,然后转到worker去运行任务, 传递了一个参数once是否只运行一个任务,这里我们直接查看daemon方法
    • 转到src\Illuminate\Queue\Worker.phpdaemon方法

    static 静态变量引起 Laravel 中队列一个 Bug

    • 前面三行代码去监听退出信号,然后主动退出进程
    • 下一行的$lastRestart是缓存中获取一个时间戳,用于之后的主动退出进程,这个时间戳只会被php artisan queue:restart重置
    • 所以可以用queue:restart这条命令去停止队列进程(并不会自动启动队列进程,可以配合Supervisor来自动重启)
    • 接下来是一个死循环,来达到进程不被杀死
    • 第一个逻辑判断死看程序是否已经启动的维护模式,强制运行等等,就是队列任务是否能继续处理的前置判断
    • 所以我们想临时暂停队列进程,可以向进程发送一个SIGUSR2信号,这时候队列进程处理完当前任务下一次就会停止,当想继续处理的时候,再发送一个SIGCONT信号
    • 然后到getNextJob这个方法去配置的队列驱动(redis, database 等等)里获取下一个待处理的任务
    • 如果支持异步扩展,registerTimeoutHandler对任务的超时做了一些处理, 如果任务超时了, 那么就结束任务
    • 下一步如果取出来的没任务, 那么就程序休眠, 否则就运行任务, 这里可以去看一下任务的实际运行代码

    static 静态变量引起 Laravel 中队列一个 Bug static 静态变量引起 Laravel 中队列一个 Bug

    • 这里我们直接看fire方法即可, 然后找到对应的队列驱动类,继承了父级的fire方法

    static 静态变量引起 Laravel 中队列一个 Bug

    • 实际上是反射了这个job类然后调用它对应的方法
    • 循环前的最后一个代码块就是stopIfNecessary, 看进程是否需要终止, 前面说的queue:restart也是在这里处理

    • 所以当我们使用静态变量的时候,虽然每次反射实例化了一个新的job,但实际上job去拿模型的属性的时候,static变量是一直没有发生变化的,这就导致了前面说的Bug

    原文链接www.shiguopeng.cn/archives/51…


    起源地下载网 » static 静态变量引起 Laravel 中队列一个 Bug

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元