ゆるふわ分散トレースはじめました / start casual distributed trace

ゆるふわ分散トレースはじめました / start casual distributed trace

【BASE社合同勉強会】コネヒトマルシェオンライン「事業を支えるWeb開発」
https://connehito.connpass.com/event/176890/

スライド資料内のリンクなどはこちらにまとめている。
https://budougumi0617.github.io/2020/06/04/connehito_marche/

Eb6be531bcfaa99714d8d3b48665a5a9?s=128

Yoichiro Shimizu

June 04, 2020
Tweet

Transcript

  1. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 2020/06/04 コネヒトマルシェ

    オンライン Yoichiro Shimizu @budougumi0617 ゆるふわ分散トレースはじめました
  2. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 自己紹介 2

    • 清水 陽一郎 @budougumi0617 • BASE BANK, Inc. Dev Division ◦ Go/PHP/Python/AWS etc... • コミュニティ: golang.tokyo / Go Conference etc... • 趣味: ボルダリング/毎週ブログを書くこと ◦ https://budougumi0617.github.io/ Go Conferenece
  3. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. はじめに 3

  4. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 4 •

    なぜ分散トレースが必要なのか ◦ 舞台となる事業のアーキテクチャ構成 • 分散トレースとは何なのか ◦ 分散トレースの概要 ◦ ”ゆるふわ”とは • どうやって実現したのか ◦ Context patternを使ったGoとPythonの実装 • 導入してどうだったか アジェンダ
  5. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 5 •

    複数サービスでシステムを構成したときに生じる悩みを共有する • 分散トレースについてざっくり知ってもらう • インフラ構成の変更、追加予算なしで始める方法の紹介 • リクエストIDを付けるだけでも解析が便利になることを共有する 今日のゴール
  6. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. なぜ分散トレースが 必要なのか

    6
  7. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 売れたタイミングで自動支払い 即時で資金調達できるという体験

    100万店舗のデータから BASE独自の売上予測を開発 リスクなく、即時で資金調達できる金融サービス https://thebase.in/yellbank 7 YELL BANK
  8. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. BASE本体 分析データ

    データ分析基盤 API データ処理系 API ログ分析 エラーレポート 8 YELL BANKのアーキテクチャ構成 CWL Kibana Raygun
  9. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • どのログ同士(エラーレポート)が関連しているのかわからない

    9 エラーが発生したとき エラー発生  エラーに対応している  ログはどれ? どれ? どれ?
  10. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 時刻で絞って探すのを止めたかった 分散トレースしたい!

    10
  11. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 分散トレースとは 11

  12. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • MicroservicesのObservabilityに関するパターンのひとつ

    • 個々の外部リクエストに一意なIDを与え、そのリクエストがサービス間をどのよう にやり取りされたのか可視化、解析する 12 分散トレース(Distributed tracing pattern) Image from https://www.jaegertracing.io/docs/1.17/architecture/
  13. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • Pattern:

    Distributed tracing ◦ https://microservices.io/patterns/observability/distribute d-tracing.html • W3C Trace context ◦ https://www.w3.org/TR/trace-context/ 13 分散トレース(Distributed tracing pattern)
  14. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • SaaSを使う

    ◦ New Relic, Datadog etc • OSSを組み合わせる ◦ OpenTelemetry/OpenCensus, Jeager, Istio etc • クラウドベンダーの仕組みに乗っかる ◦ AWS X-Ray, GCP Cloud trace etc • それなりに仰々しい追加・変更が必要になる 14 分散トレースの実現方法
  15. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. ゆるくふわっと始めてみる 15

  16. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • (現時点では)そこまで困っていなかった

    ◦ 1ヶ月に1回あると楽だなと思うくらい ◦ パフォーマンス面でとくに問題ない • 他のOKRタスクの片手間でやれるくらいでやりたかった ◦ 追加コストを払ってまではやりたくない ◦ インフラ構成の追加・変更してまでやりたくない ◦ 正式に導入するときに容易に廃棄可能であってほしい 16 そんなにガッツリやりたくなかった
  17. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • ログ分析やエラーレポートは既存の基盤をそのまま使う

    ◦ 各サービスごとにKibanaやCWLを確認する現状は維持 • リクエストIDを付与することでログとエラーの関連性を可視化 • ドリルダウンみたいなリッチな可視化は今回は諦める 17 ゆるくふわっと始める分散トレース
  18. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. ゆるふわ分散トレースの方針 1

    2 3 リクエストからIDを取り出す IDをサービス全体に伝播させる IDをログやエラーに埋め込む 18
  19. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. サービス間で リクエストIDをやりとりする

    19
  20. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 20 リクエストIDでログ同士、エラーの関連性を可視化

    リクエストID生成 with ID with ID with ID with ID with ID • リクエストごとに各ログ出力、エラーレポートが一意なIDを内包 with ID
  21. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 21 ログやエラーにリクエストIDを伝播させる

    • 操作の起点でリクエストIDを生成する ◦ PHPからGoに送信するリクエストにリクエストIDを付与 • GoはPHPからもらったリクエストIDをPythonに送信する • Go/Pythonサービス内でリクエストIDを伝播するようにする • ログやエラーレポートにリクエストIDをいれる
  22. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. ここでちょっと問題 レイヤードアーキテクチャでは

    リクエストヘッダーにアクセスできる箇所は限られる 22
  23. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • BANKのサービスはレイヤードアーキテクチャ構成になっている

    ◦ GoでのAPI開発現場のアーキテクチャ実装事例(Pythonもほぼ同じ) ▪ https://speakerdeck.com/hgsgtk/go-api-architecture-practical-example 23 レイヤードアーキテクチャ内でリクエストIDを使う
  24. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • コントローラ層以外でHTTPリクエストは参照できない

    • ドメイン層やサービス層でもリクエストIDを参照したい ◦ すべての関数や引数にリクエストIDを直接含めるのは嫌 24 レイヤードアーキテクチャ内でリクエストIDを使う
  25. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. Context pattern

    25
  26. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 26 Context

    pattern • 特定の条件下に閉じた情報を透過的にやりとりするパターン ◦ Go(1.7~)やPython(3.7~)で標準で提供されている ▪ https://golang.org/pkg/context/ ▪ https://docs.python.org/ja/3/library/contextvars.html ◦ J2EE、AndroidやWPF(C#)でもあるパターン ▪ https://docs.oracle.com/javase/jp/8/docs/api/org/omg/CORBA/Context.html ▪ https://developer.android.com/reference/android/content/Context.html ▪ https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.frameworkelement.datacontext ◦ Stateパターンと似ているが、「状態」だけではない
  27. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. GoでContextを使う 27

  28. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • 透過的に値をやり取りするときにつかう

    ◦ キャンセルやタイムアウトを伝播させるときにも使われる • 関数やメソッドの第一引数にcontext.Contextを含める ◦ [Go] context.TODO()を使って漸進的にcontext対応を始める ▪ https://budougumi0617.github.io/2020/02/21/use-context/ 28 GoでContextを使う
  29. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • MiddlewareでcontextにリクエストIDを注入しておく

    ◦ Middlewareはハンドラーに対する共通の前処理 29 GoでContextを使う
  30. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • ロギングやエラーレポート送信時にcontextからリクエストIDを

    取り出す • 他サービス呼び出し時にはcontextから取り出してHTTPヘッダー にリクエストIDを付与する • アクセスログにもリクエストIDを付与する 30 GoでContextを使う
  31. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • ロギングやエラーレポート送信時にcontextからリクエストIDを

    取り出す 31 GoでContextを使う
  32. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. Python(aiohttp)で Contextを使う

    32
  33. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • Middleware(ハンドラーに対する共通の前処理)でcontextにリ

    クエストIDを注入しておく ◦ [Python] aiohttpでリクエストスコープのコンテキスト情報を扱う ▪ https://budougumi0617.github.io/2020/04/08/python-use-context-var-in-aiohttp/ 33 Python(aiohttp)でContextを使う
  34. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • Middleware(ハンドラーに対する共通の前処理)でcontextにリ

    クエストIDを注入しておく 34 Python(aiohttp)でContextを使う
  35. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • ロギングやエラーレポート送信時にcontextからリクエストIDを

    取り出す 35 Python(aiohttp)でContextを使う
  36. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • アクセスログにもリクエストIDを付与する

    ◦ [Python] aiohttpで独自形式のアクセスログを出力する ▪ https://budougumi0617.github.io/2020/04/11/python-access-log-in-aiohttp/ 36 Python(aiohttp)でContextを使う
  37. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 37 リクエストIDでログ同士、エラーの関連性を可視化

    リクエストID生成 with ID with ID with ID with ID with ID • アプリケーションコードの変更のみでIDを付与するようにした with ID
  38. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • 通知されたエラーレポートのリクエストIDを確認する

    38 ゆるふわ分散トレース実装後
  39. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. • KibanaやCloud

    Watch LogsでリクエストIDを検索する 39 ゆるふわ分散トレース実装後
  40. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 40 ゆるふわ分散トレース実装後

    • IDを検索するだけで関連ログが探せるようになった! Before After
  41. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. ログやエラーの関連性を 可視化できた

    kibanaやCWLでIDを検索するだけで 関連ログが探せるようになった! 41
  42. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 42 •

    複数サービスでシステムを構成したときに生じる悩みを共有する • 分散トレースについてざっくり知ってもらう • インフラ構成の変更、追加予算なしで始める方法の紹介 • リクエストIDを付けるだけでも解析が便利になることを共有する 今日のゴール
  43. © 2012-2019 BASE, Inc. © 2012-2020 BASE, Inc. 43 •

    分散トレースをしたくなるときを説明 • 分散トレースの概要を説明 • GoやPythonでどうやってリクエストIDを引き回すか解説 • インフラ構成やランニングコストを変えずにログやエラーを追跡 できるようになった • 複数言語で類似処理を実装すると言語差異を感じられて楽しい まとめ