2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Wavefrontで学ぶ分散トレーシング〜第二回 Spring Bootで分散トレーシング

Last updated at Posted at 2020-07-15

この文章は、Wavefrontで学ぶ分散トレーシング シリーズの第二回目です。

シリーズ

第一回 : 概要編 
第二回 : Spring Bootで分散トレーシング ← いまここ
第三回 : REDメトリクスって何?
第四回 : サービスをつなげてみる
第五回 : Pythonで分散トレーシング
第六回 : AMQPで分散トレーシング
第七回 ; サービスメッシュで分散トレーシング

始めに

この回では、まずは手取り早くWavefrontの分散トレーシングを知っていただくためSpring Bootを使ったアプリケーションを紹介します。
なお、プログラミング経験ですが、皆無で大丈夫です。筆者自身インフラエンジニア出身なので、複雑なコードはかけません。

準備編

Spring BootはJavaのフレームワークです。そのため、最低限以下が必要です。

  • Java JDK 8+

Oracle JDKに従いJDKをインストールしてください。
今回はこれだけでOKです。
なお、本来は、エディターも必要ですが、今回のレベルであれば、なしでできるのであえて割愛します。
また、今回の内容はすべて無料でできますのでご安心ください。

ソースコード

ここに公開しています。

アプリの準備

準備ができたら、以下のURLにアクセスしてください。

start.spring.io

image.png

ログイン後、以下を実施します。

  • Add Dependencies を選択
  • Spring Webを検索して追加
  • Sleuth も同様に追加
  • Wavefront も同様に追加

最後にGenerateをクリックします。
すると、zipファイルのダウンロードされるので、どこでもいいので展開してくだい。
展開後、以下のようなファイル構造になっているかと思います。

mhoshino@mhoshino demo % tree
.
├── HELP.md
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           └── demo
    │   │               └── DemoApplication.java
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       └── templates
    └── test
        └── java
            └── com
                └── example
                    └── demo
                        └── DemoApplicationTests.java

14 directories, 7 files

Javaのコードを少しだけ編集します。
お気に入りのエディターで以下のファイルを開いてください。

mhoshino@mhoshino demo % vi src/main/java/com/example/demo/DemoApplication.java

これを以下の内容に差し替えてください。


package com.example.demo;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

@RestController
class HelloRestController {

	private static final Logger LOGGER = LoggerFactory.getLogger(HelloRestController.class);

	@GetMapping("/hello")
	public ResponseEntity<String> hello (@RequestHeader Map<String, String> header){
		printAllHeaders(header);return
		ResponseEntity.ok("Hello World!");
	}

	private void printAllHeaders(Map<String, String> headers) {
		headers.forEach((key, value) -> {
			LOGGER.info(String.format("Header '%s' = %s", key, value));
		});
	}
}

さらに以下のファイルを開きます。

mhoshino@mhoshino demo % vi src/main/resources/application.properties

そして以下の内容を追記します。

management.endpoints.web.exposure.include=wavefront
server.port=8081
wavefront.application.name=demo
wavefront.application.service=HelloRest

コード編集は以上です。上のコードが何をするかは後ほど説明します。

分散トレーシングを早速試してみる

それではアプリケーションを稼働させます。
以下のコマンドを実行してください。

mhoshino@mhoshino demo % ./mvnw spring-boot:run

初回は起動までに時間がかかるかもしれませんが、二回目以降は早くなります。
そして以下のように出力されたら成功です。

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.1.RELEASE)

2020-07-15 10:24:49.985  INFO [hellorest,,,] 66556 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2020-07-15 10:24:50.487  INFO [hellorest,,,] 66556 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=930eeca1-6f00-3004-b800-9fca9761a189
2020-07-15 10:24:50.831  INFO [hellorest,,,] 66556 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8081 (http)
2020-07-15 10:24:50.837  INFO [hellorest,,,] 66556 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-07-15 10:24:50.837  INFO [hellorest,,,] 66556 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.36]
2020-07-15 10:24:50.914  INFO [hellorest,,,] 66556 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-07-15 10:24:50.914  INFO [hellorest,,,] 66556 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 917 ms
2020-07-15 10:24:50.990  INFO [hellorest,,,] 66556 --- [           main] i.m.c.instrument.push.PushMeterRegistry  : publishing metrics for WavefrontMeterRegistry every 1m
2020-07-15 10:24:51.583  INFO [hellorest,,,] 66556 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-07-15 10:24:51.853  INFO [hellorest,,,] 66556 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 3 endpoint(s) beneath base path '/actuator'
2020-07-15 10:24:51.889  INFO [hellorest,,,] 66556 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8081 (http) with context path ''
2020-07-15 10:24:51.908  INFO [hellorest,,,] 66556 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 3.558 seconds (JVM running for 3.794)

A Wavefront account has been provisioned successfully and the API token has been saved to disk.

