Azure FunctionsでCircuit Breaker付きなService Bus トリガーを作ってみる
あいさつ
もうすぐ年末ですがAdventカレンダーの進捗はいかがでしょうか?
私は全くです(ノ゚Д゚)八(゚Д゚ )ノイエーイ
そしてここでお知らせがございます。
2017年12月24,25日に開催予定のクリスマスは、隣国の情勢の悪化に伴い中止となりました。
本決定により、クリスマスイブも中止になります。
中止、ならびに本告知が遅れたことにつきまして、楽しみにしておられた方々、及び関係者各位には謹んでお詫び申し上げます。
はじめに
みなさん、Azure Functionsは使ってますか?
ビバ!サーバーレス!! 素晴らしきかなサーバーレス!!
サーバレスで作成すマイクロサービスアーキテクチャでAIを利用すればOK(∩´∀`)∩
なんてことは全く思っているわけではないんですがFunctions自体は好んで使ったりしてます。
Functionsではキュートリガーであったりブロブトリガーなどはよく使うかと思います。
キュートリガー系の設計を設計して行った時に以下のような課題にぶつかったりする事があります。
- トリガーで動作するFunctionの中で外部サービスへアクセスを行なっている。
- 外部サービスが障害により停止した時にもFunctionは実行されてしまう。
- FunctionはExceptionが発生するのでキューはいずれポインズンキュー or 配信不能キューに移動する
- 失敗する事が確定しているのに無駄にリソースが消費されてしまう
この様なケースに対応するクラウドなサービスパターンはサーキットブレーカーパターンでしょう。
www.slideshare.net
Azure Functionsでサーキットブレークを行おうとすると、おそらく二つの方法が思いつきます。
- Application Insights等でFunctionの実行状況を監視してエラーが閾値を超えた場合にFunction App自体を停止する。
- そういう風な仕組みを持ったトリガーを自作する。
今回は前回の記事
を応用して、サーキットブレークするトリガーの作成してみたいと思います。
なお、今回サーキットブレークを厳密に実装しているわけではなくなんちゃってサーキットブレーカーである事をはじめに宣言しておきます。
本題
今回の成果物
SErviceBus・・・・・
解説
実装検討
まず最初に検討した実装方法は「SIngletonAttribute的な感覚でCircutiBreakerパターンを行うことはできないだろうか」ということだったのですが、SingletonAttribute自体WebJobsのコアに食い込んで実装されているため同様な実装を行うためにはかなりのコストがかかってメンドくさいのでボツ。
じゃあトリガー系でよく使われるのはAzure Storage QueueのトリガーとServiceBusのキュートリガーなので「継承していい感じにできないかな」と考えたんですがほとんどの実装がinternalとなっているため無理(・ω・ノ)ノ!
どちらの方が再実装が楽かなぁとコードを見てみた結果、ServiceBusの方が実装シンプルだったので、今回はServiceBusのキュートリガーを作成してみることにしました。
ServiceBusTrigger
azure-webjobs-sdk/src/Microsoft.Azure.WebJobs.ServiceBus at dev · Azure/azure-webjobs-sdk · GitHub
この辺がMicrosoftで作られているServiceBusTriggerのコードです。
現状のdevブランチはVersion3.0系の開発が行われています。 3.0系は.net standardに対応するためにServiceBusTriggerで使われているServiceBusClientのパッケージが
となっています。
version2.0系は
こちらのパッケージを使用しています。
で、今回どっちを使おうかなぁって考えたのですが、Microsoft.Azure.ServiceBusの方は今まで使った事がなかったので、今回はこちらで実装してみることにしました。
解説
ServiceBusTriggerの実装を見てみるとやっていることは実にシンプルでMessageReceiverでメッセージ受信を行なってメッセージを受信したらFunctionを実行して終わったらComplete or Abandonする。という事をしています。
ちなみにStorageQueueトリガーの場合にはループ処理にてキューの取得を行なってキューが存在していたらFunctionを実行する様な処理をしています。
Triggerの作り方とかは前回の記事で解説していますので今回は実装のキモであるIListenerの実装部分のみ解説します。
とは言ったものの、解説するほど大したことはしていなくて
Functionの実行結果が成功でなかった場合、ErrorCountをインクリメントして閾値をオーバーした場合に一旦受信を停止します。
停止した際にオープン状態時間経過後に再度受信を開始します。
エラーが一定時間経過間に発生しなくなった場合にはエラー状態をリセットして正常に復帰します。
サーキットブレーカーと書いていますがハーフオープンなどもなく違う感じなのですがブレーカーが落ちるっていうところでサーキットブレークとさせてください(´・ω・`)
動作画面は非常に地味なため載せません。(´・ω・)(´-ω-
)) ペコリなさい
こんな感じで自作したトリガーを用いてデザインパターンを使って課題を解決するっていう事ができます。
いやぁAzure Functionsって本当に良いものですね、それではヾ(´д`)ノシ