ログを利用すると、アプリケーションが何をしているかを理解しやすくなります。ほぼすべてのアプリケーションはホストされているサーバーにそのログを生成しています。しかし、現代の分散システムやマイクロサービス化された環境においては、ログだけではいまひとつです。
全てのアプリケーションログを集めるためにElasticsearchのようなサービスを利用可能で、これはアプリケーションが1つだけの場合は十分シンプルでしょう。しかし昨今では、アプリケーションはむしろサービスの集合に近くなっており、それぞれのサービスが独自のログを出力します。それぞれのログがサービス上の行動やイベントを記録しますが、アプリケーションの問題を見抜くに当たってこれらのサービスをまたがってどのように問題を把握するのでしょうか?
このような疑問は分散トレーシングが「効率的に監視するための必要条件」となっている1つの証であり、トレーシングの標準が必要とされる1つの理由です。
OpenTracingの理論
トレーシングはアプリケーションの処理過程が増えた場合にも可視性を提供しますが、トレーシングのためのシステム計装(instrumentation)はとても骨が折れ複雑です。OpenTracingスタンダートはこれを変え、分散トレーシングを行うためのアプリケーションの計装のコストを最小化します。
2016年の10月にOpenTracingはCloud Native Computing Foundationの元でプロジェクト化されました。CNCFの管理のもとで、OpenTracingは分散システムの計装のオープンでベンダーに中立なスタンダードを目指しています。これによって開発者はスレッドを追跡できるようになります。すなわち、リクエストを最初から最後まで各接点の間にわたってトレースし分散システムを規模を拡大して理解できます。
OpenTracingを利用すると、分散システムにまたがってトランザクションやワークフローがどのように伝播しているかをトレースできます。トレースのコンセプトとしては科学の世界から有向非巡回グラフ(directed acyclic graph: DAG)とよばれる方法を取り入れており、これは各処理過程を明確な開始、明確な終了で段階分けするものです。いくつかのステップあるいは間にまたがるスパンは繰り返し可能かもしれませんが、これは決して終了条件のない"do loop"のような無期限に続くものであってはなりません。
従いましてここでのトレースはスパン、つまり名前付きの連続的で切れ目のない固まりを表す時限の操作、によって構成されるあるDAGであるといえます。分散トレーシングのそれぞれの構成要素は自身のスパンに寄与します。
少し背景知識ができましたので次の定義をご紹介します。トレースとはある共通のルートを共有するスパンの集合です。OpenTracingでは、TraceIDが共通である全てのスパンのデータを収集することでトレースが成り立ちます。
このインスタンス内ではスパンは特定のリモートプロシージャコールに対応するアノテーション(annotation)のセットとなります。それぞれのスパンはある時間単位を表し自身のログを持ちます。スパンにはキーバリューの情報が付与可能で、スパンの関連するイベントをより良く理解できるようにこれを記録します。基本的にはトレーシングは複数のスパン、プロセス間の伝達、そしてアクティブなスパンの管理に関するものです。
OpenTracingの採用が増えている理由
マイクロサービスアーキテクチャでは、アプリケーション間の連携がいまだかつてないほど行われています。アプリケーションの性能監視は単一アプリケーション内をデバッグするのには素晴らしい一方で、システムが複数サービスに広がるに連れ、それぞれのサービスにどのくらい時間がかかっておりシステム全体として健全かどうかをどのように把握できるのでしょうか?とりわけ、サービス間のネットワーク遅延、つまりあるアプリケーションから他のアプリケーションへのリクエストにどのくらい時間がかかっているか、をどのように計測するのでしょう?
分散トレーシングを計装することを考えてみましょう。クラウドベースの環境で発生する高レベルにサービスが分散している場合には、サービスをサポートしているクラウド基盤におけるトレーシングが重要な要素となります。
Firefoxブラウザーを開発で利用した経験があれば、ブラウザーコンソールを開くと(Ctrl + Shift + J)、現在キャッシュで実行されているすべての要素、そして現在の操作状況をみることができるのをご存知でしょう。ある意味では、これは一種のトレースです。
クライアントサイドでのトレーシングの必要性と同じくらい、サーバーサイドのサービス群に対するトレーシング標準の必要性が明確だといいのですが。我々には明確にOpenTracingが必要で、これ異なる言語および異なるライブラリがあり、これらは各々独自に計装をし、異なるデータを送り独自のデータベースに保存するためです。したがってある1つのトレースをする際に1つの構成要素のみでできることはほとんどないでしょう。この事実からもアプリケーションコード、ライブラリのコードそしてあらゆる種別のシステムを計装するための共通言語が必要なのです。
OpenTracingのユースケース
OpenTracingのドキュメントではトレーシングする際の共通の定義付けとして次の例を記述しています。「アプリケーション/ライブラリーコードとトレーシングおよび関係のあるデータを利用する様々なシステムとの間にある薄い標準化レイヤー」。システムの振る舞いを記述する標準の方法としてOpenTracingはこのようにしてアプリケーション、ライブラリー、サービス、フレームワークが「それを支えるOpenTracingの実装について知らずとも分散トレーシングを記述し伝播させる」よう機能します。ここのどこにその価値があるかを記載します。
GitHubで議論されているようにOpenTracingの通常のユースケースには次のものがあります。
- マイクロサービス: 例えば、マイクロサービスアーキテクチャに渡ったやり取りを再構成する
- キャッシュ : トラブルシューティングの際にリクエストがキャッシュヒットしたかどうかを判断する
- 問題解決(Arbitration): 単一プロセスの全履歴をトレースし、シーケンシャルというより並列で実行される複数サービスのやり取りをする際の振舞いを決める
- メッセージバスの監視: キュー内のメッセージが適切にイベント群のトリガーを引いていることを確かめるため、所要時間と伝播が適切かを測定する。ある複数のメッセージが個別の複数のものであってもデータのリークが決して発生していないことを確認する。
InfluxDataのOpenTracing対応
マイクロサービス基盤でトラブルシューティングをシンプル化する需要を認識しましたので、InfluxDataは追加されたトレーシング機能をTelegrafのZipkin Pluginに追加することを決めました。Zipkinは分散トレーシングシステムの1つで、マイクロサービスでは共通のレイテンシーの問題のトラブルシュートに必要となる時刻データの収集に役に立ちます。
ZipkinはCassandraをバックエンドの保存領域として利用しており、全てのトレースを保存します。我々はTelegrafはトレースを収集するのに適しており、ネイティブの時系列データベースであるInfluxDBはこのデータを保存するのが有用であることに気が付きました。トレースは全てタイムスタンプがついていますので、InfluxDBはこれを保存するのにベターな選択肢です。これは時系列データに最適化されており、メトリクスとイベントを保存するために1から作り直したものです。既に他のメトリクスをInfluxDBに保存している場合は、InfluxDataのネイティブの処理エンジンであるKapacitorを利用して(トレースの)他のメトリクスとのクロス解析および操作をすることができるという観点から、トレース情報も合わせて保存することは特に有用となるでしょう。
InfluxDataでは、独自にビルドしたものを利用しています。この我々の理論の妥当性を証明するために、InfluxCloudのサービスにOpenTracingを実装しています。この実装の詳細のいくつかについてはすぐ共有する予定で、これが我々のトラブルシュートにどのように役に立ったかについても同様に共有します。
開発者にはアプリケーション内で何が発生しているか知りたいという要望があり、OpenTracingは複数の会社からいままで以上に注目を集めています。OpenTracingを利用することで、開発者の方々がそれぞれのリクエストはいつ開始し、どこに向かい、その旅の最中で何が起きているのが分かるようになります。知見がたまればより適切な行動を起こせるわけです。
最近のInfluxDataのOpenTracingのオンラインセミナーをご覧になるともう少し情報をえることができます。