To share this account, make sure the following is added to your configuration:

	management.metrics.export.wavefront.api-token=2b7543f5-2fc7-42ea-afdf-2c329a87d76e
	management.metrics.export.wavefront.uri=https://wavefront.surf

Connect to your Wavefront dashboard using this one-time use link:
https://wavefront.surf/us/pGqpk9QCjb

別のプロンプトで以下のコマンドを数回、実行してください。

mhoshino@mhoshino demo % curl localhost:8081/hello

うまくいっていればHello World!と出力されるはずです。
そして、しばらくしたら以下のURLを参照してください。

するとあら不思議、WavefrontのUIへ移動されます。
image.png
上のApplication > Application Map(Beta)を選択します。
image.png
何も表示されないかと思いますが
image.png
左上のShow Single Service Nodesを選択してください。
image.png
すると、今回のアプリケーションが表示されます。
image.png
HelloRestをクリックして、View Traces For Serviceをクリックします。
image.png
すると、Trace一覧が表示されます。
image.png

なんと、これで分散トレーシングを体験することができました。

ちょっと待って、何が起きている?

説明をほとんどせず、ここまできてしまいましたので、補足します。
まず、今回作成したアプリケーションは、結果にあるとおり、Hello World!と返すシンプルなREST APIアプリケーションです。

今回使用したSpring Bootは、このREST APIアプリケーションを簡易につくることのできるフレームワークです。
コード上は、いかの部分が、URLとREST APIを作成するための箇所です。


@RestController
class HelloRestController {

	private static final Logger LOGGER = LoggerFactory.getLogger(HelloRestController.class);

	@GetMapping("/hello")
	public ResponseEntity<String> hello (@RequestHeader Map<String, String> header){
		printAllHeaders(header);return
		ResponseEntity.ok("Hello World!");
	}

	private void printAllHeaders(Map<String, String> headers) {
		headers.forEach((key, value) -> {
			LOGGER.info(String.format("Header '%s' = %s", key, value));
		});
	}
}

さて、コードそのものの説明は割愛しますが。。。気づいてほしい点として、Wavefrontとの連携箇所を表したコーディング箇所はほとんどないです。では、なぜWavefrontと連携できていたかというと、その前の手順にあったstart.spring.ioでの依存関係追加部分です。以下で言うところの② ~ ④の箇所です。

image.png

もうすこし、この依存関係が何をしているかについてですが、

  • Spring Web : 今回作ったようなRESTサービスの雛形を提供
  • Sleuth : 分散トレーシングの中心部分。それぞれのリクエストに対して、自動的にTrace、Span情報を付与してくれる。
  • Wavefront : Wavefrontへの接続を行ってくれる。

Trace、Spanという単語が突然でてきましたが、概要編に記載したように

  • Trace : 複数Spanがまとまったひとつの処理
  • Span : 処理の単位。一般的には一つのRESTリクエストもしくはAMQPリクエスト

先ほど追加したSleuthが分散トレーシングの中心的な役割を果たしており、コードとは透過的に各HTTPリクエストに対して、Trace IDとSpan IDを付与しています。

アプリ側のログをみると、多分以下のようなログが表示されています。

2020-07-15 10:26:47.356  INFO [hellorest,5f0e5b575bea47a61ec9c6adc683de47,1ec9c6adc683de47,true] ...

この場合、5f0e5b575bea47a61ec9c6adc683de47がSleuthが追加したTrace IDであり、1ec9c6adc683de47がSpan IDです。

Wavefrontでも、このTrace IDとSpan IDがログから見えます。
image.png

さて、Wavefront側ですが、必要な設定は以下だけでした。

spring.application.name=hellorest
management.endpoints.web.exposure.include=health,info,wavefront
server.port=8081
wavefront.application.name=demo
wavefront.application.service=HelloRest

この中で、wavefront.application.namewavefront.application.serviceがWavefront上でどのように表示されるかを制御しています。

この状態でアプリケーションを起動すると、自動でFreemium(無料)アカウントを作成され、利用可能となります。
Freemiumアカウントは本アカウントと比べると、様々な制約がありますが、試すには手っ取り早いと思います。

なお、http://localhost:8081/actuator/wavefront 
のURLは自動でこのFreemiumアカウントにフォワードされます。
このURLはmanagement.endpoints.web.exposure.include=wavefrontと設定した場合に有効になります。

ここまで簡単に早くできるのは、Spring Bootのメリットです。のちに取り上げますが、他の言語だと結構大変です。
Spring Boot、WavefrontともにVMwareの配下にあり、連携が今後も強化される予定です。

まとめ

今回の内容についてまとめます。

  • Spring Bootを使うとWavefront固有のコーディングなく連携ができる
  • 分散トレーシングのTrace IDとSpan IDはSleuthがこれまたコーディングの必要なくやってくれる
  • Wavefrontの接続は、Freemiumアカウントが勝手に作成され、すぐに利用できる
  • Spring Boot + Wavefrontはなかなかに良い

次回 第三回は「REDメトリクスって何?

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?