LoginSignup
7
4

More than 5 years have passed since last update.

ElasticBeanstalkのワーカー環境で定期バッチ処理を動かしてみた

Last updated at Posted at 2018-10-17

はじめに

適当になりがちだけど、扱いに悩むことも多い定期バッチ処理。
ちょっとしたタスクならWebサーバ内のcronで呼び出しちゃったりするけど、コンテナ+複数インスタンスの環境で、ちょっとスマートな感じにしたい。
定番はSQS+Lambdaかと思いますが、既にWebアプリ上に機能があったりする場合、ElastiBeanstalk(以下EB)のワーカー環境が便利です!

image.png

こんな仕組みらしい。
ややこしいキューの管理はEBにお任せできちゃいます。

公式ドキュメント:AWS Elastic Beanstalk ワーカー環境

EB環境の作り方等はドキュメントをご参考ください。
AWS Elastic Beanstalk 環境を作成する

APIを用意する

ワーカー環境内のSqsdからHTTP POSTで呼び出されます。
なので、通常のWeb APIとして処理を実装すればOK。
かんたんですね!

とはいえ、同じアプリケーションをWebに公開している場合は外部からアクセスされたくないので、IP制限的なものはかけておきましょう。
こんな感じで、ネットワーク外からのアクセスをブロック。

if (request.remote_ip =~ /(^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.)/).nil?
  redirect_to root_path
end

cron.yamlを用意する

タスクの名前と↑で用意したAPIのURL、実行スケジュールを定義したcron.yamlを作ります。
scheduleはcronの形式そのまんま。

cron.yaml
version: 1
cron:
 - name: "batch_task_1"
   url: "/batch/task_1"
   schedule: "* *1 * * *"
 - name: "batchtask_2"
   url: "/batch/task_2"
   schedule: "* */12 * * *"

cron.yamlに記述したschedule通りにEBがSQSのキューにメッセージを追加し、それを受け取ったEBのSqsdがHTTP POSTでURLを呼び出されます。
という仕組みのようです。

あとは、ソースバンドルに含めてzip形式にしてアップすれば

おまけ(ハマりポイントその1)
cron.yamlはECRのイメージ内に置いてもダメ

今回の環境はMulti ContainerなEB環境で、Dockerrun.aws.jsonのみをアップロードし、ECRからイメージを持ってきてデプロイしています。
試しにcron.yamlをプロジェクトルートに置いてECRにプッシュしてみたのですが、これではスケジュールは登録されず。
Dockerrun.aws.jsonと一緒にzip化したものをアップしてデプロイ時のソースバンドルとして指定したところ、無事登録できました。
問題なく登録できた場合は、EBダッシュボードのイベント内に

Successfully loaded 2 scheduled tasks from cron.yaml.

のように表示されるはずなので、これを確認しましょう。

おまけ(ハマりポイントその2)
Lhaplusで圧縮したらうまく読み込まれない

これは本当に原因が謎。
ワーカー環境云々というより、EBの仕様かな?
ドキュメントに書いてある通り、送る→圧縮(zip形式)フォルダー(Window環境)としたら問題なくアップできました。

おまけ(ハマりポイントその3)
なぜか5分に1度呼び出される

APIが
204 No Content
を返しているのが原因で、デッドレターキューにメッセージがいってた。。
API処理の最後に以下を追加して解決。(Rails)

    render body: nil
7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4