EIP / Verify the Credit Bureau Operation


Verify the Credit Bureau Operation

Verify the Credit Bureau Operation

  • 2つ目の要求は外部の信用調査機関のサービスが正しく動作しているかを監視すること
    • 銀行が正しい見積もりを提供するのに顧客の信用スコアが必要なので、ローンブローカーはこのサービスにアクセスする
  • 外部の信用調査機関のサービスが正しく動作しているかを検証するため、定期的にTest Messageをサービスに送ることにした
    • 信用調査機関のサービスがReturn Addressをサポートしているので、既存のメッセージフローに悪影響を与えることなくTest Messageを簡単に導入できる
    • テストメッセージのセパレータを使わなくて済むよう、テストメッセージ専用のチャネルを用意する(P.587の図)
  • テストデータジェネレータとテストデータベリファイアも必要
    • テストデータジェネレータはテスト対象のサービスに送るテストデータを生成する
      • テストメッセージは非常にシンプルで、社会保障ナンバー(SSN)のフィールドを持つだけ
      • テスト用に架空人物の固定のSSNを使う
      • これを予め用意された結果と比較することで検証できるようになる
      • これでリプライメッセージを受け取ったかをチェック出来るだけでなく、メッセージの中身が正しいかを検証することもできる
    • 9章の単純なサンプルで、信用調査機関のサービスは送られてきたSSNは考慮せずにランダムな結果を返していた
      • なので、テストデータベリファイアは特定の結果をチェックするのではなく、代わりに300から900の信用スコアで検証する
      • もし範囲外の結果であれば、テストデータベリファイアは管理コンソールにメッセージを送って知らせる
  • テストデータベリファイアは外部サービスのレスポンスタイムもチェックする
    • 予めセットされた時間間隔内にリプライメッセージを受け取れなければ、管理コンソールに警告する
  • ネットワークの帯域を最小限のものとするのに、テストデータベリファイアはリプライメッセージが遅れたりダメなものであった時のみ通知し、正常な場合は何も送らない
    • このルールの唯一の例外は、モニターがエラーを検知したあと正常なリプライメッセージが送られてきた場合の通知
    • モニターが「サービスOK」のメッセージを管理コンソールに送り、信用調査期間が正常に戻ったことを通知する
  • 最後に、モニターは起動中、コンソールに自分の存在を通知する
    • このメッセージによりコンソールがアクティブなモニターを見つけられ、それぞれのステータスを表示できる
  • モニターの実装では二つのタイマーを使う
    • 一つはTest Messageを一定間隔で送るためのもの
    • もう一つはタイムアウト期限内にレスポンスが届かなかった場合のフラグを立てるためのもの(P.589の図)
  • Send Timerは、最後に受け取ったメッセージあるいは最後のタイムアウトイベントと、次に送るTest Messageとの間のインターバルを決定する
  • Timeout Timerは、モニターがリクエスト・メッセージを送信してから起動される
    • タイムアウト期限内にリプライが届くと、タイマーをリセット
    • 届かなかったら、モニターはコントロールバスにエラーメッセージを送る
      • そのときに送信インターバル後の新しいメッセージを初期化するのに、新しいSend Timerを起動する(何のことかよくわからない。。。)
  • 現実のシナリオは数秒といった比較的短いタイムアウトと1分といった長いインターバルが使用される
  • P.589の図について
    1. モニターがTest Messageを送ってTimeout Timerがスタート
    2. レスポンスが期限内に届いたので、モニターがTimeout TimerをキャンセルしてInterval Timerを開始
    3. インターバルタイマーが経過し、モニターが新しいTest Messageを送ってTimeout Timerがスタート
    4. ここでリプライが返される前にTimeout Timerが終わってしまい、モニターがControl Busにメッセージを送る
    5. 同時にモニターは新しいInterval Timerを開始する
  • モニターの実装は一つのクラスのみ
  • MonitorクラスはMessageConsumer?を継承し、Smart Proxyパターンを提供する
  • 入力チャネルを定義し、メッセージを受け取るのにEvent-Driven Consumerを起動する
  • 入ってくるメッセージそれぞれに対し、ProcessMessage?メソッドを実行する
  • 継承するクラスはこのメソッドをオーバーライドして独自処理を追加できる
  • Processメソッドはメッセージの消費を開始するのにMessageConsumer?を構築する
  • MonitorクラスはSend Timerを起動することでこのメソッドの基底の実装を拡張している
    • タイマーが作動すると、OnSendTimerEvent?メソッドが実行される
  • Processメソッドは存在をアナウンスするのに、MonitorStatus?型であるメッセージをモニターに送る
