Supervisorパターンを実装してみました。少々長くなりますが、最後までお付き合い頂けますと幸にございます。最後にクラウドデザインパターンとは?マイクロソフトが提供している、クラウド上でアプリケーションを作成するためのベストプラクティスを集めたものです。https://docs.microsoft.com/ja-jp/azure/architecture/patterns/これらのデザインパターンは、クラウドの特徴を十分活かしている一方で、クラウド環境固有のデメリットをカバーするという、非常に秀逸なものとなっております。実装例も豊富(C#がメインなので、Javaもほしいなぁ・・・)で、すぐに実践適用可能です。PDFでも同内容のものが提供されており、300ページ超の大作ですが、読破すればクラウドネイティブアプリケーションエンジニアになれること間違いなしです。してクラウドデザインパターンが必要なのか?本章では、クラウド特有のメリデリを列挙し、そのメリットを活かすため、もしくはそのデメリットをカバーするために、クラウドデザインパターンがどのように使われるのかをご説明致します。オンプレミスにはなかったクラウド固有の様々な課題を、クラウドデザインパターンは一刀両断します(๑•̀ᄇ•́)و✧リモートコールを多用するクラウドは、複数のAPIをネットーワーク越しにコールし、それらのAPIを連携して1つのサービスを提供する形態を取ることが多くあります。今までのアプリケーションに多く見られた、アプリケーション内の関数呼び出し(インメモリコール)と比較して、ネットワーク越し(場合によってはインターネット越し)にAPIをコールするため、以下の問題が生じます。ネットワーク輻輳によるAPI呼び出しの失敗APIの認証処理によって生じる設計実装の煩雑さ障害発生時の切り分けの難しさこれらの多くは、クラウドデザインパターンで解決が可能です。「ネットワーク輻輳によるAPI呼び出しの失敗」については、「Retryパターン」による処理の再試行によって解決が可能です。障害が一時的なものではなく、災害などの要因により復旧に長時間を要する場合、RetryパターンによるAPI呼び出しの再試行が、逆にリソースを消費(大量のAPIの再試行による、大量のデータストアコネクションの占有など)する場合があります。Breakerパターン」を用いて、システムより切り離すことが有効な対策となります。Offloadingパターン」により、複数のAPIの認証処理(を始めとして、SSLターミネーション、ロギングなど)を1ヶ所に集約することにより、設計や運用保守をシンプルにすることが可能です。Gatewayと呼ばれることもあります。Providerより発行されたJWTを検証」をご覧頂けますと幸いです。いいね!やシェアをしてくれますと、もっと幸いです。Offloadingパターンを具現化したものといえます。トランザクション管理が難しいクラウドは、先程も申し上げましたとおり、複数の外部APIをコールして、1つのサービスを構成することが多くあります。3つのAPI(A、B、C)があり、A→B→Cの順番に呼び出すことで、1つのサービスを構成したとします。月並みな事例とはなりますが、旅行予約サイトのユースケースを思い浮かべて頂けますと、イメージがしやすいと思います。A:航空券の予約をする。B:ホテルの予約をする。C:レンタカーの予約をする。上記のAPIは、提供元も呼び出し先もすべて異なると仮定します。Cの呼び出しに失敗した場合、それまでに行われた「航空券の予約」「ホテルの予約」をなかったことにしなければなりません。いわゆるロールバックです。従来型のモノリシックなアプリケーションであれば、これらの処理はデータベース内で単一トランザクションとして扱っていましたので、ロールバックも容易でした。昨今のシステム開発では、外部のサービスベンダーから提供されている機能をネットワーク越しにAPIを用いて利用し、それらの結果を結合して1つのサービスとすることが一般的です。この場合、各APIはステートレスのため、お互いに共有するコンテキストがなく、データベース内の単一トランザクションをロールバックするように簡単にはできません。Transactionパターン」が適用することができます。多種多様なストレージがあるAzureを始めとするパブリッククラウドサービスには多種多様なストレージが提供されています。Storageなど用途に応じて様々なストレージを使い分けることができます。ところで、こんなユースケースを考えてみます。昨今、Angularに代表されるように、クライアントサイドでビューのみならず、ルーティングまで行うフレームワークが隆盛期と言えます。」をご覧頂きまして、シェアなんてしてくれるといいかもです。Scriptを始めとする静的なコンテンツになります。パターン」というものがあります。Appsよりも遥かに簡単で安価に静的コンテンツをホストできる方法が記載されております。)クラウドデザインパターン利用のすゝめこのようなデザインパターンは昔からあり、古くはJavaのデザインパターン、AWSにもAzureと同様のデザインパターンがあります(AWSの方が先ですが)。このようなデザインパターンは積極活用すべきと思います。システム設計に限らず、物事を始める際は、先人の知恵を活用するのが最も近道ですし、最も安定した品質が確保できます。「学ぶは真似ぶ」ともいいますし、何もない真っ白なキャンパスから良質な設計を生み出せる人は、三度の飯よりコーディングが好きな生粋のエンジニアとか、数々の修羅場鉄火場をくぐり抜けた手練とか、不眠不休で働き続けるショートスリーパーとか、仕事という麻薬に侵された天性のワーカーホリックとかなのかもしれませんが、こういう逸材は稀有な存在です。そこでデザインパターンが大活躍です。デザインパターンをそのまま適用したり、または部分的に組み合わせる、一部デフォルメする等、その案件に合わせた形で適用していく、つまり、プロジェクトマネジメントでいうところのテーラリングを行い、最適化を図っていくということが必要です。Supervisorパターンとは、クラウドデザインパターンの1つで、リモートサービス(例えばOffice365に代表されるようなクラウド上のサービス)へのアクセスの際に発生したエラーの回復性を高めるために利用されます。以下にマイクロソフトの公開資料があります。障害は必ず発生するという前提で設計するというものがあります。リモートサービスへのアクセスは、ネットワークの輻輳、リモートサービス側の過負荷、スロットリング(単位時間あたりの規定アクセス数超過によるアクセス制限)の発生、地震や火事などの災害によるデータセンターの業務停止など、様々な理由で失敗します。短期間で回復するものもあれば、復旧まで長時間を要するのものあります。短期間で回復するものはRetryパターンで対応可能ですが、容易に回復できない持続的なエラーが発生した場合は、以下のいずれかの対応が必要となります。(以下はあくまで一例であり、ユーザー要件によっては、以下以外の特殊な対応が必要となる場合があります)リモートサービスへ処理の再試行をする。システムを一貫性のある状態に保つために、リモートサービスへの変更を全てロールバックする。管理者にメールで通知を行い、管理者が手動で回復する。Supervisorパターンです。以下がイメージ図となります。Storeに登録します。Storeの実装は、データが永続化ができれば、ファイルでもリレーショナルデータベースでもNoSQLデータベースでもなんでも構いません。その他には以下の情報が登録されます。Storeをチェックし、実行状態が「未処理」のタスクを抽出し、Agentにタスクの実行を依頼します。Storeを以下のように変更します。Serviceにアクセスし、処理を実行します。Serviceに対する処理の結果をSchedulerに返します。Storeを以下のように変更します。Storeをチェックし、以下の処理を行います。タスクの失敗回数が規定回数以内で、タスクの実行状態が失敗、もしくは、タスクの予定完了時間を過ぎていたら、タスクの実行状態を未処理にする。(つまり再びAgentに処理をさせる)タスクの失敗回数が規定回数を超えていたら、リトライによる復旧は不能として、メールで通知し管理者が手動で修正、各サービスをロールバックするなど要件に応じて適切な処理を行う。Supervisorパターンを、Azureによるテクノロジーでどのように実現するかを表したのが、以下の図になります。(ちなみに以下は一例であり、他のテクノロジーでも実現可能です)Office365にユーザーを登録するというユースケースを想定しております。MySQLで実現します。Triggerで実現します。関数は以下の2つを用意します。タスクの失敗回数が規定回数以内で、タスクの実行状態が失敗、もしくは、タスクの予定完了時間を過ぎていたら、タスクの実行状態を未処理にする。Storeに実行結果を登録する。Storageによるメッセージ交換によって実現します。SchedulerからAgentへ処理をリクエストするキュー(RequestQueue)と、SchedulerがAgentから処理結果を受け取るキュー(ResponseQueue)をそれぞれ別々に用意します。Jobをチョイスしました。Functionsをチョイスしました。関数は以下の2つを用意します。Storeから実行状態が未処理のタスクを抽出して、RequestQueue(後述)にメッセージを登録する。タスクの失敗回数が規定回数を超えていたら、リトライによる復旧は不能として、メールで通知し管理者が手動で修正、各サービスをロールバックするなど要件に応じて適切な処理を行う。本章では、一連の処理の流れの中で、データがどのように遷移していくかをご説明します。Storeのスキーマ構造を説明します。Storeにはt_state_storeというテーブルがあり、以下のフィールドがあります。Storeに以下のように登録されます。Functionsの関数pushRequestMessageが、テーブルt_state_storeのフィールドprocess_stateが00(未処理)、かつlocked_byがNULLのタスクを取得します。タスク情報を取得したら、pushRequestMessageが、テーブルt_state_storeのフィールドprocess_stateを01(処理中)、フィールドlocked_byを01、complete_byを現在時刻の10分後にします。RequestQueueに以下のJSONをpushします。ServiceつまりOffice365にユーザーを登録、そして、ResponseQueueに以下のJSONを登録します。ここでは、成功したらSupervisorの出番がないので、Office365への登録が失敗したと仮定して、processStateを03にしています。Storeをチェックし、ResponseQueueからメッセージを取得して、JSON内のprocessStateの値を、テーブルt_state_storeのフィールドprocess_stateに03(失敗)として登録する。Storeをチェックし、process_stateが03(失敗)のタスクを以下のように更新します。すると、以下のレコードをSchedulerが抽出して、もう一度Agentに処理を依頼します。2そして、リトライを繰り返し、ついに3回失敗したとします。これはOffice365にただならぬ障害が発生したとSupervisorのrollbackTask関数は判断して、リトライを諦め、ロールバックするなり、管理者にメールで通知するなり適切な処理をします。MySQLなどの設定方法を記載します。MySQL」が表示されるので、それをクリックします。「作成」をクリックします。name」にはMySQLに接続するためのユーザー名、「Password」にはMySQLに接続するためのパスワード、「Location」は自分のいるところと一番近いところ、「Version」は「5.7」を選択して、「作成」をクリックします。リソースグループに移動して、MySQLのアイコンをクリックします。services」を「ON」にして、「Save」をクリックします。これで、Azureのサービスから接続が可能になります。WorkbenchなどのMySQLクライアントからデータベースに接続します。SSL接続のみしか受け付けませんので、以下のURLから証明書を取得して、MySQLクライアントに設定して下さい。https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem以下のDDLに従って、タスク情報を登録するテーブルを作成して下さい。storage」を入力してエンターを押すと、「ストレージアカウント」が表示されるので、それをクリックします。「作成」をクリックします。「リソースグループ」は他のリソースが所属するのと同じリソースグループ、「ストレージアカウント名」は任意の名称を入力して、後はそのままデフォルトのままで「確認および作成」をクリックします。「作成」をクリックします。「リソースに移動」をクリックします。「キュー」をクリックします。「キュー」をクリックして、「キュー名」に「o365-request」を入力して、「OK」をクリックします。同様の手順で「o365-response」キューも作成します。App」が表示されるので、それをクリックします。「作成」をクリックします。「アプリ名」は任意の名称、「サブスリプション」「リソースグループ」は環境に応じたもの、「Storage」は「新規作成」をチェック、「場所」は自分が住んでいるところに一番近いところ、他は以下のように入力して、「作成」をクリックします。Functionsのアイコンをクリックして下さい。Appの設定」をクリックします。「ランタイムバージョン」を「〜1」にします。2018年10月2日時点、「〜2」にしますと、今まで使えていた便利な機能が使えなくなってしまいますので、「〜1」にします。これから関数を作成します。この手順はこの先4回ほど繰り返すので、よく覚えておいて下さい。「関数」のとなりにある「+」をクリックします。「カスタム関数」をクリックします。Trigger」をクリックします。*」(1分ごとに動かす設定)を入力して、「作成」をクリックします。同様の手順で以下の名前の関数を作成して下さい。retryTaskrollbackTaskretrieveResponseMessageという名前の関数を作成します。Triggerで作成します。「カスタム関数」をクリックします。trigger」をクリックします。「名前」に「retrieveResponseMessage」と入力します。「ストレージアカウント接続」の「新規」をクリックして、o365-responseのキューを作成したストレージアカウントを選択します。「キュー名」のところに「o365-response」と入力し、「作成」をクリックします。次にMySQLにSSL接続するために必要なルート証明書をアップロードします。「プラットフォーム機能」をクリックします。「高度なツール」をクリックします。「CMD」をクリックします。コンソールに以下のように入力します。certs以下で取得した証明書をmysqlcert.pmというファイル名で保存します。https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem下記の画面の部分に、mysqlcert.pmをドラッグ&ドロップします。下図のように表示されればOKです。次に環境変数を定義します。FunctionsからMySQLに接続するのに利用します。「プラットフォーム機能」→「アプリケーション設定」の順にクリックします。新しい文字列の追加」ありますので、クリックします。以下の環境変数を追加して、最後に「保存」をクリックします。MYSQL_CA:D:\home\site\certs\mysqlcert.pemMYSQL_DB:statestoreMYSQL_HOST:MySQLのホスト名(以下の方法で取得)MYSQL_USER:MySQLのユーザー名(以下の方法で取得)MYSQL_SECRET:MySQLを作成したときに入力したパスワードMySQLのホスト名及びユーザー名の取得方法は以下のとおりです。リソースグループに移動して、MySQLのアイコンをクリックします。「Overview」をクリックします。name」は「MYSQL_SECRET」に相当します。FunctionsからMySQLに接続するためのライブラリをインストールします。「プラットフォーム機能」をクリックします。「高度なツール」をクリックします。「CMD」をクリックします。コンソールに以下のように入力します。mysql2次に、関数pushRequestMessageの設定を行います。「統合」をクリックします。Storage」を選択して「選択」をクリックします。「ストレージアカウント接続」はキューを作成したストレージアカウントを選択、「キュー名」は「o365-request」を入力して、後はデフォルトのままで「保存」をクリックします。関数名をクリックします。上図のコードを入力する部分に、以下のコードを入力して、「保存」をクリックします。次に、関数retrieveResponseMessageの設定を行います。関数名をクリックします。上図のコードを入力する部分に、以下のコードを入力して、「保存」をクリックします。次に、関数retrieveResponseMessageの設定を行います。関数名をクリックします。上図のコードを入力する部分に、以下のコードを入力して、「保存」をクリックします。次に、関数rollbackTaskの設定を行います。関数名をクリックします。上図のコードを入力する部分に、以下のコードを入力して、「保存」をクリックします。WebJobsAgentの設定を行います。cloneして下さい。https://github.com/noriyukitakei/scheduleragentsupervisor-agentAgentはJavaで記述されております。主要なソースコードのみ以下に解説致します。基本的な実行ファイルは以下に示すO365Agent.javaのみとなり、同パッケージにある他の2つのソースファイルは、JSONのマッピング用DTOなので説明を割愛させていただきます。AgentのソースはMavenプロジェクトとなります。以下のコマンドでビルドして下さい。packagetargetディレクトリ以下に「・・・-jar-with-dependencies.jar」というファイルが出来上がります。これをo365-agent.jarというファイル名に変更します。次に以下のファイルを作成し、run.cmdという名前で保存します。o365-agent.jarrun.cmdとo365-agent.jarをZIPでアーカイブします。Jobにアップロードするアプリケーション本体になりますので、大切に保存しておきます。service」を入力してエンターを押します。App」が表示されますので、クリックします。「作成」をクリックします。「アプリ名」を任意の名称、「サブスクリプション」は環境に応じたもの、「リソースグループ」は他のリソースが入っているリソースグループを指定、「OS」は「Windows」、他はデフォルトのままで、「作成」をクリックします。して画面上部の鈴のアイコンをクリックして以下のような画面が表示されるので、「リソースに移動」をクリックします。環境変数を設定します。キューに接続するための情報を定義します。「アプリケーション設定」をクリックします。Queueの接続情報を入力して、「保存」をクリックします。Queueの接続情報の取得方法は以下になります。Queueが登録されているリソースグループに移動して、以下のアイコンをクリックします。※名前はご自分でつけたものになりますので、下図と違うかもしれません。「アクセスキー」をクリックします。「key1」の「接続文字列」が、先程の「STORAGE_KEY」の値になります。Serviceの画面に戻って、「Webジョブ」をクリックします。最後にクラウドデザインパターンいかがでしたでしょうか?先人の知恵は、うまく有効活用して、これからもどんどんステキな設計をしていきましょう。Life!!ステキなデザパタライフをお過ごしくださいませ。雑誌等の執筆依頼を受付しております。役に立たなかった1人がこの投稿は役に立ったと言っています。コメントをキャンセルメールアドレスは表示されません。Reserved.本サイトに掲載されている社名、製品名、サービス名等は各社の商標または登録商標です。プライバシーポリシーお問い合わせ。