このエントリは、Serverless Advent Calendar 2017とFusic Advent Calendar 2017の5日目となります。
PHPカンファレンスや、Serverlessconf Tokyo 2017でも紹介したServerless Ninja Tips(名前だけかっこいい)ですが、その中で、説明するたびに伝わっていない感がある "Instant Job Queue" について紹介したいと思います。
想定するユースケース「クローラ」
サーバーレスアーキテクチャでWebページのクローラを実装するとします。
まずは、以下のような1つのLambdaファンクション(今回はWorkerと呼びます)を考えるでしょう。
- URLを入力として受け取って、URLにアクセスしてHTMLパース、次のURLをリストアップする
- リストアップしたURLを次のLambdaファンクションの入力としてinvokeする
これでだいたいクローラとしては動きそうですが、実際に動かすとどうなるでしょうか?
無限ループになってしまいます。 さらに、同時実行されるLambdaファンクションはURLをリストアップする度にどんどん多くなり、対象サーバにDoSを仕掛けてしまうことになってしまいます。 これではマズいですね。
- 無限ループになる
- 同時実行数がどんどん大きくなる
この2つを解決したいと思います。
無限ループを回避する
無限ループを回避するのは簡単です。
URLと同時に深さ( depth
) をLambdaファンクションに与えて、深さが規定に達したら次のURLのリストアップとinvokeをやめて終了すればOKです。
同時実行数を制御する "Instant Job Queue"
次は同時実行数です。
"Instant Job Queue" は、再帰構造になっているLambdaファンクションにおいて、同時実行数を簡易的に制御するためのTipsです。
フロー
仕組みとしては以下のようになります。
まず、WorkerだけでなくStarterと呼ぶLambdaファンクションを用意します。そして仕組みの真ん中にSQS(キュー)を配置します。
- まずStarterがURLを深さの対をエンキューする
- StarterはWorkerをinvoke
- Workerはデキューしようとする
- Workerはキューがなければ自身を終了する。URLと深さを受け取って、深さが規定に達していても終了する
- 深さ++
- WorkerはURLにアクセスしてHTMLパース、次のURLをリストアップする
- WorkerはリストアップしたURLとインクリメントした深さをそれぞれ対にしてエンキューする
- WorkerはWorkerをinvokeして自身を終了する
特徴
AWSのマネージドサービスのみで実現しているので「キュー待ちするWorkerのプロセス管理」などが必要ありません。
また、(本来なら採用したほうが良いであろう)Step Functions よりも安い料金で実現可能です。
具体的な実装
"Instant Job Queue" を実際に組み込んでいる実装として utsusemi があります。
(utsusemiについてもいつか紹介エントリを書こうと思います)
というわけで
"Instant Job Queue" についての紹介でした。