コンテナ、サーバーレスプログラミングの出現により、ソフトウェアの配信とデプロイの効率が大幅に向上しました。 アーキテクチャの進化で次の 2 点が変わりました。

  • アプリケーションアーキテクチャは、単一のシステムからマイクロサービスに変わりつつあり、 ビジネスロジックはマイクロサービス間の呼び出しや、リクエストに変化しています。
  • リソースに関しては、従来の物理サーバーは、次第に少なくなってきており、目に見えない仮想リソースに変化しています。
図 1. アーキテクチャの進化


前述の 2 つの変化は、柔軟で標準化されたアーキテクチャが柔軟の一方、運用管理 (O&M) と診断の要件がますます複雑化していることを示しています。これらの変化に対応するために、集中ログシステム (ロギング)、集中測定システム (メトリック)、および分散トレースシステム (トレーシング) を含む一連の DevOps 向けの診断および分析システムが登場しました。

ロギング、メトリック、およびトレーシング

ロギング、メトリック、トレーシングの特徴は次のとおりです。

  •  ロギングにより、あらゆるイベントが記録されます

    たとえば、問題診断の基礎となるアプリケーションのデバッグ情報またはエラー情報です。

  • メトリックにより、集約可能なデータを記録します。

    たとえば、キューの現在の深さをメトリックとして定義し、要素がキューに追加またはキューから削除される際に更新します。 HTTP リクエスト数は カウンターとして定義されることができ、新しいリクエストを受信するたびに累積されます。

  •  トレーシングにより、リクエスト範囲内で情報を記録するために使用されます

    たとえば、リモートメソッドを1回呼び出しするプロセスと消費時間。これは、システムパフォーマンスを調査するために使用されるツールです。ロギング、メトリック、および、トレーシングは、下図のように重なり合う部分があります。

図 2. ロギング、メトリック、トレーシング


以上から、既存のシステムを分類することができます。たとえば、Zipkin は Tracing に特化しています。プロメテウスはメトリックに特化し始めており、より多くのトレーシング機能が実装されていく可能性は高いですが、ロギングにはあまり関心がないようです。ELK や Alibaba Cloud Log Service といったシステムはロギングに特化し始めていますが、他の機能も継続的に統合されており、上図の中心に向かっています。

詳細については、メトリック、トレーシング、ロギングをご参照ください。次は、トレーシングシステムの紹介です。

トレーシングの技術的背景

トレーシング技術は 1990 年代から存在していました。Google 記事「Dapper, a Large-Scale Distributed Systems Tracing Infrastructure」により、この分野は主流となりました。また、記事「Uncertainty in Aggregate Estimates from Sampled Distributed Traces」には、サンプリングに関して詳細に分析されています。左記記事の発表により、優れたトレーシングソフトウェアプログラムを開発するグループが多く現れました。

よく利用されている製品

  • Dapper (Google): あらゆる Tracer の基盤
  • StackDriver Trace (Google)
  • Zipkin (Twitter)
  • Appdash (golang)
  • EagleEye (Taobao)
  • Ditecting (Pangu、Alibaba Cloud のプロダクトで使用される Tracing システム)
  • Cloud Map (Ant Tracing システム)
  • sTrace (Shenma)
  • X-ray (AWS)

分散トレーシングシステムは急速に発展しており、種類も数多くあります。 ただし、いずれも共通してコードトラッキング、データストレージ、およびクエリの表示の 3 ステップがあります。

下図に、分散呼び出しの例を示します。 クライアントがリクエストを開始すると、まずロードバランサに送信され、次に認証サービス、請求サービス、そして最後にリクエストされたリソースの順に渡されます。 最後に、システムは結果を返します。
図 3. 分散呼び出しの例




データが収集され保存されると、分散型トレーシングシステムは通常、タイムラインを含むタイミング図としてこの Trace を提示する。 ただし、データ収集プロセスでは、システムがユーザーコードに割り込まなければならない、 その上、異なるシステム間の API 互換性がないため、トレーシングシステムを切り替え流には、大きな変更を加える必要があります。

