译文GitHub https://github.com/yuansir/diving-laravel-zh 原文链接 https://divinglaravel.com/task-scheduling/before-the-dive 想象这种情况,作为一个大型SaaS的开发者,您需要找到一种在周末每分钟选择10个随机客户的方式,并提供折扣升级,发送折扣的工作可能非常简单,但我们需要每分钟运行一次,为此我分享一些CRON的简要介绍给还不熟悉人。 CRON CRON是一个守护进程,它驻留在你的linux服务器中,大部分时间都没有唤醒,但是每一分钟它都会睁开双眼,看看是否运行任何给定的任务,你使用crontab文件与该守护进程通信,在大多数常见的设置文件可以位于/etc/crontab,crontab文件可能看起来像这样: 0 0 1 * * /home/full-backup 0 0 * * * /home/partial-backup 30 5 10 * * /home/check-subscriptions 在crontab文件中,每行表示一个计划任务作业,每个作业定义包含两部分: *****部分代表该作业运行的计时器。 第二部分是应运行的命令 CRON时序语法 5个星号按顺序排列如下: 一小时内的分钟 一天内的小时 一个月内的日期 一年内的月份 一周的内的天 示例: 0 0 1 * * 在第一个例子中,表示该工作应在每月,每个月的第一个天,上午12点,每小时第一分钟运行。 或者简单地说,它应该在每月的第一天上午12:00运行。 0 * * * * 在第二个例子中,表示该工作应该每小时运行一次。 30 5 10 * * 表示该工作应该在每个月10日上午5:30运行 这里还有一些其他的示例: * * * * 3 表示工作应该在星期三每分钟运行一次。 * * * * 1-5 表示该工作应该每周一至周五运行。 0 1,15 * * * 表示该工作应该每天在凌晨1点和3点运行两次。 */10 * * * * 表示该工作应该每10分钟运行一次。 所以我们为我们的工作注册一个cron任务? 是的,我们可以在我们的crontab文件中注册:

阅读全文

译文GitHub https://github.com/yuansir/diving-laravel-zh 原文链接https://divinglaravel.com/queue-system/pushing-jobs-to-queue 有几种方法可以将作业推送到队列中: Queue::push(new InvoiceEmail($order)); Bus::dispatch(new InvoiceEmail($order)); dispatch(new InvoiceEmail($order)); (new InvoiceEmail($order))->dispatch(); 调用Queue facade是对应用程序使用的队列驱动的调用,如果你使用数据库队列驱动,调用push方法是调用Queue\DatabaseQueue类的push方法。 有几种有用的方法可以使用: // 将作业推送到特定的队列 Queue::pushOn('emails', new InvoiceEmail($order)); // 在给定的秒数之后推送作业 Queue::later(60, new InvoiceEmail($order)); // 延迟后将作业推送到特定的队列 Queue::laterOn('emails', 60, new InvoiceEmail($order)); // 推送多个作业 Queue::bulk([ new InvoiceEmail($order), new ThankYouEmail($order) ]); // 推送特定队列上的多个作业 Queue::bulk([ new InvoiceEmail($order), new ThankYouEmail($order) ], null, 'emails'); 调用这些方法之后,所选择的队列驱动会将给定的信息存储在存储空间中,供workers按需获取。 使用命令总线 使用命令总线调度作业进行排队可以给你额外控制权; 您可以从作业类中设置选定的connection, queue, and delay 来决定命令是否应该排队或立即运行,在运行之前通过管道发送作业,实际上你甚至可以从你的作业类中处理整个队列过程。 Bug facade代理到Contracts\Bus\Dispatcher 容器别名,此别名解析为Bus\Dispatcher内的Bus\BusServiceProvider的一个实例: $this->app->singleton(Dispatcher::class, function ($app) { return new Dispatcher($app, function ($connection = null) use ($app) { return $app[QueueFactoryContract::class]->connection($connection); }); }); 所以Bus::dispatch() 调用的 dispatch() 方法是 Bus\Dispatcher 类的:

阅读全文

原文链接https://divinglaravel.com/queue-system/preparing-jobs-for-queue Every job we push to queue is stored in some storage space sorted by the order of execution, this storage place could be a MySQL database, Redis store, or a 3rd party service like Amazon SQS. 我们推送到队列的每个作业都存储在按执行顺序排序的某些存储空间中,该存储位置可以是MySQL数据库,Redis存储或像Amazon SQS这样的第三方服务。 Later in this dive we’re going to explore how workers fetch these jobs and start executing them, but before that let’s see how we store our jobs, here are the attributes we keep for every job we store:

阅读全文

