dusterio / laravel-aws-worker

在 AWS Elastic Beanstalk 工作器中运行 Laravel(或 Lumen)任务和队列监听器

v1.0.02 2024-05-29 05:54 UTC

README

Code Climate Total Downloads Latest Stable Version Latest Unstable Version License

在 AWS Elastic Beanstalk 工作器中运行 Laravel 任务和队列监听器

我们已停止对 Lumen 的未来支持,但您仍然可以使用 v0.1.40 版本用于 Lumen。

概述

Laravel 文档建议使用 supervisor 作为队列工作进程和 *IX cron 作为计划任务。然而,当将您的应用程序部署到 AWS Elastic Beanstalk 时,这两个选项都不可用。

此软件包帮助您在 AWS 工作环境上运行 Laravel 作业。

Standard Laravel queue flow AWS Elastic Beanstalk flow

依赖

  • PHP >= 5.5
  • Laravel >= 5.1

计划任务 - 选项 1

第一个选项是使用 Kernel.php 作为计划,并每分钟运行 Laravel 计划运行器。你还记得 Laravel 文档建议如何调用任务调度器吗?没错,通过定期运行 php artisan schedule:run,为了做到这一点,我们不得不将条目添加到我们的 crontab 文件中

* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1

AWS 允许您运行 *IX 命令或直接添加 crontab 任务。相反,您必须定期向您的工人端点发出 HTTP(POST,更准确地说)请求。

将 cron.yaml 添加到您的应用程序根目录中(这可以是您仓库的一部分,或者您可以在部署到 EB 之前添加此文件 - 重要的是确保在部署时此文件存在)

version: 1
cron:
 - name: "schedule"
   url: "/worker/schedule"
   schedule: "* * * * *"

从现在开始,AWS 将每分钟向您的端点发出 POST /worker/schedule 请求 - 类似于我们在编辑 UNIX crontab 文件时所达到的效果。这里的重要区别在于,工作环境仍然需要运行一个网络进程来执行计划任务。在幕后,它将执行类似于内置的 schedule:run 命令的操作。

您的计划任务应在 App\Console\Kernel::class 中定义 - 就像在 Laravel 中一样正常,例如。

protected function schedule(Schedule $schedule)
{
    $schedule->command('inspire')
              ->everyMinute();
}

计划任务 - 选项 2

第二个选项是使用 cron.yml 中定义的 AWS 计划

version: 1
cron:
 - name: "run:command"
   url: "/worker/schedule"
   schedule: "0 * * * *"

 - name: "do:something --param=1 -v"
   url: "/worker/schedule"
   schedule: "*/5 * * * *"

注意,AWS 将使用 UTC 时区为 cron 表达式。在上面的示例中,AWS 将每小时调用 /worker/schedule 端点一次,使用 run:command artisan 命令,每 5 分钟调用一次 do:something 命令。目前不支持命令参数。

选择最适合您的选项!

队列作业:SQS

通常 Laravel 需要轮询 SQS 以获取新消息,但在 AWS Elastic Beanstalk 的情况下,消息将来自 AWS 守护进程的 POST 请求。

因此,我们将根据到达的 SQS 有效负载手动创建作业,并将该作业传递给框架的默认工作进程。从这一点开始,作业将以 Laravel 中通常处理的方式进行处理。如果处理成功,我们的控制器将返回 200 HTTP 状态,AWS 守护进程将删除队列中的作业。再次强调,我们不需要轮询作业,我们也不需要删除作业 - 在此情况下,这是 AWS 完成的。

如果您从 Laravel 的另一个实例分发作业,或者如果您遵循 Laravel 的有效负载格式 {"job":"","data":""},那么您应该没问题。如果您想接收自定义格式的 JSON 消息,您可能还需要安装 Laravel plain SQS 软件包。

配置队列

每次在AWS中创建工作环境时,都必须选择两个SQS队列——要么是自动生成的,要么是您现有的某些队列。其中一个队列用于工作本身,另一个队列用于失败的工作——AWS将此队列称为死信队列。

您可以在环境启动时或在之后的任何时候设置工作队列。

AWS Worker queue settings

别忘了将HTTP路径设置为/worker/queue——AWS将在这里调用我们的应用程序。如果您选择自动生成队列,您可以在AWS控制台的SQS部分稍后查看它们的详细信息。

AWS SQS details

您必须告诉Laravel关于这个队列。首先,在.env文件中将队列驱动程序设置为SQS。

