Akkaを分散トレーシングで見てみよう

@grimrose

@Scala関西 Summit2018

2018-11-10

今日話すこと

マイクロサービス化されたアプリケーションでは、パフォーマンス測定の一つとして分散トレーシングが挙げられます。

Akka HTTPをAPIサーバの一つとして構築した際に、他のサービスとのやり取りを含め全体のパフォーマンスを可視化するには、分散トレーシングの仕組みに載せる必要が出てきます。

そこで、数ある分散トレーシングの実装の中から、MetricsとTracingの実装の一つであるOpenCensusと、 OpenCensusが利用できる分散トレーシングのバックエンドの一つであるJaegerを用いて、 Akka HTTPのAPIサーバでの分散トレーシングの可視化を紹介します。

お前、誰よ

お前、誰よ

よしだ

  • twitter: @grimrose
  • github: grimrose
  • とある人材紹介会社
    • マーケティング部門のデータエンジニア(自称)
  • 好きなIDE: IntelliJ IDEA
  • Scala歴: 3年(2015~)
  • ScalaMatsuri 2016, 2017, 2018, 2019 スタッフ

普段の仕事

設計から運用

  • 事業KPIの可視化を行うためのWebアプリケーション
  • Scalaを使った日次や月次の集計バッチを実行するアプリケーション
  • 帳票と呼ばれるExcelや外部APIなどからデータベースへデータを投入するツール
  • 部門の日常業務を改善するためのちょっとしたツール

普段の仕事

その他

  • 先述のアプリケーションをAWSで運用する基盤の構築

今回のテーマ

Akkaで作られたアプリケーションの監視の必要に迫られた人

背景

どの処理にどれくらい時間がかかっているかを知りたい。

  • 本番環境はコンテナで動かしているので、SSHで入ってログファイルをtailしてなんてのは無理。
  • ログには出力しているが、整理しながら見るにはシェル芸や超絶技巧検索スキルを駆使する必要がある。
  • 時系列で可視化しておいて、後で見たい。また、自分以外が見られるようにしたい。
  • 他のHTTPサービスとやり取りしてると、どこがボトルネックなのか分かりづらい。

そこで

分散トレーシングで可視化しよう

分散トレーシングについて

In [2]:
HTML('<iframe src="//www.slideshare.net/slideshow/embed_code/key/g5OEQjI18X0BNw" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/td-nttcom/open-tracingjaeger" title="分散トレーシング技術について(Open tracingやjaeger)" target="_blank">分散トレーシング技術について(Open tracingやjaeger)</a> </strong> from <strong><a href="https://www.slideshare.net/td-nttcom" target="_blank">NTT Communications Technology Development</a></strong> </div>')

分散トレーシングについて

  • Tracing
    • Span全体のStartからFinishまでを含むSpanの集合体
    • 各Spanの間には関係性があり、有効巡回グラフ(DAG)で表すことができる。
  • Span
    • 一つのサービス(境界)内の処理

JVMで使う場合

他にもあるが一例として、以下のプロダクトが挙げられる。

Zipkinについて

https://zipkin.io/

TwitterがGoogle Dapperを参考に開発した分散トレーシングシステム

OpenTracingについて

OpenTracingとは

https://opentracing.io

Vendor-neutral APIs and instrumentation for distributed tracing

仕様を統一し、実装は各プロダクトのものを採用できるように。

OpenTracingとは

CNCF(Cloud Native Computing Foundation)の管理下にあるプロジェクトのひとつ。

https://landscape.cncf.io

Category: Observability and Analysis - Tracing

同じカテゴリにJaegerが存在。

OpenTracingとは

CNCFの他のプロジェクトとの関わりは、TrailMapを参照。

https://github.com/cncf/landscape#trail-map

TrailMapについては、Japan Container Days、CNCFのCTOが語るクラウドネイティブへの道を参照。

OpenTracingに対応したTracerライブラリ

https://opentracing.io/docs/supported-tracers/

ここのリストに挙げられているもの以外にも、プロダクトでサポートしているものは、以下のが挙げられる。

その他にもContributeされているものが、こちらのレポジトリ

Jaegerについて

Jaegerについて

数ある実装からJaegerを選んだ理由

  • CNCFのプロジェクトである。
  • ロゴがかわいい。

logo

Jaegerについて

現在の最新versionは 1.7

https://www.jaegertracing.io/docs/1.7/features/

  • High Scalability
  • Native support for OpenTracing
  • Multiple storage backends
  • Modern Web UI
  • Cloud Native Deployment
  • Observability
  • Backwards compatibility with Zipkin

Jaegerについて

アーキテクチャは、主に以下のコンポーネントで構成されている。

  • jaeger-agent
  • jaeger-collector
  • jaeger-query

Jaegerについて

開発や検証だけなら、all-in-oneなdocker imageが利用可能。

$ docker run -d --name jaeger \
  -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
  -p 5775:5775/udp \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 14268:14268 \
  -p 9411:9411 \
  jaegertracing/all-in-one:1.7

Jaegerについて

本番向けとして、k8sのmanifestが公開されている。

jaegertracing/jaeger-kubernetes

更にHelmのChartも公開されているので、デプロイもHelmから可能。

