avram / aws-cron-job
Laravel命令,仅让单个EC2实例在AWS云托管上运行schedule:run定时任务
Requires
- aws/aws-sdk-php: ^3.36
- illuminate/console: ^7.0|^8.0|^9.0|^10.0
README
这是一个Laravel 5/6/7/8/9的包,它允许在您的ElasticBeanstalk负载均衡的AWS设置中仅在一个EC2实例上运行定时任务。
对于不同的Laravel版本,请使用相应的包版本
- Laravel 5:
^0.1
- Laravel 6:
^0.2
- Laravel 7:
^0.3
- Laravel 8, 9 & 10:
^0.4
问题
在典型的AWS负载均衡环境中,所有EC2实例都完全相同,它们都将运行任何配置的定时任务(如果通过.ebextensions
文件夹配置)。在某些情况下这可能没问题,但可能导致定时任务运行多次,这可能会成为一个问题,例如您的系统可能会发送多次相同的电子邮件通知。
AWS解决方案
AWS建议在.ebextensions
文件夹中使用leader_only
标志为定时任务,这将仅在第一个部署的实例上设置定时任务。这很好,直到负载均衡器介入,创建一个新非领导者实例,然后决定不需要额外的实例并杀死一个实例,可能是运行时间最长的实例,这可能是您的领导者实例;并且由于leader_only
仅在部署期间应用,您将没有领导者实例,也不会运行定时任务。
针对此问题还有更多解决方案,但其中大多数都需要在AWS端进行额外设置。其中一些甚至建议您只为定时任务设置另一个EC2实例。在某些情况下这可能没问题,但我不太喜欢这样做。
AWS Cron Job
此包提供了一种简单的方法,可以从单个EC2实例触发定时任务,而无需更改您的AWS设置。它将简单地从您的AWS账户中获取单个AWS EB环境的所有当前运行实例,按字母顺序排序,然后检查当前实例ID是否与列表中的第一个相同。当实例发生变化时,列表会动态更改,因此您无需担心这一点!
为了提高性能,此包默认将实例列表缓存5分钟,但您可以更改此设置。此外,由于实例ID永远不会更改(实例可以更改但它们的ID不能,至少不是自动的),当前实例ID将永远缓存。所有内容都将在同一实例上本地缓存(file
缓存驱动程序)。
安装
只需通过composer要求即可
composer require avram/aws-cron-job
Laravel 5.5(及更高版本)应在您使用composer安装此包时自动发现并启用服务提供程序。对于旧版本,您必须手动将服务提供程序添加到您的config/app.php
中
'providers' => [
// ...
Avram\AwsCronJob\Providers\AwsCronJobServiceProvider::class,
],
设置
AWS凭证
此包依赖于AWS PHP SDK,它将自动从AWS_ACCESS_KEY_ID
和AWS_SECRET_ACCESS_KEY
环境变量中获取您的API密钥和秘密密钥,因此最好在环境中定义这些值。但是,您也可以将这些值硬编码(见下文)。
配置
此包提供了一个配置文件,您必须与以下内容一起发布
php artisan vendor:publish --provider="Avram\AwsCronJob\Providers\AwsCronJobServiceProvider"
之后,您可以在config/awscronjob.php
中设置包
<?php
return [
'connection' => [
'region' => env('AWS_REGION', 'ca-central-1'),
'version' => env('AWS_API_VERSION', 'latest'),
// 'credentials' => [
// 'key' => env('AWS_ACCESS_KEY_ID','my-access-key-id'),
// 'secret' => env('AWS_SECRET_ACCESS_KEY','my-secret-access-key'),
// ],
],
'aws_environment' => env('AWS_CRON_ENV', 'app-production'),
'skip_environments' => env('AWS_CRON_SKIP_APP_ENV', 'local'),
'run_on_errors' => env('AWS_CRON_RUN_ON_ERRORS', true),
'cache_time' => env('AWS_CRON_CACHE_TIME', 5),
'cache_enabled' => env('AWS_CRON_CACHE_ENABLED', true),
];
connection
AWS区域和API版本(默认情况下将从您的环境变量中获取凭证)aws_environment
AWS环境名称(用于通过环境名称标记筛选实例)skip_environments
要跳过的 Laravel 应用环境列表,以逗号分隔,并自动运行定时任务(默认:local
)run_on_errors
当与 AWS 服务器通信发生错误时,是否运行定时任务(默认:true
)cache_time
应该缓存所有实例列表多长时间(以分钟为单位,默认:5
)cache_enabled
是否缓存实例列表和实例 ID(默认:true
)
由于每个环境至少有一个 aws_environment
,因此最好不要过度修改已发布的配置文件,而是直接在您的 Elasticbeanstalk 控制台中设置以下环境变量
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_REGION
AWS_CRON_ENV
AWS_API_VERSION
(可选)AWS_CRON_SKIP_APP_ENV
(可选)AWS_CRON_RUN_ON_ERRORS
(可选)AWS_CRON_CACHE_TIME
(可选)
注意:您的 AWS IAM 用户必须具有
ec2:Describe*
权限才能访问您的实例列表。为了以防万一,我给我的用户分配了arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
策略。
使用方法
简单来说,不要像这样运行您的定时任务
php artisan schedule:run
...而是改为
php artisan aws:schedule:run
...就这样! ;)