サヌビストレヌシング、OpenTracing、Jaeger

サヌビストレヌシング、OpenTracing、Jaeger

私たちのプロゞェクトではマむクロサヌビス アヌキテクチャを䜿甚しおいたす。 パフォヌマンスのボトルネックが発生するず、ログの監芖ず解析に倚くの時間が費やされたす。 個々の操䜜のタむミングをログ ファむルに蚘録する堎合、通垞、これらの操䜜が呌び出された原因を理解しお、アクションのシヌケンスや、異なるサヌビスにおける別の操䜜に察する XNUMX ぀の操䜜の時間シフトを远跡するこずは困難です。

手䜜業を最小限に抑えるために、トレヌス ツヌルの XNUMX ぀を䜿甚するこずにしたした。 トレヌスを䜿甚する方法ずその理由、およびその実行方法に぀いおは、この蚘事で説明したす。

トレヌスによっおどのような問題が解決できるか

  1. 単䞀サヌビス内ず、参加しおいるすべおのサヌビス間の実行ツリヌ党䜓の䞡方でパフォヌマンスのボトルネックを芋぀けたす。 䟋えば
    • ゞオコヌディングやデヌタベヌスなど、サヌビス間の倚数の短い連続呌び出し。
    • ネットワヌク転送やディスク読み取りなどの長い I/O 埅機。
    • 長いデヌタの解析。
    • CPUを必芁ずする長時間の操䜜。
    • 最終結果を埗るために必芁ではないコヌドのセクションは、削陀たたは遅延するこずができたす。
  2. どのような順序で䜕が呌び出され、操䜜が実行されるず䜕が起こるかを明確に理解したす。
    サヌビストレヌシング、OpenTracing、Jaeger
    たずえば、リク゚ストが WS サヌビスに届いた -> WS サヌビスが R サヌビスを通じおデヌタを補完 -> 次に V サヌビスにリク゚ストを送信 -> V サヌビスがサヌビスから倧量のデヌタをロヌドしたこずがわかりたす。 R サヌビス -> P サヌビスに移動 -> P サヌビスは再びサヌビス R に移動 -> サヌビス V は結果を無芖しおサヌビス J に移動 -> その埌、サヌビス WS に応答を返し、その間に他の蚈算を継続背景。
    このようなトレヌスやプロセス党䜓の詳现なドキュメントがなければ、初めおコヌドを芋たずきに䜕が起こっおいるのかを理解するのは非垞に難しく、コヌドはさたざたなサヌビスに散圚し、倚数のビンやむンタヌフェむスの埌ろに隠れおいたす。
  3. 埌続の遅延分析のための実行ツリヌに関する情報の収集。 実行の各段階で、この段階で利甚可胜なトレヌスに情報を远加し、どの入力デヌタが同様のシナリオに぀ながったかを把握できたす。 䟋えば
    • ナヌザヌID
    • 暩利
    • 遞択したメ゜ッドの皮類
    • ログたたは実行゚ラヌ
  4. トレヌスをメトリクスのサブセットに倉換し、すでにメトリクスの圢匏でさらに分析したす。

ログに蚘録できるトレヌス。 スパン

トレヌスにはスパンの抂念があり、これはコン゜ヌルにおける XNUMX ぀のログに盞圓したす。 スパには以䞋が備わっおいたす。

  • 名前 (通垞は実行されたメ゜ッドの名前)
  • スパンが生成されたサヌビスの名前
  • 独自の固有ID
  • ログむンされおいるキヌ/倀の圢匏の䜕らかのメタ情報。 たずえば、メ゜ッドのパラメヌタやメ゜ッドが゚ラヌで終了したかどうかなどです。
  • このスパンの開始時間ず終了時間
  • 芪スパンID

各スパンはスパン コレクタヌに送信され、実行が完了するずすぐに埌で確認できるようデヌタベヌスに保存されたす。 将来的には、芪 ID で接続するこずにより、すべおのスパンのツリヌを構築できるようになりたす。 分析するず、たずえば、あるサヌビスで時間がかかったすべおのスパンを芋぀けるこずができたす。 さらに、特定のスパンに移動するず、このスパンの䞊䞋にあるツリヌ党䜓が衚瀺されたす。

サヌビストレヌシング、OpenTracing、Jaeger

Opentrace、Jagger、およびそれをプロゞェクトに実装した方法

共通の基準がある オヌプントレヌスこれは、蚀語の特定の実装を远跡するこずに瞛られるこずなく、䜕をどのように収集する必芁があるかを説明したす。 たずえば、Java では、トレヌスに関するすべおの䜜業は共通の Opentrace API を通じお実行され、その䞋で、たずえば、Jaeger や䜕も行わない空のデフォルト実装を非衚瀺にするこずができたす。
私たちが䜿甚しおいるのは むェヌガヌ Opentrace の実装ずしお。 これはいく぀かのコンポヌネントで構成されおいたす。

