LaravelとElastic Beanstalkのかなり新しいユーザーである私は、ほとんどの人がそうであるように、すぐに操作をスケジュールする必要があることに気づきました。
過去には、これに常に単純なcrontabスケジューリングを使用していました。だから今私は質問のリストの前に立った:
これらの質問に対する個々の答えを見つけることはそれほど難しくありませんでした。それらを組み合わせて実際にすべてを機能させることは、しかし、少しトリッキーであることがわかりました。そのため、これを適切に機能させるのに苦労している他の人のために、ここでソリューションを共有することにしました。
回答の最後にある実際の_.ebextentions
_構成を参照してください。
この質問への回答はもちろん最も明白であり、Laravelに少しでも慣れていれば、きっとその回答を知っています。 Scheduling !
Laravel Schedulingとは、ドキュメントでそれを自分で読むことができるためです。
しかし、私たちが持ち歩く必要がある重要なことは、Laravel=スケジューリングは、ドキュメントで説明されているように、実行にcrontabを使用することです。
_* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
_
これは次に私たちを導き、そしてもう少しトリッキーな質問です...
一見すると、この質問に対する答えは非常に簡単に思えるかもしれません。 AWS Knownledge Centerでこれを見つけました: Elastic Beanstalk環境のEC2インスタンスでcronジョブを作成するにはどうすればよいですか?
ここでは、.ebextentionsを使用してElastic Beanstalk EC2マシンでcronジョブをセットアップする方法について説明します。つまり、目的のcronジョブを配置するディレクトリ_/etc/cron.d/
_に新しいファイルを作成します。
このディレクトリ内のファイルは、crontabによってroot
ユーザーとして処理されます。以下にコメントしたように、私が侵入したいくつかの落とし穴があります。
_files:
# The name of the file should not contain any dot (.) or dash (-), this can
# cause the script not to run. Underscore (_) is OK.
"/etc/cron.d/mycron":
# This permissions is important so that root user can run the script.
mode: "000644"
# As the file is run by the root user it needs to be the owner of the file.
owner: root
# For consistency it's a good idea to have root as the group aswell.
group: root
# NOTE: We need to explicitly tell the cron job to be run as the root user!
content: |
* * * * * root /usr/local/bin/myscript.sh
# There need to be a new line after the actual cron job in the file.
_
これらすべてのトラップをクリアした後は、Laravel cronジョブを上からスケジュールします。これは次のようになります。
_files:
"/etc/cron.d/schedule_run":
mode: "000644"
owner: root
group: root
content: |
* * * * * root php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
_
ただし、これはほとんどの場合実際には機能しません。これは、LaravelスケジューラがENV変数にアクセスできず、データベースの設定を著しく変更してはならないためです。
私はこれに対する答えをここに見つけました: 取得方法Laravel AWS Elastic Beanstalk Cronでタスクスケジューリングが機能
それで、ジョージ・ベニッシュに大きな叫びをあげました。これを共有してくださった皆さんに敬意を表します!
それで、この最後のパズルのピースで、最終的にセットアップを正しく機能させることができました:
ファイル構造:
_[Project root]
|-- .ebextensions
| |-- cronjob.config
_
cronjob.config:
_files:
"/etc/cron.d/schedule_run":
mode: "000644"
owner: root
group: root
content: |
* * * * * root . /opt/elasticbeanstalk/support/envvars && /usr/bin/php /var/www/html/artisan schedule:run 1>> /dev/null 2>&1
commands:
remove_old_cron:
command: "rm -f /etc/cron.d/*.bak"
_
Elastic Beanstalkの主要な機能の1つは、必要に応じて自動スケーリングしてサーバーを追加できることです。Laravel Scheduling: Running 1つのサーバー上のタスク 。
多くの場合、複数のサーバーでcronジョブを実行したくありません。たとえば、メールを送信するためのスケジュールされたコマンドがある場合、それらを複数回送信することは望ましくありません。
注:これには、ドキュメントに記載されているように、キャッシュエンジンとしてmemcachedまたはredisを使用する必要があります。そうでない場合は、AWSサービス Elasticache をご覧ください。
注2:onOneServer()
を使用する場合、name()
メソッドを使用して、スケジュールされたタスクに名前を付ける必要があります(前にonOneServer()
)を呼び出します。そのようです:
_$schedule->command('my:task')
->name('my:task')
->daily()
->onOneServer();
_
より簡単な方法は、新しい定期的なタスク機能を使用することです。 cronジョブに.ebextensions
を使用すると、複数のマシンで同じジョブが実行されたり、自動スケーリングで他の競合状態が発生する可能性があります。
cron.yaml
で定義されたジョブは、ワーカー環境によってのみロードされ、一度に1台のマシン(リーダー)によってのみ実行されることが保証されています。重複がないことを確認するために、Nice同期メカニズムがあります。ドキュメントから:
Elastic Beanstalkはリーダー選出を使用して、ワーカー環境のどのインスタンスが定期的なタスクをキューに入れるかを決定します。各インスタンスは、Amazon DynamoDBテーブルに書き込むことでリーダーになることを試みます。成功する最初のインスタンスはリーダーであり、リーダーのステータスを維持するために引き続きテーブルに書き込む必要があります。リーダーがサービスを停止すると、別のインスタンスがすぐにその役割を果たします。
プロジェクトのルートにcron.yaml
を配置します。
version: 1
cron:
- name: "schedule"
url: "/worker/schedule"
schedule: "* * * * *"
考慮すべきことの1つは、Beanstalkの定期的なタスクは、アプリケーションのURLにHTTP POSTリクエストを送信するように設計されていることです。これにより、実行するジョブがトリガーされます。これは、 SQSでキューを管理する方法。
Laravel=の場合、具体的には、スケジュールされた各ジョブを処理するためのルートとコントローラーを作成できます。しかし、より良いアプローチは、Laravelのスケジューラーを使用し、毎分呼び出す単一のルートを用意することです。
このパッケージはこれらのルートを自動的に作成します https://github.com/dusterio/laravel-aws-worker
CodePipelineからデプロイをトリガーするときにDynamoDBのLeader Table作成権限で問題が発生している場合は、CodePilelineサービスロールにdynamodb:CreateTable
が必要なためです。手順については、これらを確認してください StackOverflow質問