【BASE社合同勉強会】コネヒトマルシェオンライン「事業を支えるWeb開発」 https://connehito.connpass.com/event/176890/
スライド資料内のリンクなどはこちらにまとめている。 https://budougumi0617.github.io/2020/06/04/connehito_marche/
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.2020/06/04 コネヒトマルシェ オンラインYoichiro Shimizu @budougumi0617ゆるふわ分散トレースはじめました
View Slide
© 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
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.はじめに3
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc. 4● なぜ分散トレースが必要なのか○ 舞台となる事業のアーキテクチャ構成● 分散トレースとは何なのか○ 分散トレースの概要○ ”ゆるふわ”とは● どうやって実現したのか○ Context patternを使ったGoとPythonの実装● 導入してどうだったかアジェンダ
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc. 5● 複数サービスでシステムを構成したときに生じる悩みを共有する● 分散トレースについてざっくり知ってもらう● インフラ構成の変更、追加予算なしで始める方法の紹介● リクエストIDを付けるだけでも解析が便利になることを共有する今日のゴール
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.なぜ分散トレースが必要なのか6
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.売れたタイミングで自動支払い即時で資金調達できるという体験100万店舗のデータからBASE独自の売上予測を開発リスクなく、即時で資金調達できる金融サービスhttps://thebase.in/yellbank7YELL BANK
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.BASE本体 分析データデータ分析基盤APIデータ処理系APIログ分析エラーレポート8YELL BANKのアーキテクチャ構成CWL KibanaRaygun
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● どのログ同士(エラーレポート)が関連しているのかわからない9エラーが発生したときエラー発生 エラーに対応している ログはどれ?どれ? どれ?
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.時刻で絞って探すのを止めたかった分散トレースしたい!10
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.分散トレースとは11
© 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/
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● Pattern: Distributed tracing○ https://microservices.io/patterns/observability/distributed-tracing.html● W3C Trace context○ https://www.w3.org/TR/trace-context/13分散トレース(Distributed tracing pattern)
© 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分散トレースの実現方法
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.ゆるくふわっと始めてみる15
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● (現時点では)そこまで困っていなかった○ 1ヶ月に1回あると楽だなと思うくらい○ パフォーマンス面でとくに問題ない● 他のOKRタスクの片手間でやれるくらいでやりたかった○ 追加コストを払ってまではやりたくない○ インフラ構成の追加・変更してまでやりたくない○ 正式に導入するときに容易に廃棄可能であってほしい16そんなにガッツリやりたくなかった
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● ログ分析やエラーレポートは既存の基盤をそのまま使う○ 各サービスごとにKibanaやCWLを確認する現状は維持● リクエストIDを付与することでログとエラーの関連性を可視化● ドリルダウンみたいなリッチな可視化は今回は諦める17ゆるくふわっと始める分散トレース
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.ゆるふわ分散トレースの方針123リクエストからIDを取り出すIDをサービス全体に伝播させるIDをログやエラーに埋め込む18
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.サービス間でリクエストIDをやりとりする19
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc. 20リクエストIDでログ同士、エラーの関連性を可視化リクエストID生成with IDwith IDwith ID with IDwith ID● リクエストごとに各ログ出力、エラーレポートが一意なIDを内包with ID
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc. 21ログやエラーにリクエストIDを伝播させる● 操作の起点でリクエストIDを生成する○ PHPからGoに送信するリクエストにリクエストIDを付与● GoはPHPからもらったリクエストIDをPythonに送信する● Go/Pythonサービス内でリクエストIDを伝播するようにする● ログやエラーレポートにリクエストIDをいれる
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.ここでちょっと問題レイヤードアーキテクチャではリクエストヘッダーにアクセスできる箇所は限られる22
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● BANKのサービスはレイヤードアーキテクチャ構成になっている○ GoでのAPI開発現場のアーキテクチャ実装事例(Pythonもほぼ同じ)■ https://speakerdeck.com/hgsgtk/go-api-architecture-practical-example23レイヤードアーキテクチャ内でリクエストIDを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● コントローラ層以外でHTTPリクエストは参照できない● ドメイン層やサービス層でもリクエストIDを参照したい○ すべての関数や引数にリクエストIDを直接含めるのは嫌24レイヤードアーキテクチャ内でリクエストIDを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.Context pattern25
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc. 26Context 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パターンと似ているが、「状態」だけではない
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.GoでContextを使う27
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● 透過的に値をやり取りするときにつかう○ キャンセルやタイムアウトを伝播させるときにも使われる● 関数やメソッドの第一引数にcontext.Contextを含める○ [Go] context.TODO()を使って漸進的にcontext対応を始める■ https://budougumi0617.github.io/2020/02/21/use-context/28GoでContextを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● MiddlewareでcontextにリクエストIDを注入しておく○ Middlewareはハンドラーに対する共通の前処理29GoでContextを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● ロギングやエラーレポート送信時にcontextからリクエストIDを取り出す● 他サービス呼び出し時にはcontextから取り出してHTTPヘッダーにリクエストIDを付与する● アクセスログにもリクエストIDを付与する30GoでContextを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● ロギングやエラーレポート送信時にcontextからリクエストIDを取り出す31GoでContextを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.Python(aiohttp)でContextを使う32
© 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/33Python(aiohttp)でContextを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● Middleware(ハンドラーに対する共通の前処理)でcontextにリクエストIDを注入しておく34Python(aiohttp)でContextを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● ロギングやエラーレポート送信時にcontextからリクエストIDを取り出す35Python(aiohttp)でContextを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● アクセスログにもリクエストIDを付与する○ [Python] aiohttpで独自形式のアクセスログを出力する■ https://budougumi0617.github.io/2020/04/11/python-access-log-in-aiohttp/36Python(aiohttp)でContextを使う
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc. 37リクエストIDでログ同士、エラーの関連性を可視化リクエストID生成with IDwith IDwith ID with IDwith ID● アプリケーションコードの変更のみでIDを付与するようにしたwith ID
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● 通知されたエラーレポートのリクエストIDを確認する38ゆるふわ分散トレース実装後
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.● KibanaやCloud Watch LogsでリクエストIDを検索する39ゆるふわ分散トレース実装後
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc. 40ゆるふわ分散トレース実装後● IDを検索するだけで関連ログが探せるようになった!Before After
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc.ログやエラーの関連性を可視化できたkibanaやCWLでIDを検索するだけで関連ログが探せるようになった!41
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc. 42● 複数サービスでシステムを構成したときに生じる悩みを共有する● 分散トレースについてざっくり知ってもらう● インフラ構成の変更、追加予算なしで始める方法の紹介● リクエストIDを付けるだけでも解析が便利になることを共有する今日のゴール
© 2012-2019 BASE, Inc.© 2012-2020 BASE, Inc. 43● 分散トレースをしたくなるときを説明● 分散トレースの概要を説明● GoやPythonでどうやってリクエストIDを引き回すか解説● インフラ構成やランニングコストを変えずにログやエラーを追跡できるようになった● 複数言語で類似処理を実装すると言語差異を感じられて楽しいまとめ