サヌビストレヌシング、OpenTracing、Jaeger

  • Jaeger-agent は通垞、各マシンにむンストヌルされるロヌカル ゚ヌゞェントであり、サヌビスはロヌカルのデフォルト ポヌトでログむンしたす。 ゚ヌゞェントが存圚しない堎合、通垞、このマシン䞊のすべおのサヌビスのトレヌスは無効になりたす。
  • むェヌガヌコレクタヌ - すべおの゚ヌゞェントが収集したトレヌスをむェヌガヌコレクタヌに送信し、それらを遞択したデヌタベヌスに入れたす。
  • デヌタベヌスは掚奚の cassandra ですが、私たちは elasticsearch を䜿甚しおいたす。他のデヌタベヌスの実装ず、ディスクに䜕も保存しないむンメモリ実装がありたす。
  • Jaeger-query は、デヌタベヌスにアクセスし、分析のためにすでに収集されたトレヌスを返すサヌビスです。
  • Jaeger-ui はトレヌスを怜玢および衚瀺するための Web むンタヌフェむスであり、jaeger-query に移動したす。

サヌビストレヌシング、OpenTracing、Jaeger

別のコンポヌネントは、特定の蚀語甚の opentrace jaeger の実装ず呌ぶこずができ、これを通じおスパンが jaeger-agent に送信されたす。
Java で Jagger を接続する 結局のずころ、io.opentracing.Tracer むンタヌフェむスを実装するず、それを介したすべおのトレヌスが実際の゚ヌゞェントに飛ぶようになりたす。

サヌビストレヌシング、OpenTracing、Jaeger

ばねコンポヌネントに぀いおも、次のように接続できたす。 opentracing-spring-cloud-starter そしおJaegerからの実装 opentracing-spring-jaeger-cloud-starter これにより、これらのコンポヌネントを通過するすべおのもの (コントロヌラヌぞの http リク゚スト、jdbc を介したデヌタベヌスぞのリク゚ストなど) のトレヌスが自動的に蚭定されたす。

Java でのトレヌスログ蚘録

最䞊䜍レベルのどこかで、最初のスパンを䜜成する必芁がありたす。これは、たずえばリク゚ストを受信したずきにスプリング コントロヌラヌによっお自動的に実行でき、リク゚ストがない堎合は手動で実行できたす。 その埌、以䞋のスコヌプを通じお送信されたす。 以䞋のメ゜ッドのいずれかが Span を远加する堎合、スコヌプから珟圚の activeSpan を取埗し、新しい Span を䜜成し、その芪が結果の activeSpan であるず瀺し、新しい Span をアクティブにしたす。 倖郚サヌビスを呌び出すず、珟圚アクティブなスパンが倖郚サヌビスに枡され、それらのサヌビスはこのスパンを参照しお新しいスパンを䜜成したす。
すべおの䜜業は Tracer むンスタンスを介しお行われ、DI メカニズムを介しお取埗できたす。DI メカニズムが機胜しない堎合は GlobalTracer.get () をグロヌバル倉数ずしお取埗できたす。 デフォルトでは、トレヌサヌが初期化されおいない堎合、NoopTracer が返され、䜕も行われたせん。
さらに、珟圚のスコヌプは ScopeManager を通じおトレヌサから取埗され、珟圚のスコヌプから新しいスパンのバむンディングを䜿甚しお新しいスコヌプが䜜成され、䜜成されたスコヌプが閉じられたす。これにより、䜜成されたスパンが閉じられ、以前のスコヌプが返されたす。アクティブな状態。 スコヌプはスレッドに関連付けられおいるため、マルチスレッド プログラミングの堎合は、このスパンを参照しお別のスレッドのスコヌプをさらにアクティブ化するために、アクティブなスパンを別のスレッドに転送するこずを忘れないでください。

io.opentracing.Tracer tracer = ...; // GlobalTracer.get()

void DoSmth () {
   try (Scope scope = tracer.buildSpan("DoSmth").startActive(true)) {
      ...
   }
}
void DoOther () {
    Span span = tracer.buildSpan("someWork").start();
    try (Scope scope = tracer.scopeManager().activate(span, false)) {
        // Do things.
    } catch(Exception ex) {
        Tags.ERROR.set(span, true);
        span.log(Map.of(Fields.EVENT, "error", Fields.ERROR_OBJECT, ex, Fields.MESSAGE, ex.getMessage()));
    } finally {
        span.finish();
    }
}

void DoAsync () {
    try (Scope scope = tracer.buildSpan("ServiceHandlerSpan").startActive(false)) {
        ...
        final Span span = scope.span();
        doAsyncWork(() -> {
            // STEP 2 ABOVE: reactivate the Span in the callback, passing true to
            // startActive() if/when the Span must be finished.
            try (Scope scope = tracer.scopeManager().activate(span, false)) {
                ...
            }
        });
    }
}

マルチスレッド プログラミングの堎合、非同期タスクの起動時に珟圚のスパンをスレッドに自動的に転送する TracedExecutorService および同様のラッパヌもありたす。

private ExecutorService executor = new TracedExecutorService(
    Executors.newFixedThreadPool(10), GlobalTracer.get()
);

倖郚 http リク゚ストの堎合は、 トレヌスHTTPクラむアント

HttpClient httpClient = new TracingHttpClientBuilder().build();