QUEUE_DRIVER=sqs

然后转到config/queue.php并从AWS控制台复制粘贴详细信息。

        ...
        'sqs' => [
            'driver' => 'sqs',
            'key' => 'your-public-key',
            'secret' => 'your-secret-key',
            'prefix' => 'https://sqs.us-east-1.amazonaws.com/your-account-id',
            'queue' => 'your-queue-name',
            'region' => 'us-east-1',
        ],
        ...

要生成密钥和密钥,请转到AWS控制台的“身份与访问管理”。最好创建一个仅具有SQS访问权限的单独用户。

通过Composer安装

要安装,只需运行

composer require dusterio/laravel-aws-worker

或者手动将其添加到composer.json

{
    "require": {
        "dusterio/laravel-aws-worker": "~0.1"
    }
}

Laravel 5中的使用

// Add in your config/app.php

'providers' => [
    '...',
    'Dusterio\AwsWorker\Integrations\LaravelServiceProvider',
];

添加服务提供者后,您应该能够看到我们添加的两个特殊路由。

$ php artisan route:list
+--------+----------+-----------------+------+----------------------------------------------------------+------------+
| Domain | Method   | URI             | Name | Action                                                   | Middleware |
+--------+----------+-----------------+------+----------------------------------------------------------+------------+
|        | POST     | worker/queue    |      | Dusterio\AwsWorker\Controllers\WorkerController@queue    |            |
|        | POST     | worker/schedule |      | Dusterio\AwsWorker\Controllers\WorkerController@schedule |            |
+--------+----------+-----------------+------+----------------------------------------------------------+------------+

环境变量REGISTER_WORKER_ROUTES用于触发上述两个路由的绑定。如果您同时在Web和工作环境中运行相同的应用程序,别忘了在您的Web环境中将REGISTER_WORKER_ROUTES设置为false。您不希望常规用户能够调用调度器或队列工作。

目前此变量默认设置为true

所以就是这样——如果您(或AWS)调用/worker/queue,Laravel将处理一个队列项(通过POST提供)。如果您调用/worker/schedule,我们将运行调度器(与在shell中运行php artisan schedule:run相同)。

Lumen 5中的使用

// Add in your bootstrap/app.php
$app->register(Dusterio\AwsWorker\Integrations\LumenServiceProvider::class);

错误和异常

请确保这两个特殊路由没有放在CSRF中间件后面。我们的POST不是真正的Web表单,这里不需要CSRF。如果您有一个全局CSRF中间件,将这些路由添加到异常中,或者将CSRF应用于特定路由或路由组。

如果您的作业失败,我们将抛出FailedJobException。如果您想自定义错误输出,只需自定义您的异常处理器。请注意,您的HTTP状态代码必须与200不同,以便AWS意识到作业已失败。

作业过期(保留)

一个新特性是能够设置作业过期(在AWS术语中称为保留)以秒为单位,以便在由于负载导致的临时队列延迟的情况下,完全跳过低价值作业。

假设我们有队列作业的激增,现在几分钟过去了,其中一些作业甚至已经没有意义了——我们不希望花费计算资源在以后处理它们。

通过在作业或监听器类上设置特殊属性

class PurgeCache implements ShouldQueue
{
    public static int $retention = 300; // If this job is delayed more than 300 seconds, skip it
}

我们可以确保我们不会在队列后300秒后运行此作业。这类似于AWS SQS的“消息保留”设置,只能为整个队列全局设置。

要使用此新功能,您必须使用提供的Jobs\CallQueuedHandler类,该类扩展了Laravel的默认CallQueuedHandler。当过期作业到达时,将抛出特殊的ExpiredJobException异常,然后由您决定如何处理它们。

如果您只是捕获这些异常,因此阻止Laravel向AWS守护进程返回500状态码,则AWS将自动删除作业。

待办事项

  1. 添加对AWS死信队列的支持(从该队列重试作业?)

视频教程

我刚刚开始了一个教育YouTube频道,该频道将涵盖软件开发和DevOps中的顶级IT趋势:config.sys

此外,我很高兴宣布我的一个新工具——GrammarCI,这是一个针对开发者的自动化错别字/语法检查工具,是CI/CD管道的一部分。

影响

请注意,AWS cron不保证100%的时间准确性。由于cron任务与其他作业共享相同的队列,您的计划任务可能会晚于预期进行处理。

后记

我写了一篇博客文章,解释了这是如何实际工作的。