surroundings

PHP_VERSION=7.4
laravel/framework: ^7.0

Static variable

  • The interpretation of static variables in many programming languages is: Variables with the same life cycle as the program are initialized only once
  • However, because PHP common operating environment is php-fpm mode, each end of the request process will be recycled, static variables are not permanent memory (will only take effect in the request)
  • PHP official website is introduced like this
Another important feature of variable scope is static variable. Static variables only exist in the local function domain, but their value is not lost when the program execution leaves this scope. Take a look at the following example: https://www.php.net/manual/zh/language.variables.scope.php

Preface

  • The project has the following pseudo-code logic: Because the json_data in the database is a json string, it does not need to be parsed every time it is retrieved. Using the static variable modifier makes the next visit need not be parsed again
<?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;
    }
}

Because I did not queue up to process asynchronous tasks before, the program has been okay. Until one day after I was in the queue, a colleague reported that abnormal data was reported. I quickly checked the log and found that the log management data in the queue was problematic, and then added more Do more, and finally locate this place.

  • Because Laravel queue using CLI mode of operation, this time processing tasks are running in the background
  • The code is loaded when the queue is started, until the queue process is killed, otherwise the code will not be updated,

Analyze the source code

  • Start order of the queue: php artisan queue:work
  • Find the startup file src\Illuminate\Queue\Console\WorkCommand.php is a Illuminate\Console\Command . When running artisan , it will run its handle method


  • In fact, it is to get the driver of the queue, and then go to worker to run the task, and pass a parameter once whether to run only one task, here we directly check the daemon method
  • Go src\Illuminate\Queue\Worker.php of daemon method
  • The first three lines of code to monitor the exit signal, and then actively exit the process
  • $lastRestart in the next line is to obtain a timestamp from the cache for the subsequent active exit process. This timestamp will only be reset php artisan queue:restart
  • So you can use the queue:restart command to stop the queue process (it will not automatically start the queue process, you can cooperate with Supervisor to automatically restart)
  • Next is an endless loop, to achieve the process is not killed
  • The first logical judgment is the maintenance mode that depends on whether the program has been started, forced operation, etc., is the pre-judgment of whether the queue task can continue to be processed
  • So we want to temporarily suspend the queue process. We can send a SIGUSR2 signal to the process. At this time, the queue process will stop the next time the current task is processed. When we want to continue processing, send a SIGCONT signal.
  • Then go to the getNextJob method to configure the queue driver (redis, database, etc.) to get the next task to be processed
  • If asynchronous extension is supported, registerTimeoutHandler has done some processing on the timeout of the task, if the task has timed out, then the task will be ended
  • In the next step, if there is no task taken out, then the program will sleep, otherwise it will run the task. Here you can go to see the actual running code of the task

  • Here we can directly look at the fire method, and then find the corresponding queue driver class, which inherits the parent's fire method
  • It actually reflects the job class and then calls its corresponding method
  • The last code block before the loop is stopIfNecessary , to see if the process needs to be terminated, the aforementioned queue:restart is also processed here


  • So when we use static variables, although each reflection instantiates a new job , but in fact job time to pick up the property model, static variables has not changed, which led to the front of that Bug

Original link https://www.shiguopeng.cn/archives/516


seth-shi
1.8k 声望231 粉丝

当神不再是我们的信仰,那么信仰自己吧,努力让自己变好,不辜负自己的信仰!