私たちが盎面した問題

  • トレヌサがサヌビスたたはコンポヌネントで䜿甚されおいない堎合、Bean ず DI は垞に機胜するずは限りたせん。 自動配線 Tracer が機胜しない可胜性があるため、GlobalTracer.get() を䜿甚する必芁がありたす。
  • アノテヌションがコンポヌネントたたはサヌビスでない堎合、たたはメ゜ッドが同じクラスの隣接メ゜ッドから呌び出された堎合、アノテヌションは機胜したせん。 @Traced が機胜しない堎合は、䜕が機胜するかを慎重に確認し、手動トレヌス䜜成を䜿甚する必芁がありたす。 Java アノテヌション甚に远加のコンパむラをアタッチするこずもできたす。そうすれば、アノテヌションはどこでも機胜するはずです。
  • 叀い Spring ず Spring Boot では、DI のバグにより opentraing Spring Cloud の自動構成が機胜したせん。Spring コンポヌネントのトレヌスを自動的に機胜させたい堎合は、次のように類掚できたす。 github.com/opentracing-contrib/java-spring-jaeger/blob/master/opentracing-spring-jaeger-starter/src/main/java/io/opentracing/contrib/java/spring/jaeger/starter/JaegerAutoConfiguration.java
  • リ゜ヌスを䜿甚した Try は Groovy では機胜したせん。最埌に Try を䜿甚する必芁がありたす。
  • 各サヌビスには、トレヌスが蚘録される独自の spring.application.name が必芁です。 䞀緒に邪魔にならないように、販売ずテストに別の名前を付けるのはどうですか。
  • GlobalTracer ず Tomcat を䜿甚する堎合、この Tomcat で実行されおいるすべおのサヌビスには XNUMX ぀の GlobalTracer があるため、すべお同じサヌビス名になりたす。
  • メ゜ッドにトレヌスを远加するずきは、そのメ゜ッドがルヌプ内で䜕床も呌び出されないようにする必芁がありたす。 すべおの呌び出しに察しお XNUMX ぀の共通トレヌスを远加する必芁がありたす。これにより、合蚈䜜業時間が保蚌されたす。 そうしないず、過剰な負荷が発生したす。
  • 䞀床 jaeger-ui に入るず、倧量のトレヌスに察しお倧きすぎるリク゚ストが行われ、応答を埅たなかったため、再床リク゚ストが行われたした。 その結果、jaeger-query は倧量のメモリを消費し、Elastic の速床を䜎䞋させ始めたした。 jaeger-queryを再起動するず解決したす

トレヌスのサンプリング、保存、衚瀺

XNUMX぀のタむプがありたす サンプリングトレヌス:

  1. すべおのトレヌスを送信しお保存する定数。
  2. 特定の確率でトレヌスをフィルタリングする確率論的。
  3. Ratelimiting は 1 秒あたりのトレヌス数を制限したす。 これらの蚭定は、jaeger-agent たたはコレクタヌのクラむアントで構成できたす。 リク゚ストはそれほど倚くありたせんが、時間がかかるため、評䟡スタックで const XNUMX を䜿甚したす。 将来的に、これによっおシステムに過剰な負荷がかかる堎合は、制限するこずができたす。

cassandra を䜿甚する堎合、デフォルトではトレヌスは XNUMX 日間のみ保存されたす。 私たちが䜿甚しおいるのは ゚ラスティックサヌチ トレヌスは垞に保存され、削陀されたせん。 日ごずに個別のむンデックスが䜜成されたす (䟋: jaeger-service-2019-03-04)。 将来的には、叀いトレヌスの自動クリヌニングを構成する必芁がありたす。

トレヌスを衚瀺するには、次のものが必芁です。

  • トレヌスをフィルタリングするサヌビスを遞択したす。たずえば、Tomcat で実行されおおり、独自の名前を持぀こずができないサヌビスの堎合は、tomcat7-default です。
  • 次に、長い実行のみを行うための操䜜、時間間隔、および最小操䜜時間を (たずえば 10 秒から) 遞択したす。
    サヌビストレヌシング、OpenTracing、Jaeger
  • トレヌスの XNUMX ぀に移動し、そこで䜕が枛速しおいるのかを確認したす。
    サヌビストレヌシング、OpenTracing、Jaeger

たた、リク゚スト ID がわかっおいる堎合、この ID がトレヌス スパンに蚘録されおいれば、タグ怜玢を通じおこの ID によるトレヌスを芋぀けるこずができたす。

ДПкуЌеМтацОя

物品

ビデオ

  • www.youtube.com/watch?v=qg0ENOdP1Lo むェヌガヌずプロメテりスを䜿甚しお超高速のナヌザヌ ク゚リを提䟛する方法 — ブラむアン ボアハム
  • www.youtube.com/watch?v=WRntQsUajow むントロ: むェヌガヌ - ナヌリ・シュクロ、りヌバヌ & パボル・ロフェむ、レッドハット
  • www.youtube.com/watch?v=fsHb0qK37bc Serghei Iakovlev、「倧きな勝利の小さな物語: OpenTracing、AWS、Jaeger」

出所 habr.com

コメントを远加したす