OpenTracing

分散型トレーシングシステム間の API 非互換性に対処するため、OpenTracing が誕生しました。OpenTracing は、軽量の標準化レイヤーで、アプリケーション/クラスライブラリと、トレーシングまたはログ解析プログラムの中間に位置します。
図 4. OpenTracing


利点
  • OpenTracing は CNCF に入られており、グローバル分散トレースシステムの統一コンセプトとデータ標準を提供しています。
  • OpenTracing は、プラットフォームやベンダーに依存しない API を提供しているため、開発者はトレーシングシステムを容易に実装 (または変更) できます。
データモデル

OpenTracing のトレーシング (呼び出しチェーン) はこの呼び出しチェーン内の Span によって暗黙的に定義されます。具体的には、Trace (呼び出しチェーン) は 複数の Span で構成される有向非巡回グラフ (DAG) と見なすことができます。Span と Span との関係は References と呼ばれます。

たとえば、次の trace には 8 つの Span で構成されています。

単一の trace の Span 間における因果関係
        [Span A] ←←←(the root span)
            |
     +------+------+
     |             |
 [Span B] [Span C] ←←←(Span C は Span A の子ノード、ChildOf)
     |             |
 [Span D] +---+-------+
               |           |
           [Span E] [Span F] >>> [Span G] >>> [Span H]
                                       ↑
                                       ↑
                                       ↑
                         (Span G は Span F の後に呼び出されます、 FollowsFrom)

次の例に示すように、タイムラインに基づくタイミング図が、Trace (呼び出しチェーン) をより適切に表示できることがあります。

単一の trace の Span 間における時間的関係。
––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time
 [Span A···················································]
   [Span B··············································]
      [Span D··········································]
    [Span C········································]
         [Span E·······] [Span F··] [Span G··] [Span H··]

各 Span には以下が示されます。

  • 操作名
  • 開始時間
  • 終了時間
  • Span タグ。キーと値のペアで構成された Span タグのコレクション。キーは文字列でなければなりません。値は文字列、ブール値、または数値にすることができます。
  • Span log。Span ログのコレクション。各ログ操作には、キー、値のペア、及びタイムスタンプが 1 つずつ含まれます。キーは文字列でなければなりません。値は任意のデータ型にすることができます。 ただし、OpenTracing をサポートするすべての Tracer が すべてのデータ型をサポートする必要があるわけではないことにご注意ください。
  • SpanContext (Span 内容)
  • References (Span 間の関係)。 関連しているゼロまたは複数の Span (Span の間では、SpanContext を通じて関係を確立します)。

各 SpanContext には、次のステータスが含まれます。

  • いかなる OpenTracing 実装も、一意の Span に基づいてプロセスの境界を越えて現行の呼び出しチェーンのステータス (Trace ID と Span ID など) を送信する必要があります。
  • Baggage items (Trace に付属するデータ)。Trace に保存されているキーと値のペアのコレクションであり、プロセスの境界を越えて送信する必要があります。

OpenTracing データモデルの詳細については、OpenTracing のセマンティック標準をご参照ください。

関数の実装

サポートされている Tracer の実装にはすべての OpenTracing の実装が一覧表示されています。JaegerZipkin の実装が最も一般的です。

Jaeger

Jaeger は、Uber によりリリースされたオープンソースの分散トレースシステムです。OpenTracing API と互換性があります。

アーキテクチャ

図 5. アーキテクチャ


