20150908 ”時間の流れ” という無限リストを扱うAWS Lambda
-
Upload
- -
Category
Technology
-
view
4.021 -
download
1
Transcript of 20150908 ”時間の流れ” という無限リストを扱うAWS Lambda
"時間の流れ" という無限リストを扱う
AWS LambdaJAWS-UG 千葉支部 Vol.5
~秋のAWS Lambda & API Gateway 祭り!!~
2015-09-08 クラスメソッド株式会社
都元ダイスケ
自己紹介✦ よく訓練されたアップル信者、都元です。 ✦ Webアプリ屋出身のAWS屋
✦ Javaやってます ✦ AWS歴約4年(since 2011夏) ✦ Twitter @daisuke_m ✦ 人間CloudFormer ✦ 自動デプロイ芸人
今日は
✦ 秋のAWS Lambda & API Gateway 祭り!!
✦ ただし、本セッションはAPI Gateway成分ゼロです。
✦ Lambdaのみでがんばります。
✦ Lambdaが出てくるのも遅くぁwせdrftgyふじこ
バッチ処理✦ リアルタイム処理の対義語。
✦ ここでは、HTTPリクエストに応答するための処理以外のもの。
✦ 例えばこんなお仕事を担う。
✦ 毎週/毎日、通知のメールを送りたい。
✦ 毎月、締め処理のバッチを走らせたい。
都元の問題提起編
“AWS上に、HAでスケーラブルな
バッチサーバを構成してください。”
冗長バッチサーバ問題
定期バッチの課題
✦ 障害等で発火できなかったトリガはどうする?
✦ 毎分発火すべきトリガで、0:31までは発火できていた。今、息を吹き返したのが0:33.30。
✦ 0:32と0:33、発火漏れ。
戦略✦ 何事もなかったように、0:34から再開。
✦ 即座に2回発火し、0:34からは予定通り。
✦ 何度撃ち漏らしていても、即座に1回だけ発火し、0:34からは予定通り。
✦ etc.
一方AWSは✦ Design for failure (障害を見越した設計)
✦ EC2インスタンス単品での可用性を担保しようとしない。
✦ 言い換えると、高可用性(HA)を要求するシステムに対しては、Multi-AZを要求する。
✦ Multi-AZ分散すると、スケーラビリティも。
cronバッチサーバ✦ 可用性のために2台冗長でバッチサーバを構築。
✦ 2回発火してくれてベンリでオトク!?
✦ バッチ処理が増えたので4台にスケール。
✦ 4サーバで同じ処理を並走してくれるので、 1台当たりの稼働率は変わらないのでオトク!?
バッチサーバの責務を分割✦ジョブスケジューラ (JS)
✦ 規定されたリズムに従ってトリガを発火
✦ 発火した結果、何が行われるかは関知しない
✦ジョブワーカー (JW)
✦ 発火したトリガを受けて、処理を実行
✦ トリガが発火した理由には関知しない
改めてHAとスケーラビリティ
✦ JWのMulti-AZ化は簡単。
✦ SQSを使ったProducer / Consumerパターン
✦ クセモノはJS側だった。
都元の解答編
Solution 1 - Brian✦ トリガのCRUDを担うRESTful API
✦ 複数台で冗長化
✦ 多重発火防止はDBを仲介したセマフォで実現
✦ トリガに従って、SNSトピックにメッセージを投げるだけ。
Brianの実装と問題点✦ QuartzというJava製OSSジョブスケジューラ。
✦ 複雑だが高機能なので、そこそこ実装は楽。 ✦ RDBを利用したセマフォ(クラスタ機能)
✦ 複雑で、RDBからDynamoDBに差し替える等は困難 ✦ misfire instruction機能
✦ RDSのfailoverによる可用性の低下がある。
✦ JSに2台、JWに2台。金のバカ食い。 ✦ cron + sh-scriptであれば1台で済んでたのに。
Solution 2 - Jimmy✦ トリガは毎秒で固定
✦ 複数台で冗長化
✦ 多重発火防止はDynamoDBを仲介したセマフォで実現
✦ トリガに従って、SNSトピックにメッセージを投げるだけ。
Jimmyが吐くメッセージ
{ "timestamp": 1438825770, "firedTimestamp": 1438825770, "recovery": false, "version": "0.1-SNAPSHOT" }
Jimmyの実装と課題✦ 中身は実はQuartzを利用。(なんだかんだよく出来てる)
✦ ただしクラスタは利用せず、気ままに毎秒発火。
✦ DynamoDBへのConditional Putを利用して、書き込みに成功したインスタンスにSNSメッセージ送信の権利を。
✦ 全インスタンス(通常2台)でビーチ・フラッグス!
✦ 欲しいのは毎秒じゃない問題。
✦ "0 0 9-18 ? * MON-FRI"
無限リスト✦ 無限の大きさを持つリスト。
✦ 手続き型プログラミングで考えると、この手のリストを処理しようとすると無限ループやメモリ破綻に繋がる。
✦ 関数型プログラミングで考えると、この手のリストは、最終的にfilterかreduceされる。
無限リスト利用例✦ [0, 1, 2, 3, 4, 5, …] という無限リスト。 これをサイズN個にフィルタしてからloopすると、N回ループが自在に作れる。
✦ ↑の無限リストに階乗関数(!n)をmapすると[1, 1, 2, 6, 24, …]
✦ さらに逆数を返す関数(1/n)をmapして [1/1, 1/1, 1/2, 1/6, 1/24, …]
✦ 全要素の総和を求めると、ネイピア数(e≠2.718)
時の流れという無限リスト✦ 太古の昔から、永遠の未来までをつなぐリスト
✦ Jimmyは、その要素を1つ1つ取り出して表現(represent)しているだけです。
✦ と考えると、Jimmyのメッセージをフィルターして、SQSに突っ込めば良いのではないか。
✦ という設計思想でJimmyを作ってみました。
ああ、やっと Lambdaが出てきた
こうだったらいいのにな✦ パラメータをコンストラクタで受け取って汎用化
✦ 1つのコードパッケージで複数のLambdaを展開
Lambdaに要望
✦ デプロイパラメータを指定できるようにしてください。
✦ できればそのパラメータはcontextから読めるといいです。
小細工チャレンジ (1)✦ Lambda Functionにタグがあれば…。
✦ GetFunctionとか呼び出してタグの情報をパラメータとして利用できるのではないか?
Functionにタグ無かったwww っうぇwwwっうぇww
小細工チャレンジ (2)$ aws lambda get-function-configuration --function-name jimmy { "FunctionName": "jimmy", "CodeSize": 8283395, "MemorySize": 128, "FunctionArn": "arn:aws:lambda:xx:xx:function:jimmy", "Handler": "JimmyMessageFilterHandler", "Role": "arn:aws:iam::xxxx:role/lambda-poweruser", "Timeout": 60, "LastModified": "2015-08-21T01:52:15.348+0000", "Runtime": "java8", "Description": "0 0 9-18 ? * MON-FRI" }
"Description": "0 0 9-18 ? * MON-FRI"アッー!
という不幸な事件を 起こさないためにも
なにとぞ。