译文GitHub https://github.com/yuansir/diving-laravel-zh 原文链接https://divinglaravel.com/queue-system/before-the-dive Laravel接收请求,做一些工作,然后向用户返回响应,这是处理请求的Web服务器的正常同步工作流程,但有时您需要在后台执行不中断或减慢的一些流程,例如在订单之后向用户发送发票电子邮件,你不想让用户等待邮件服务器接收请求,构建电子邮件消息,然后分派给用户,你只要向屏幕发送“谢谢!”给用户,电子邮件在后台准备和发送,他继续做他自己的事。 Laravel配有内置的队列系统,可帮助您在后台运行任务,并通过简单的API来配置系统在不同情况下起作用。 您可以在 config/queue.php中管理队列配置,默认情况下它有使用不同队列驱动的几个连接,您可以看到项目中可以有多个队列连接,也可以使用多个队列驱动程序。 我们将研究不同的配置,但请先看看API: Queue::push(new SendInvoice($order)); return redirect('thank-you'); 队列Queue facade 是 queue 容器别名,如果我们看看Queue\QueueServiceProvider ,我们可以看到这个别名是如何注册的: protected function registerManager() { $this->app->singleton('queue', function ($app) { return tap(new QueueManager($app), function ($manager) { $this->registerConnectors($manager); }); }); } 所以 Queue facade 代理到在容器中注册为 Queue\QueueManager 类的单例,我们还将连接器注册到Laravel所支持使用的registerConnectors()的不同队列驱动程序中: public function registerConnectors($manager) { foreach (['Null', 'Sync', 'Database', 'Redis', 'Beanstalkd', 'Sqs'] as $connector) { $this->{"register{$connector}Connector"}($manager); } } 该方法只需调用注册 register{DriverName}Connector方法,例如注册一个Redis连接器: protected function registerRedisConnector($manager) { $manager->addConnector('redis', function () { return new RedisConnector($this->app['redis']); }); } addConnector() 方法将值存储到 QueueManager::$connectors 类属性。 连接器只是一个类,它包含一个 connect() 方法,它根据需要创建所需驱动的一个实例,方法看起来像在Queue\Connectors\RedisConnector里面:

阅读全文

Larvae的配置都在config目录下非常方便管理,可以通过config()帮助函数来实现对配置项目的设置和获取,同时用 DotEnv 来实现项目内环境变量的控制,非常强大和方便。我们在日常开发中如果没有使用Laravel框架,比如写一些脚本,或者自己写的项目框架,但是想集成这样的配置管理。这里就讲讲如何集成illuminate/config 到自己的项目中实现Laravel那种config配置。 首先通过composer来安装illuminate/config 和 vlucas/phpdotenv,composer.json如下: { "require": { "illuminate/config": "^5.2", "vlucas/phpdotenv": "^2.3" }, "autoload": { "psr-4": { "App\\": "app/" } } } 创建.env文件,同时创建对应环境的env文件,为了解决不同环境加载不同配置的问题。比如: .env 里面只写入当前环境,比如local,develop , production .local.env 表示本地开发环境的配置项 .develop.env 表示测试环境的配置项 .production 表示生产环境的配置项 关于Laravel在不同环境加载不同配置的方法可以参考我的这篇文章《Laravel在不同的环境调用不同的配置文件》 我们在新建一个配置文件,比如 config/app.php 或者 config/path/to.php 加载配置文件,新建 app/Config.php <?php namespace App; use Illuminate\Config\Repository; use Illuminate\Filesystem\Filesystem; class Config extends Repository { public function loadConfigFiles($path) { $fileSystem = new Filesystem(); if (!

阅读全文

Laravel Tips 之 forelse

我们在Laravel Blade模板中经常在循环输出前先判断一下集合是否有值,然后再foreach 比如: @if ($posts->count()) @foreach ($posts as $post) <p>This is post {{ $user->id }}</p> @endforeach @else <p>No posts found.</p> @endif 其实在Laravel Blade中可以使用forelse: @forelse ($posts as $post) <p>This is post {{ $post->id }}</p> @empty <p>No posts found.</p> @endforelse 它的实现可以在Illuminate/View/Compilers/BladeCompiler.php找到: /** * Compile the forelse statements into valid PHP. * * @param string $expression * @return string */ protected function compileForelse($expression) { $empty = '$__empty_'.++$this->forelseCounter; return "<?php {$empty} = true; foreach{$expression}: {$empty} = false; ?

阅读全文

Docker 快速入门指引

Docker是什么? Docker是 Docker.Inc 公司开源的一个基于 LXC技术之上构建的Container容器引擎,基于Go语言并遵从Apache2.0协议开源。 开发者可以搭建他们的应用仅仅一次,就能保证让这个应用保持一致的跑在任何地方。运营人员可以将他们的服务器配置一遍,就能跑任何应用。 What is Docker’s architecture? Docker uses a client-server architecture. The Docker *client* talks to the Dockerdaemon, which does the heavy lifting of building, running, and distributing your Docker containers. Both the Docker client and the daemon *can* run on the same system, or you can connect a Docker client to a remote Docker daemon. The Docker client and daemon communicate via sockets or through a RESTful API.

阅读全文

作者的图片

Ryan是菜鸟 | LNMP技术栈笔记

一步一个脚印,一直在路上! LNMP技术栈,web架构学习笔记

菜鸟码农

南京