更にKubernetes Operatorも用意されたので、更にデプロイが省力化されている。

分散トレーシングについて

ここまでのまとめ

  • 分散トレーシングは、TraceとSpanで構成されている。
  • OpenTracingという統一された仕様が存在する。
  • JaegerをTracerとして使うことでOpenTracingを利用できる。

ここでの疑問

あれ? OpenTracing? OpenCensusじゃないの?

OpenCensusについて

OpenCensusについて

https://opencensus.io

OpenCensus is a vendor-agnostic single distribution of libraries to provide metrics collection and tracing for your services.

ベンダー非依存なMetricsとTracing用のライブラリ

OpenCensusについて

仕様

  • OpenTracingとは別物。
  • Observabilityの為のライブラリ。
    • つまり、metricsとtracesまとめて面倒を見るために。
  • Googleが作っている部分が多いが、OSSである。

なぜ、OpenCensusか

  • 仕様と実装の分離
    • 各サービスのライブラリを使って書くのもいいが、統一した仕様のもとに書ける。
    • ロックインされることなく、切り替えまたは同時に利用出来る。
  • MetricsとTracingどちらも欲しい
    • Tracingだけでは、RuntimeやOSといった情報までは持っていない。

なぜ、OpenCensusか

Scalaの実装があったから -> opencensus-scala

OpenCensus-Scalaについて

ちょっとした注意点

  • jaegerのtrace-exporterはjavaにあるものの、scalaではconfigが無い。
    • 出力属性がzipkinのB3フォーマットより少ない。
  • zipkinのexporterを使うことで、jaegerのZipkin compatibility APIを利用可能。
    • 若干ScalaのtoStringそのままなのが気になる。

OpenCensus-Scalaについて

JaegerのZipkin compatibility APIとは。

  • B3 propagationを要求されているので、jaegerのフォーマットではエラーとして扱われてしまう。
  • そこで、HTTP headerに以下のものを付与することで、トレーシングが可能に。
    • X-B3-TraceId
    • X-B3-ParentSpanId
    • X-B3-SpanId
    • X-B3-Sampled

OpenCensus-Scalaについて

  • io.opencensus.scala.akka.http.TracingDirective が用意されているので、Akka-HTTPでio.opencensus.trace.Span を使うのが簡単に。
  • io.opencensus.scala.Tracing が用意されているので、対応していないframeworkでも実装が可能。

TracingIDについて

Zipkin以外にも以下のようなHTTP headerがTracingに用いられている。

  • AWS ALB
    • X-Amzn-Trace-Id
  • GCP
    • X-Cloud-Trace-Context
  • Jaeger
    • uber-trace-id

TracingIDについて

Q. 誰がこのIDを付与するのか?

A. ロードバランサーやプロキシーが行う。

特に以下のプロダクトが例として挙げられる。

では、実際にどんな感じなのか見てみましょう

デモ

デモアプリケーションについて

メッセージを登録するAPIアプリケーション

  • メッセージのIDはID生成サービスから取得

デモアプリケーションについて

containers

メッセージ用のID生成について

ログについて

dockerのlogging driverとしてfluentdを利用。

  • コンテナのログもdocker logging driverで取得。
  • fluentdからfluent-plugin-elasticsearchでelasticsearchへ。
  • ログの加工を楽にするひと手間として、json形式へ加工。
    • logstash/logstash-logback-encoderを利用し、そのまま標準出力へ。
    • コンテナ以外は見やすい形式にするために、sbt-native-packager側で切り替え。

Metricsについて

Prometheusをバックエンドにすることで、opencensusからMetricsを転送することが可能。

(但し、opencensus-scalaではまだ計画中の段階)

今回は、opencensus-integrations/ocjdbc を利用して、JDBCのMetricsを可視化。

また、他のexporterと組み合わせることで、より詳細な監視が可能に。

今後

今後について

  • OpenCensusがサポートする言語、バックエンドがまだ少ないが徐々に増えていくと思われる。
  • opencensus-scalaのようにブリッジとなるライブラリが出来ていくことで、今のプロダクトへ導入することが進むと思われる。
    • 出来ればフレームワークが公式にサポートするとありがたい。

今後について

  • 既にDatadogやZipkinを単体で使っているような場合でも、OpenCensusに切り替えることで、複数のバックエンドに転送が可能に。
    • 例えば、デプロイするときには、Stackdriver + Datadog、ローカルで開発するときは、Zipkinのコンテナみたいなのも可能。

今後について

Module for tagless-final & cats-effect

  • 関数の合成が出来るようになると、さらにいろいろと便利に。

今後について

OpenTracingとは別に、OpenMetrics といったプロジェクトがCNCFで立ち上がっているので、こちらも同様に注視しておくと良いかも。

  • promertheusのようなテキスト形式のフォーマットや、Protocol Buffersのフォーマットを選択出来るようになっていくそう。

まとめ

まとめ

  • 分散トレーシングを織り込んで作ることで、ログだけでは分かりにくいことが見えるように。
  • OpenTracingやOpenCensusを利用することで、ロックインされることなく、複数のバックエンドを有効活用出来る。
  • Scalaだと言語のチカラで、より簡単に導入することが出来るように。