Monitor Class: Sending Messsages(P.589のソース)
  • OnSendTimerEvent?メソッドは新しいメッセージを作成する
  • リクエストのパラメータはSSNのみで固定値
  • たくさん入ってくるリプライメッセージのCorrelation Identifierを検証するのに、メッセージIDを保存する
  • 最後に、期限内にメッセージが届かなかったら通知できるよう、timeroutTimerをスタートする
  • テストメッセージのPriorityプロパティをAboveNormal?に設定し、キューにあるアプリケーションメッセージがサービスにあたかも利用不可だと見せないようにする(意味不明。。)
  • Test Messageに高い優先度を使うことで、メッセージキューがキューにあるアプリケーションメッセージよりも先にこれらのメッセージを配信する
  • 今回のケースでは、高い優先度を設定することは安全
    • Test Messageが非常に小さなボリュームでテストデータジェネレータにより生成されるので
  • もしリクエストチャネルで大きなサイズのものを高い優先度にしてしまうと、アプリケーションメッセージのフローを中断してしまうかもしれない
    • これは確実に、可能な限りでしゃばってはならないというマネジメントソリューションの目的を壊してしまう
  • ProcessMessage?メソッドはMonitorクラスの中心
    • テストメッセージベリファイアと、入ってきたリプライメッセージの評価を実装している
  • タイムアウトタイマーを止めたあと、入ってきたメッセージが正しいCorrelation Identifierか、正しいメッセージボディのデータ型か、ボディにある値は意味のあるものかをチェックする
    • もし何らかの落ち度があれば、MonitorStatus?を構築し、Control Busチャネルに送信する
    • モニターはlastStatus変数で前回のステータスを保持している
      • ステータスが「error」から「OK」に変わっても、ProcessMessage?メソッドはControl Busに通知を送る
Monitor Class: Receiving Messsages(P.590のソース)
  • インターバル内にメッセージが届かなかったら、timeoutTimerはOnTimeoutEvent?メソッドを実行する
    • このメソッドはMonitorStatus?メッセージをControl Busに送り、新しいリクエストメッセージがインターバル後に送れるよう、新しいSend Timerを起動する
Monitor Class: Timeout(P.592のソース)

Credit Bureau Failover

  • これで外部の信用調査機関サービスのステータスをモニターすることができるので、信用調査機関サービスが落ちている間でもローンブローカーが続けて動作できるよう、そのデータを使ってフェイルオーバーのスキームを実装していきたい
    • Point-to-Point Channelがすでにフェイルオーバーの基本形を提供しているので価値はなさげ
  • 複数のCompeting Consumer?を単一のPoint-to-Point Channelで使う場合、あるコンシューマがこけても他のコンシューマが実行終えるまで処理を中断する、というようなことはない
    • 複数のコンシューマーがアクティブなら、不可を分割するので、効率的に単一のロードバランシングのメカニズムを実装できる
  • なぜ明示的なフェイルオーバーのメカニズムを実装する必要がある?
    • 外部のサービスを使うとき、Competing Consumer?をサポートしない、例えばSOAPやHTTPといった単純なチャネルに制限されてしまう
    • ロードバランスする複数のサービスは欲しくない
  • 例えば、主要となるサービスプロバイダーと、ある使用量に達すると大幅に割引されるといった、使用量に関する契約を結んでいるとする
    • 二つのプロバイダにトラフィックを分割すると、コストがよりかかってしまう
    • その代わりに、低コストのプロバイダを主要なプロバイダとし、そこがこけている間だけ高いプロバイダにスイッチしたいかもしれない
      • 素晴らしいライセンスを考慮したアーキテクチャの決定に関する優れた議論はBeyond Software Architectureを参照
  • 明示的なフェイルオーバーを実装するのに、信用調査機関のリクエストチャネルにMessage Routerを挿入する(P.593の図)
  • ルータはリクエストを主要な信用調査機関サービス(太い矢印)か補助的なサービス(細い矢印)かに振り分ける
    • 補助的なサービスは最初のサービスとはメッセージのフォーマットが異なるので、補助的なサービスはMessage Translatorのペアでラップする
  • Message Routerは、Control Busの向う側にある管理コンソールによってコントロールされる、コンテキストベースのMessage Router
  • 管理コンソールは、前節で設計した信用調査機関モニターからモニタリングのデータを受け取る
  • モニターが失敗を示すと、管理コンソールはMessage Routerに補助的なサービスプロバイダに再送するよう指示する
  • リクエストメッセージが補助的なサービスプロバイダに再送されている間は、モニターは主要なプロバイダにテストメッセージを送り続けている
    • モニターがサービスから正しい操作を確認すると、コンソールはMessage Routerにリクエストメッセージを主要なプロバイダに送信するよう指示する
    • 図では補助的なサービスプロバイダのモニターは示していないが、2つ目のモニターのインスタンスを使うだけなので簡単
  • コンテキストベースのMessage Routerの実装を見る
    • ContextBasedRouter?クラスは入ってくるメセージを処理するためにMessageConsumer?基底クラスを継承している
    • ProcessMessage?メソッドはcontrol変数の値をチェックし、その変数に応じて入ってきたメッセージを主要か補助かのチャネルに振り分ける
ContextBasedRouter Class(P.594のソース)
  • control変数はOnControlEvent?メソッドにより設定される
    • このメソッドは、コントロールチャネルからのメッセージを受け取るためにMessageConsumer?を継承したControlReceiver?クラスによって呼び出される
  • ContextBasedRouter?クラスはControlEvent?型としてControlReceiver?提供し、数値の含まれたコントロールイベントを受信したときに実行される
ControlReceiver Class(P.594のソース)

担当者のつぶやき

遅くなってすみません。。

みんなの突っ込み