“ASKS” の働き
2019年12月17日 火曜日
CONTENTS
Twitterフォロー&条件付きツイートで「バリーくんぬいぐるみ」を抽選で20名にプレゼント!
応募期間は2019/11/29~2019/12/31まで。詳細はこちらをご覧ください。
今すぐツイートするならこちら→ フォローもお忘れなく!
【IIJ 2019 TECHアドベントカレンダー 12/17(火)の記事(その1)です】
こんにちは、CHAGE 開発メンバーの くまさか です。
CHAGE 紹介記事、第三弾です。
前回のCHAGE の動きでは、CHAGE の中に ASKS が存在し、高速に再帰検索を行うことや、ASKSの活用するデータの仕組みに外部APIを検索するISONがあることを紹介しました。
今回は、高速に再帰検索を行う仕組みである ASKS の中身について、紹介します。
ASKS の中身
前回の記事で概要図を紹介していたので、既に気づいた方もいると思いますが、CHAGE はマイクロサービスです。そして、ASKSもマイクロサービスです。
CHAGE の構造の一部としてASKS紹介すると、ちょっとしたパーツの様に見えるかもしれません。
しかし、ASKS自身も無駄なく動作できるように設計された複雑な仕組みです。
今回は、ASKSの中身で重要なポイントである「高速などんどん検索」を支えているサービスのASKS Buyerや、ASKS Routerについて紹介します。
既に紹介しているCHAGE の概要図から、ASKS の中身が一部見える形にしました。
簡単に紹介すると、OwnerやAgentは大きく2つの機能から成り立っています。互いを連携するための機能と、自身が行うべき機能です。
例えば、Agentは、前回紹介したISON等と連携できる機能と、検索システムの検索結果を保管するCache機能から成り立っています。
データはRouterが伝搬してくれます
ASKS はマイクロサービスのため、一連の検索をいくつかの機能を用いて行うためにはサービス間の連携が必要です。
しかし、連携する機能をサービスごとに用意してしまうと、全体の速度低下やメンテナンス性の低下などの問題が考えられます。
そのため、データを連携させる為だけの仕組み、ASKS Routerというものが存在します。
ASKS Routerが存在するので、連携したい機能達は「この宛先にデータを渡したい。」とASKS Routerへ頼むだけで連携が可能です。
例えば、Ownerの中にいるASKS BuyerがASKS Agentに連携したい場合は、以下のように連携します。
- 検索が開始されると、ASKS Buyerは検索したいデータの検索可能な宛先を確認します。
- そして、ASKS Buyerは、宛先へデータを渡すようASKS Routerへ依頼します。
この例からもわかるように各機能は、宛先を確認し、転送を依頼するだけで、データが連携されます。
ASKS Routerが存在することで、非常に簡単にデータの連携が実現できます。
とはいえ、ASKS Routerが効率的に連携するためには様々な機能が必要になります。
- アプリケーションステートフルな動作をさせ、戻りの経路が自動生成される
- 送出した経路の優先度を下げる動作があり、同じ役割の経路情報があれば、ロードバランシングが可能
- ストリームエンコーディングに対応したインタフェースを活用し、待ちの少ない通信が可能
- …
全てを詳しく紹介することは難しいため、1つ目を詳しく紹介します。
ASKS Routerは、戻りの経路を自動生成します
ASKS Routerは、戻りの経路を自動生成することで、メンテナンス性や独立性を向上させています。
例えば、仮にASKS Routerが、単に宛先へ配送だけする機能の場合、事前に全ての行き戻り経路情報を準備する必要が生まれます。
加えて、戻りの経路情報は、応答結果の種類だけ必要になってしまうので、多くの経路情報が必要になります。
わかりやすいようにASKS Agentの応答結果で、具体的な例を挙げます。
ASKS Agentの場合、検索を行うkey, value
は1つですが、応答結果のkey, value
は複数です。
そのため、ASKS AgentがASKS Buyerに結果を戻すには、出しうる全ての種別の経路をASKS Buyerへ向ける必要があります。
全ての経路を登録することは不可能ではありませんが、膨大な数となります。
ASKSの世界は、とても多くの数のASKS Routerが存在するので、全ての経路情報を登録することは現実的ではありません。登録情報自体のメンテナンスが必要なことはもちろん、静的経路情報は依存度を上げてしまい、メンテナンス性や独立性を下げる要因となります。
このような経路情報の問題を解決するために、戻りの経路を記録するステートフルルーティングの機能があります。
動作イメージは以下のようになります。
- ASKS Routerが、ルーティング時に、自身が保有するテーブルにASKS Protocol内部のメッセージID(詳細は次の項目で説明します) と、送信元となったインタフェースを記録
- 以降、レスポンスと思われるデータがASKS Routerに到達した場合、テーブルを確認
- 一致するメッセージIDが存在する場合、送信元となったインタフェースにデータをルーティングする
このようなステートフルルーティングの機能の他、紹介しきれていないいくつもの機能によって、ASKS Routerによる効率的なサービスの連携を実現しています。
通信プロトコル
ASKSで流れる通信プロトコルをASKS Protocolと呼びます。
ASKS Protocolは、リクエストでもレスポンスでも同じ構造を持つという特徴があります。
この構造によって、データのやりとりをシンプルにし、「どんどん検索」を支えています。
ASKS Protocolの通信データ構造は、以下のような要素から構成されています。
- Message ID
- 検索時に付与されるID
- ASKS Buyerがどの検索に紐づく結果かを認識する為に活用する
- ASKS Routerのステートフルルーティングで活用する
- 検索時に付与されるID
- Status
- 検索リクエストなのか、レスポンスなのか等を表すステータス
- Body
key value
形式のリクエスト、レスポンス共通フォーマット
通信プロトコルが、行きも戻りも同じ構造を持っているのは、TCP/IP構造でも同じです。
しかし、アプリケーションレイヤで行き(リクエスト)も戻り(レスポンス)も同じ構造を持っているのは珍しいかと思います。
Buyerは、再帰検索だけをします
ASKS Buyerは、再帰検索だけを行います。
先ほど紹介した通り、ASKS Routerが連携を担うので、ASKS Buyerは「どんどん検索」に集中できます。
なぜ、Buyerといった名前かというと、いくつかの検索先からデータを集め続ける動きを買い物に見立て、「複数の店舗からデータを買っている様に見える」という理由です。
ASKS Buyer の行うべきことは以下のようなステップです。
- WebUIからのリクエストにメッセージIDを付与し、リクエストとして、ASKS Routerへ渡す
- ASKS Routerから、帰ってきた結果に別のメッセージIDを付与し、リクエストとして、ASKS Routerへ渡す。あわせて、メッセージIDを付与する前のデータ(結果)を保存する
- どういった検索の結果であるかを判断するのに、自身が付与したメッセージIDを活用します
- 何度もそれを繰り返し、データがまとまったら、WebUIへ一括応答を行う
前回の記事で紹介したASKSの再帰的検索機能を支えているポイントは、ステップ2です。
(ステップ2で紹介した内容のみで再帰検索を実現しているわけではありません。周辺の構造が存在することで、ASKSは実現されています。)
前回の記事で、「再帰的検索でどんどんデータが溜まって行く際に、同じデータをどの深度で検索するかわからない。」と紹介しました。
ここを支えているのも、先ほど紹介したステップ2です。
ASKS Buyerのステップ2では、応答するために取りまとめた結果に、検索したいデータが存在するか確認します。
CHAGEで扱うデータのリクエストやレスポンスはkey, value
形式で同一です。そのため、結果のデータが存在するということは、既に検索済みであるという事になります。
(検索の結果打ち止めされた場合もあるので、必ずしもデータが存在するわけではないが、1検索期間中にそのデータを検索済みである実績は確認できます。)
この問題についてASKS Buyerは、過去に自分が検索したかどうかを判断するだけで解決できるのでとても簡単に解決している様に見えます。
しかし、ASKS Buyerが単純に問題を解決できる理由は、関係する構造を適切に組み合わせている為です。
- 検索先についてはASKS Routerが担ってくれるので、考えなくて良い
- CHAGE で扱うデータ構造が、
key, value
であり、リクエスト、レスポンス共に同じ構造である - …
ASKS Routerや、ASKS Buyerといった「どんどん検索」を支えているポイントを紹介しました。
ASKS全体の構造を大きく紹介できたので、最後にボトルネックになりやすい通信インタフェースについて少し紹介します。
ASKS Router の通信インタフェース
インタフェースはとても大切です。4K動画を遅いインターネット回線で見ても楽しめないように、流れるデータや周りの構造がいくら最適であっても、インタフェースが遅ければ活かすことはできません。
このため、ASKS Router の通信インタフェースは、データのやり取りを高速に行えるMPPP(MessagePack Passing Protocol) という仕組みを持っています。
MPPP
活用しているのは、MessagePackです。
それらをMessage Passingにやりとりできるプロトコルとして、MPPP (MessagePack Passing Protocol) を用意しています。
ASKSの紹介で説明している通り、連携される際にやりとりされるデータ構造はASKS Protocolです。
その裏側では、MPPPに変換されたbyte列として、TCPソケットやUnixDomainSocketを経由しています。
ところで、なぜMessagePackを採用しているのか。
それは、MessagePackが、ストリームエンコードデコードが可能という特徴を持つからです。
これにより、ASKS Protocolからの変換でデータ受信を待つ必要がなく、随時変換が行えます。
このため、各Protocol Layerで、変換を待つことなく、検索Keyを検索先に伝えることができます。
CHAGEも、ASKSも高速な連携が鍵です
今回は、再帰検索の機能であるASKS Buyerや、それらを連携させるASKS Router, ASKS Protocol, MPPPについて紹介しました。
各々のサービスは非常にシンプルな役割を持ち、それらが高速に連携されていることを紹介できたかと思います。
こういった工夫によって、CHAGE はマイクロサービスでありながら、高いレイテンシの影響を最小限にし、スループットを向上させています。
詳細は、CHAGEの裏側: レイテンシに呪われないQAQの世界 で紹介しています。
次回はデータソースをどんどん増やせる仕組みを紹介
CHAGEは、サービスを容易に増やす為に、マイクロサービスで連携しやすい構造になっています。
今回紹介している、ASKS Routerも、連携を支える仕組みの1つです。
こういった構造になっている理由の大きなポイントは、利用者がOSINTする為に活用するデータを容易に増やせる様にしていることです。
これにより、IIJ独自の調査データ等といったものも容易に追加できています。
データを容易に増やせる構造にも名前が付いており、ASKS Sellerと言います。
ASKS Buyerが収集する先がASKS Sellerです。
どういったデータもASKS Sellerを介して、ASKSに接続する構造の共通化を図り、データの追加を容易にしています。
実は、前回紹介したISONも、ASKS Sellerを介しています。
次回の記事では、ASKS Sellerや存在する理由(なぜ内製データ用ISONとかを作って、構造の共通化をしないのか等)の紹介や、ISON以外のデータソースについても触れていこうと思います。
関連記事
- IIJ内製調査システム CHAGE のご紹介
- CHAGE の動き
- “ASKS” の働き(本記事です)
- “ASKS” と データソースの接続
- “CHAGE” の大切な要素