上図に示すように、Jaeger は次のコンポーネントで構成されています。

  • Jaeger client: 異なる言語の OpenTracing 標準に準拠した SDK を実装します。 アプリケーションは API を使用してデータを書き込みます。 Client Library は、 アプリケーションで指定されたサンプリングポリシーに従って Trace 情報を jaeger-agent に送信します。
  • Agent: UDP ポートが受信した Span データをモニタリングし、そのデータをまとめて collector に送信するネットワークデーモン。 Agent は基本コンポーネントとして設計されており、すべてのホストにデプロイされています。 Agent は Client Library と collector を分離し、 Client Library を ルータ、および Collector 詳細の検出から遮断します。
  • Collector: jaeger-agent によって送信されたデータを受信してから、そのデータをバックエンドストレージに書き込みます。 Collector はステートレスコンポーネントとして設計されています。 そのため、任意の数の jaeger-collectors を同時に 実行できます。
  • Data store: バックエンドストレージは、Cassandra と Elasticsearch へのデータ書き込みをサポートするプラグイン可能なコンポーネントとして設計されています。
  • Query: クエリリクエストを受信し、バックエンドストレージシステムから Trace 情報を取得して UI に表示します。 Query はステートレスで、複数のインスタンスを起動できます。 インスタンスを Nginx などの ロードバランサの後にデプロイできます。

Jaeger on Alibaba Cloud Log Service

Jaeger に基づいています。これにより、収集したトレースデータを Log Service に永久保存し、ネイティブ Jaeger インターフェイスを使用してデータをクエリおよび表示できます。
図 6. Jaeger


利点

  • ネイティブ Jaeger は Cassandra と Elasticsearch へのデータの永久保存のみをサポートします。ユーザーはバックエンドストレージシステムの安定性を保守し、ストレージ容量を調整する必要があります。 Jaeger on Alibaba Cloud Log Service は、 Log Service の大量データ処理機能を利用しているため、ユーザーはバックエンドストレージシステムの問題を意識することなく、分散トレース機能の利便性を享受できます。
  • Jaeger UI は、クエリおよび Trace 表示機能のみを提供し、問題分析およびトラブルシューティングを十分に行うことができません。Jaeger on Alibaba Cloud Log Service を使用することで、Log Service の強力なクエリおよび分析機能を利用して、システム内の問題を迅速に分析することができます。
  • バックエンドストレージに Elasticsearch を使用する Jaeger と比較し、Log Service は従量課金に対応しているため、そのコストは Elasticsearch のコストのわずか 13% となります。詳細については、「自己構築 ELK vs Log Service (SLS)」をご参照ください。

手順

詳細については、 GitHub をご参照ください。

設定例

HotROD は、複数のマイクロサービスで構成されたアプリケーションで、OpenTracing API を使用して Trace 情報を記録します。

Alibaba Cloud Log Service で Jaeger を使用して HotROD の問題を診断するには、次の手順に従ってください。 ビデオには次の内容が含まれます。

  1. Log Service の設定
  2. Jaeger を起動 (docker-compose コマンドを実行)
  3. HotROD の実行
  4. Jaeger UI で Trace 情報の取得
  5. Jaeger UI での詳細な Trace 情報表示
  6. Jaeger UI でのアプリケーションパフォーマンスのボトルネック特定
  7. Log Service コンソールでのアプリケーションパフォーマンスのボトルネック特定
  8. アプリケーションの OpenTracing API 呼び出し

構成チュートリアル

http://cloud.video.taobao.com//play/u/2143829456/p/1/e/6/t/1/50081772711.mp4

例では、次のクエリステートメントを使用します。

  • 1 分ごとにフロントエンドサービスの HTTP GET / dispatch 操作の平均待ち時間およびリクエスト数をカウント
    process.serviceName: "frontend" and operationName: "HTTP GET /dispatch" |
    select from_unixtime( __time__ - __time__ % 60) as time,
    truncate(avg(duration)/1000/1000) as avg_duration_ms,
    count(1) as count
    group by __time__ - __time__ % 60 order by time desc limit 60
  • 2 つの Trace 操作の所要時間を比較
    traceID: "trace1" or traceID: "trace2" |
    select operationName,
    (max(duration)-min(duration))/1000/1000 as duration_diff_ms
    group by operationName
    order by duration_diff_ms desc
  • 待ち時間が 1.5秒 を超える Trace の IP アドレスをカウント
    process.serviceName: "frontend" and operationName: "HTTP GET /dispatch" and duration > 1500000000 |
    select "process.tags.ip" as IP,
    truncate(avg(duration)/1000/1000) as avg_duration_ms,
    count(1) as count
    group by "process.tags.ip"