Elastic Beanstalk ワーカー環境の定期的なタスクとFIFOキューを併用する
概要
If you configure your worker environment with an existing SQS queue and choose an Amazon SQS FIFO queue, periodic tasks aren't supported.
FIFOキューと定期的なタスクが併用できない旨が記載されています。
対策方針
オートスケールによって台数が増減しても、ワーカー環境の定期的なタスク
は重複実行されないようになっています。
その仕組みとしては、DynamoDBの AWSEBWorkerCronLeaderRegistry
に書き込みできたインスタンスをリーダー(Leader)として、そのリーダーインスタンスのみで実行することでそれを実現しています。
そのリーダーの選出を流用し、ワーカー環境のEC2でcron実行をさせることで表題の併用を実現してみます。
検証環境
Ruby 2.6 running on 64bit Amazon Linux 2/3.1.1
Amazon Linux 2
なので注意してください。
ステップ : ダミーのcron.yamlを作成し、 AWSEBWorkerCronLeaderRegistry
を書き込みさせる
version: 1
cron: # UTC
- name: "dummy-job" # 何でもよい
url: "/health" # 何でもよい
schedule: "7 7 7 7 7" # 何でもよい
ステップ : 自身がLeaderか判定するスクリプトを用意
#!/usr/bin/env bash
# EC2でないときはexit
if [[ ! -f /var/lib/cloud/data/instance-id ]]; then
exit
fi
instance_id=$(cat /var/lib/cloud/data/instance-id)
# AWSEBWorkerCronLeaderRegistry のテーブル名を取得
table_name=$(awk -F': ' '$1=="registry_table" {printf $2}' /etc/aws-sqsd.d/default.yaml)
# 定期的に更新されている、leader_idを取得する (ex: i-XXXXX.${registration-record.worker_id})
leader_id=$(aws dynamodb get-item --region ${AWS_REGION} --table-name ${table_name} --key '{"id": {"S": "leader-election-record"} }' | jq -r .Item.leader_id.S)
echo ${leader_id} | grep -q ${instance_id}
exit $?
ステップ : cronをセット
ステップ2で作成した bin/eb_is_worker_leader
が成功したら、処理を実行するようにcronをセットします。
例えば、Rubyでcronをセットする whenever を使う場合、下記のようになります。
job_type :leader_runner, "cd :path && bin/eb_is_worker_leader && bin/rails runner -e :environment ':task' :output"
every :hour do
leader_runner "SomeModel.ladeeda"
end
なお、whenever で用意されている runner
は下記のとおりです。
比べると bin/eb_is_worker_leader
が追加されているだけなのがわかるかと思います。
job_type :runner, "cd :path && bin/rails runner -e :environment ':task' :output"
おまけ: wheneverでcronを更新する
#!/usr/bin/env bash
# Workerでなければ何もしない
env_name=$(jq -r .Name /opt/elasticbeanstalk/config/ebenvinfo/envtier.json)
if [[ ! ${env_name} = 'Worker' ]]; then
exit
fi
/opt/elasticbeanstalk/.rbenv/shims/bundle exec whenever --user webapp --update-crontab
まとめ
これらによって、すべてのワーカーインスタンスでcronが実行されます。
cronではリーダーのみ処理が継続されるため、定期的なタスクの重複した実行が防げます。
似たような解決策
- https://github.com/awsdocs/elastic-beanstalk-samples/blob/main/configuration-files/aws-provided/instance-configuration/cron-leaderonly-linux.config
- https://github.com/dignoe/whenever-elasticbeanstalk
どちらも Amazon Linux 1
が対象です
これらはインスタンス数でLeaderを判断しています。
この記事のやり方では、 AWSEBWorkerCronLeaderRegistry
を流用することで、シンプルな実装になるかなと思っています。
Author And Source
この問題について(Elastic Beanstalk ワーカー環境の定期的なタスクとFIFOキューを併用する), 我々は、より多くの情報をここで見つけました https://qiita.com/DianthuDia/items/83e504b065916c12537d著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .