マイクロサービスはシンプルな分散ログ追跡を実装します

マイクロサービスはシンプルな分散ログ追跡を実装します

最近、プロジェクトに簡単な分散リクエスト追跡機能を追加したいと考えています。フロントエンドからゲートウェイへのリクエストを開始し、ゲートウェイから Spring Cloud マイクロサービスを呼び出します。これらのプロセス中に、ログから分散 ID リンクが表示されることを期待します。問題のトラブルシューティングを容易にするために、リクエスト ID を通じてリンク全体を追跡できます。

[[378163]]

既存のソリューションとしては、当然ながら SkyWalking、Spring Cloud Sleuth、Zipkin などのコンポーネントを使用することになります。ただし、ログクエリを容易にするために、さまざまなサービスで常に実行できる ID を記録することが主な目的であるため、複雑なコンポーネントをあまり導入したくありません。最終的に、MDC を介してログに追跡 ID を出力し、Feign と RestTemplate のマイクロサービスにリクエスト ID を渡すことにしました。

主にいくつかのステップが含まれます:

  • フロントエンドからリクエストIDを生成し、それをリクエストヘッダーに追加してゲートウェイに持ち込む
  • ゲートウェイは WebFilter を通じてメッセージを傍受し、MDC に参加してログに出力します。
  • FeignとRequestTemplateでは、リクエストIDをHTTPヘッダー内のマイクロサービスに渡します。
  • 各マイクロサービスもWebFilterによってインターセプトされ、MDCに追加され、ログに出力されます。

MDCC

MDC (Mapped Diagnostic Context) は、マルチスレッド条件下でのログ記録を容易にするために Log4j と Logback によって提供される機能です。 MDC は、キーと値のペアを追加できる、現在のスレッドにバインドされたハッシュ テーブルとして考えることができます。

MDCの主な業務:

  • 値を MDC に設定します: MDC.put(key, value);
  • MDC から値を取得します: MDC.get(key);
  • MDC の内容をログに出力します: %X{key}

TraceIdツールクラスを追加しました

まず、TRACE_ID の定数値と TRACE_ID の設定および生成方法を定義する TraceIdUtils ツール クラスを追加します。以降のコードはこの推定クラスを通じて操作されます。

  1. org.apache.commons.lang.RandomStringUtils をインポートします。
  2. org.apache.commons.lang.StringUtils をインポートします。
  3. org.slf4j.MDC をインポートします。
  4.  
  5. パブリッククラスTraceIdUtils {
  6. 公共 静的最終文字列 TRACE_ID = "traceId" ;
  7. プライベート静的最終int MAX_ID_LENGTH = 10;
  8.  
  9. /**
  10. * トレースIDを生成する
  11. */
  12. プライベート静的文字列genTraceId() {
  13. RandomStringUtils.randomAlphanumeric(MAX_ID_LENGTH)を返します
  14. }
  15.  
  16. /**
  17. * トレースIDを設定する
  18. */
  19. 公共 静的void setTraceId(文字列traceId) {
  20. // パラメータが空の場合は新しいIDを生成する
  21. トレース ID = StringUtils.isBlank(traceId) ? genTraceId(): トレースID;
  22. //MDCにtraceIdを入れる
  23. MDC.put(TRACE_ID、 StringUtils.substring (traceId、-MAX_ID_LENGTH));
  24. }
  25.  
  26. /**
  27. * トレースIDを取得
  28. */
  29. 公共 静的文字列 getTraceId() {
  30. // 得る
  31. 文字列traceId = MDC.get(TRACE_ID);
  32. // traceIdが空の場合は新しいIDを生成する
  33. StringUtils.isBlank(traceId)を返しますか? genTraceId(): トレースID;
  34. }
  35. }

WebFilter経由でTraceIdフィルターを追加する

リクエスト ヘッダーから TraceIdUtils.TRACE_ID に対応する値を取得するために、GenericFilterBean を追加します。この値は、フロントエンドがリクエストを開始するとき、またはマイクロサービス間で渡されるときに伝達されます。値がない場合、TraceIdUtils.setTraceId によって値が生成されます。

  1. org.springframework.core.annotation.Orderをインポートします
  2. org.springframework.web.filter.GenericFilterBean をインポートします。
  3.  
  4. @WebFilter(urlPatterns = "/*" , filterName = "traceIdFilter" )
  5. @注文(1)
  6. パブリッククラスTraceIdFilterはGenericFilterBeanを拡張します{
  7. @オーバーライド
  8. public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) は IOException、ServletException をスローします {
  9. //traceIdの初期化
  10. HttpServletRequest 要求 = (HttpServletRequest) リクエスト;
  11. 文字列 traceId = req.getHeader(TraceIdUtils.TRACE_ID);
  12. TraceIdUtils.setTraceId(traceId);
  13. // 後続のフィルターを実行する
  14. フィルターチェーン.doFilter(リクエスト、レスポンス);
  15. }
  16. }

SpringBoot スタートアップ クラスに @ServletComponentScan アノテーションを追加することを忘れないでください。そうしないと、カスタム フィルターは有効になりません。 「com.yourtion.trace.filter」は、TraceIdFilter が配置されているパッケージ名です。

  1. @ServletComponentScan(basePackages = "com.yourtion.trace.filter" )
  2. @SpringBootアプリケーション
  3. パブリッククラスMyApplication {
  4.  
  5. 公共 静的void main(String[] args) {
  6. SpringApplication.run(MyApplication.class、引数);
  7. }
  8. }

FeignにTraceIdを追加する

@FeignClient プロキシ クラスは実行時に Spring コンテキストの RequestInterceptor を使用するため、独自のインターセプターをカスタマイズして Spring コンテキストに挿入し、リクエスト コンテキストにカスタム リクエスト ヘッダーを追加できるようにします。

  1. feign.RequestInterceptor をインポートします。
  2. feign.RequestTemplate をインポートします。
  3. org.springframework.stereotype.Service をインポートします。
  4.  
  5. @サービス
  6. パブリッククラスFeignInterceptorはRequestInterceptorを実装します{
  7. @オーバーライド
  8. パブリックvoid 適用(リクエストテンプレート テンプレート) {
  9. template.header(TraceIdUtils.TRACE_ID, TraceIdUtils.getTraceId());
  10. }
  11. }

RestTemplate に TraceId を追加する

一部のリクエストは RestTemplate を通じて開始されます。以前は、RestTemplateConfig 構成クラスを独自に実装していました。今回は、関連する構成に以下を追加しました。

  1. RestTemplate restTemplate = builder.additionalInterceptors((リクエスト、本文、実行) -> {
  2. リクエスト.getHeaders()。 add (TraceIdUtils.TRACE_ID, TraceIdUtils.getTraceId());
  3. 実行を返します。execute (リクエスト、本文) ;
  4. })。建てる();

この時点で、リンクへの TraceId の追加は完了しており、残っているのはそれをログに印刷することだけです。

Log4j2のレイアウト形式を変更する

MDC に traceId を出力するために、ログのレイアウト形式を変更します。

  1. <! -- 元の形式 -->  
  2. <PatternLayout パターン = "%5p %c:%L - %m %throwable{セパレーター( --> )}%n" />
  3.  
  4. <! -- traceId フォーマットを追加 -->  
  5. <PatternLayout パターン = "%5p traceId:%X{traceId} %c:%L - %m %throwable{separator( --> )}%n" />

この時点で変更は完了です。

<<:  2021 年に組織が完璧なクラウド コンピューティング戦略を作成するための 3 つの柱

>>:  IBMはまたもや戦いに敗れた。クラウド コンピューティングは Big Blue に悪影響を及ぼしていますか?

推薦する

ウェブサイト上でユーザーを維持し、直帰を減らす方法

ウェブサイトがユーザーを維持し、直帰を減らし、コンバージョンを向上させる方法は、常に注目の話題です。...

ウェブサイトデータ分析に関する雑談

データ分析その他マーケティングの役職や職務には、一般的にデータの機密性に関する潜在的な要件がいくつか...

Dockerを使用する際に注意すべき点

公式ベースイメージを使用してアプリケーションをビルドするアプリケーションを構築する際に、オペレーティ...

デジタル変革を加速する平安クラウドは、中小銀行の技術革新能力を全面的に強化します。

[51CTO.comからのオリジナル記事] デジタル経済は長い間、世界経済の重要な部分となり、徐々に...

ウェブサイトを宣伝するためのWeiboの適切な使用

Weiboは今や人々の生活に欠かせないものとなり、仕事でも勉強でも、私たちはいつでもWeiboを利用...

ハイブリッド クラウド戦略に関する 5 つの専門家のヒント

[[349842]]ハイブリッド クラウドの動的な性質により、組織は戦略と実行を定期的に見直し、更新...

4月の地方求人サイトの発展の軌跡:地方大学と地方企業の融合

今は4月ですが、卒業まであと2か月しかないため、多くの都市の大学生は就職活動に焦っています。現在、多...

百度は再びこう述べた。「世界には百度のページランクと重みはない」

Baidu Webmaster Platform は公式に発表しました: Baidu ページランクと...

魏牙が火事になり、抖音と快手が被害を受ける

意外にも、世論の注目から王力宏を救ったのはヴィヤだった。 12月20日、「ヴィヤの脱税」のニュースが...

デジタル産業を支援し、インテリジェントな未来をつなぐ――西安航空基地企業「ファーウェイ参入」デジタル変革社長クラス

[51CTO.comからのオリジナル記事]現在、疫病と政治環境の影響により、多くの不確定要素が重なり...

Baidu 628K サイトからの Baidu 独自の変換

6月28日はウェブマスターにとって暗黒の日でした。大量のウェブサイトがBaiduのデータベースから追...

360 エンタープライズ セキュリティ: ネットワークをより安全に

[51CTO.com からのオリジナル記事] 360 Enterprise Security Gro...

layer.ae はどうですか?シンガポール データ センターの AMD Ryzen VPS レビュー

layer.ae のシンガポール VPS ビジネスは、10Gbps の大きな帯域幅、AMD Ryze...

投資を探すとき、スタートアップをどのように評価しますか?

よく、企業が資金調達をしようとしているときや買収交渉をしているときに、この質問を受けます。「私の会社...