laravel 计划任务的实现原理
laravel的计划任务确实好用,之前就计划吧这个功能研究下,自己造一个给tp5使用
但是研究之后发现,容器这个概念吧代码变得比较抽象,代码读起来的难度比较高
然后研究之后发现除了phpstorm可以追踪大部分代码之外,其他的ide代码追踪功能真的很一般,比如我一般使用NetBeans
看官网在开发9.0不知道啥时候了,等等吧
2018年7月30日11:01:42
补充:laravel主要使用的是容器来实现功能的注册,绑定,使用的 ,但是我逐渐发现laravel的慢的原因估计也是因为这个,虽然容器实现了对象池,但是大多数的调用还是new,理论上都是在对象池只有一个,但是new的东西太多
使用起来更容易了,但是代码可读性也越差了,很多IDE都没办法追踪源代码了
现在对于容器的好与坏,确实有待商榷,现在tp也开始学习这套东西,不知是好是坏
laravel的实现原理就是利用 crontab 每分钟执行一次
计算任务的所需要执行的时间,加上互斥保证只执行一次,防止其他用户执行, 判断是否已经执行过
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
这个就是官方提供的执行计划任务的crontab脚本
提供部分代码参考
public function command($command, array $parameters = []) { if (class_exists($command)) { $command = Container::getInstance()->make($command)->getName(); } return $this->exec( Application::formatCommandString($command), $parameters ); }
执行普通命令 php artisan xxxTask
php artisan schedule:run
class CronExpression { const MINUTE = 0; const HOUR = 1; const DAY = 2; const MONTH = 3; const WEEKDAY = 4; const YEAR = 5; /** * @var array CRON expression parts */ private $cronParts; /** * @var FieldFactory CRON field factory */ private $fieldFactory; /** * @var int Max iteration count when searching for next run date */ private $maxIterationCount = 1000; /** * @var array Order in which to test of cron parts */ private static $order = array(self::YEAR, self::MONTH, self::DAY, self::WEEKDAY, self::HOUR, self::MINUTE); /** * Factory method to create a new CronExpression. * * @param string $expression The CRON expression to create. There are * several special predefined values which can be used to substitute the * CRON expression: * * `@yearly`, `@annually` - Run once a year, midnight, Jan. 1 - 0 0 1 1 * * `@monthly` - Run once a month, midnight, first of month - 0 0 1 * * * `@weekly` - Run once a week, midnight on Sun - 0 0 * * 0 * `@daily` - Run once a day, midnight - 0 0 * * * * `@hourly` - Run once an hour, first minute - 0 * * * * * @param FieldFactory $fieldFactory Field factory to use * * @return CronExpression */ public static function factory($expression, FieldFactory $fieldFactory = null) { $mappings = array( '@yearly' => '0 0 1 1 *', '@annually' => '0 0 1 1 *', '@monthly' => '0 0 1 * *', '@weekly' => '0 0 * * 0', '@daily' => '0 0 * * *', '@hourly' => '0 * * * *' ); if (isset($mappings[$expression])) { $expression = $mappings[$expression]; } return new static($expression, $fieldFactory ?: new FieldFactory()); }
/** * Get the next or previous run date of the expression relative to a date * * @param string|\DateTime $currentTime Relative calculation date * @param int $nth Number of matches to skip before returning * @param bool $invert Set to TRUE to go backwards in time * @param bool $allowCurrentDate Set to TRUE to return the * current date if it matches the cron expression * * @return \DateTime * @throws \RuntimeException on too many iterations */ protected function getRunDate($currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false) { if ($currentTime instanceof DateTime) { $currentDate = clone $currentTime; } elseif ($currentTime instanceof DateTimeImmutable) { $currentDate = DateTime::createFromFormat('U', $currentTime->format('U')); $currentDate->setTimezone($currentTime->getTimezone()); } else { $currentDate = new DateTime($currentTime ?: 'now'); $currentDate->setTimezone(new DateTimeZone(date_default_timezone_get())); } $currentDate->setTime($currentDate->format('H'), $currentDate->format('i'), 0); $nextRun = clone $currentDate; $nth = (int) $nth; // We don't have to satisfy * or null fields $parts = array(); $fields = array(); foreach (self::$order as $position) { $part = $this->getExpression($position); if (null === $part || '*' === $part) { continue; } $parts[$position] = $part; $fields[$position] = $this->fieldFactory->getField($position); } // Set a hard limit to bail on an impossible date for ($i = 0; $i < $this->maxIterationCount; $i++) { foreach ($parts as $position => $part) { $satisfied = false; // Get the field object used to validate this part $field = $fields[$position]; // Check if this is singular or a list if (strpos($part, ',') === false) { $satisfied = $field->isSatisfiedBy($nextRun, $part); } else { foreach (array_map('trim', explode(',', $part)) as $listPart) { if ($field->isSatisfiedBy($nextRun, $listPart)) { $satisfied = true; break; } } } // If the field is not satisfied, then start over if (!$satisfied) { $field->increment($nextRun, $invert, $part); continue 2; } } // Skip this match if needed if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) { $this->fieldFactory->getField(0)->increment($nextRun, $invert, isset($parts[0]) ? $parts[0] : null); continue; } return $nextRun; } // @codeCoverageIgnoreStart throw new RuntimeException('Impossible CRON expression'); // @codeCoverageIgnoreEnd }
判断需要执行的任务是否是当前任务
namespace Illuminate\Console\Scheduling; use Illuminate\Contracts\Cache\Repository as Cache; class CacheMutex implements Mutex { /** * The cache repository implementation. * * @var \Illuminate\Contracts\Cache\Repository */ public $cache; /** * Create a new overlapping strategy. * * @param \Illuminate\Contracts\Cache\Repository $cache * @return void */ public function __construct(Cache $cache) { $this->cache = $cache; } /** * Attempt to obtain a mutex for the given event. * * @param \Illuminate\Console\Scheduling\Event $event * @return bool */ public function create(Event $event) { return $this->cache->add( $event->mutexName(), true, $event->expiresAt ); } /** * Determine if a mutex exists for the given event. * * @param \Illuminate\Console\Scheduling\Event $event * @return bool */ public function exists(Event $event) { return $this->cache->has($event->mutexName()); } /** * Clear the mutex for the given event. * * @param \Illuminate\Console\Scheduling\Event $event * @return void */ public function forget(Event $event) { $this->cache->forget($event->mutexName()); } }
互斥 的实现
protected function expressionPasses() { $date = Carbon::now(); if ($this->timezone) { $date->setTimezone($this->timezone); } return CronExpression::factory($this->expression)->isDue($date->toDateTimeString()); }
是否过期
自己实现一个计划任务
https://www.cnblogs.com/zx-admin/p/15641124.html
QQ一群 247823727
QQ二群 166427999
博客文件如果不能下载请进群下载
如果公司项目有技术瓶颈问题,请联系↓↓
如果需要定制系统开发服务,请联系↓↓
技术服务QQ: 903464207
QQ二群 166427999
博客文件如果不能下载请进群下载
如果公司项目有技术瓶颈问题,请联系↓↓
如果需要定制系统开发服务,请联系↓↓
技术服务QQ: 903464207