## Memo - epollで動くネットワークサーバが間に挟まったときの追跡ってできるのかな。マルチプロセスやマルチスレッドなら特定のpidとトレースログのタイムスタンプだけで、アプリケーションの一連の処理を終えるけど、epollはいると同じpidでも別々のコンテキストの処理が時間的に入れ違いになって現れるけど、それらを区別できるのだろうか。 ## Memo with LLM ### 問題意識 本論文では、マイクロサービスアーキテクチャの進化に伴い、システムの複雑さが増し、観測性の確保が困難になっている問題に注目しています。特に、既存の動的トレーシングツールは、ユーザースペースに限定されており、アプリケーションのインストルメンテーションが必要である点が課題とされています。このような状況では、パフォーマンスのボトルネックを特定し、システムの最適化を図ることが難しくなります。 ### 既存手法とその課題 現在広く使用されている動的トレーシングツールには、[[OpenTracing]] API、[[Jaeger]]、[[Zipkin]]、Kieker、[[2010__Dapper, a Large-Scale Distributed Systems Tracing Infrastructure|Dapper]]などがあります。これらのツールは、クライアントリクエストのパスを追跡し、パフォーマンスの分析を行うために利用されます。しかし、これらのツールは以下の課題を抱えています: 1. 観測はユーザースペースに限定されているため、カーネルでの活動は観測されない。 2. アプリケーションのインストルメンテーションが必要であり、開発者の介入が求められる。 ### 課題に対する解決の提案 本論文では、これらの課題を解決するために、MiSeRTrace(MicroService Request Trace)という新しいオープンソースフレームワークを提案しています。MiSeRTraceは以下の特長を持ちます: 1. カーネルスペースでのエンドツーエンドのリクエストトレースを実現し、アプリケーションのインストルメンテーションや変更を必要としない。 2. bpftraceやftraceなどのフレームワークを利用して、ユーザーが有効にしたカーネルイベントをトレースし、アプリケーションリクエストに関連するカーネル活動を分離する。 3. これにより、ネットワーク転送やI/Oタスクなどの活動を詳細に分解し、パフォーマンス分析やホットスポットの特定を可能にする。 ### 実装と結果 MiSeRTraceは、[[DeathStarBench]]というオープンソースのマイクロサービスベンチマークスイートを用いて検証されています。このベンチマークにおいて、カーネルスペースでの動的トレーシングを行い、各クライアントリクエストのDAG(有向非巡回グラフ)を生成し、パフォーマンスの違いを理解するための分析が行われました。 ### 結論と将来の展望 MiSeRTraceは、アプリケーションのインストルメンテーションを必要とせずに、カーネルスペースでのリクエストトレーシングを実現することで、観測性の向上とパフォーマンスの最適化を支援します。将来的には、クラスタ環境でのカーネル活動のトレーシングをサポートすることで、さらにスケールの大きいアプリケーションに対しても対応可能にする予定です。 MiSeRTraceにはいくつかの限界や弱点があります。 1. **リクエストスループットの減少**: MiSeRTraceを使用して特定のイベントをトレースすると、リクエストスループットが約5-6%減少することがあります。これはトレースのオーバーヘッドによるもので、アプリケーションのパフォーマンスに影響を与える可能性があります 2. **トレースログの管理**: bpftraceを使用する場合、リングバッファの割り当てやトレースログのディスクへの書き込みが通知されないため、ユーザーがこれらを手動で管理する必要があります。また、bpftraceから取得されたログは各CPUごとに時系列に並んでいますが、グローバルに時系列に並んでいないため、これをソートするシステムも含まれています。 3. **大規模なアプリケーションへの対応**: 本論文での実験は大規模なコア数を持つサーバーで実施されていますが、将来的にはクラスタ環境でのカーネル活動のトレースをサポートすることが必要です。現在のMiSeRTraceの実装は単一のマシン上でのトレースに限られているため、スケールの大きいアプリケーションに対応するには追加の開発が必要です。 4. **ユーザーの設定の複雑さ**: MiSeRTraceはユーザーがトレースするイベントや設定を細かくカスタマイズできるように設計されていますが、これにより設定が複雑になり、適切な設定を行うためには十分な知識が必要となります。 スレッドステートモデル(Thread State Model, TSM)は、MiSeRTraceがリクエストのライフサイクルを通じてアプリケーションスレッドの活動を追跡するために使用する概念です。このモデルは、特定のカーネルイベントに基づいてスレッドの状態を管理し、各リクエストに関連する活動を可視化します。 ![[Pasted image 20240610183444.png|400]] ### スレッドステートモデルの構成 TSMは、主に以下の2種類の状態で構成されています。 1. **ネットワークスレッド状態 (Network Thread States)**: - この状態は、スレッドがTCPリクエストを受信した際に作成されます。 - 各ネットワーク状態は、送信元スレッド、TCP 4タプル(送信元および受信側のIPアドレスとポート番号)、およびリクエストのトレースIDによって一意に識別されます。 - ネットワーク状態は、リクエストの到着からそのリクエストに対する応答が送信されるまでの期間を表します。 2. **フォークスレッド状態 (Fork Thread States)**: - この状態は、スレッドが複数のリクエストを処理するためにフォーク(新しいスレッドを生成)した際に作成されます。 - 各フォーク状態は、親スレッドとそのスレッドを生成するリクエストのトレースIDによって一意に識別されます。 - フォーク状態は、子スレッドが生成されてから終了するまでの期間を表します。 ### スレッドステートモデルの動作 TSMは、以下のような手順でスレッドの状態を管理します。 1. **リクエストの追跡**: - スレッドがリクエストを受信すると、ネットワークスレッド状態が作成されます。 - 送信元スレッド、TCP 4タプル、およびリクエストのトレースIDに基づいて状態が識別されます。 2. **スレッドのフォーク**: - スレッドがフォークすると、フォークスレッド状態が作成されます。 - 親スレッドとリクエストのトレースIDに基づいて状態が識別されます。 3. **状態の更新**: - 各スレッドの状態は、リクエストのライフサイクル全体を通じて更新されます。 - ネットワークイベントやスケジューリングイベントに基づいて、状態が開始および終了します。 ### アルゴリズムの例 以下は、ネットワーク転送イベントを処理するTSMアルゴリズムの簡略化された例です。 ```python ThreadPool ← Map[Pid → Thread] SocketPool ← Map[(IpPair, PortPair) → Socket] SendSyscallsSet ← Set{sendto, sendmsg, write, writev} ReceiveSyscallsSet ← Set{recvfrom, recvmsg, read, readv} NetworkStateStore ← Map[(SrcThread, tcp4tuple, TraceId) → NetworkState] if currentSyscall ∈ SendSyscallsSet then if currentTracepoint.event = tcpSendKprobe then senderSock ← SocketPool.get(currentTracepoint.tcp4tuple) senderSock.senderThread ← currentThread senderSock.type ← REQUEST forall state ∈ NetworkStateStore.values() do if state.source = senderSock.destination then senderSock.type ← RESPONSE state.endSpan() break end end else if currentSyscall ∈ ReceiveSyscallsSet then if currentTracepoint.event = tcpRcvSpaceAdjust then receiverSock ← SocketPool.get(currentTracepoint.tcp4tuple) if receiverSock.type = REQUEST then senderThread ← receiverSock.senderThread forall traceID ∈ senderThread.allTraces do stateKey ← (senderThread, receiverSock.tcp4tuple, traceId) state ← createNetworkState(stateKey) state.source ← receiverSock.source state.startSpan() NetworkStateStore[stateKey] ← state end end end end ``` このアルゴリズムは、ネットワークイベントを監視してネットワークスレッド状態を作成および更新します。送信イベントや受信イベントに応じて、適切な状態が開始され、終了されます。 ### まとめ スレッドステートモデルは、MiSeRTraceがマイクロサービスアプリケーションのリクエスト処理を詳細に追跡するための中心的なコンポーネントです。このモデルを使用することで、各リクエストに関連するカーネルレベルの活動を可視化し、パフォーマンス分析やボトルネックの特定を可能にします。 ## Abstract マイクロサービスアプリケーションの進化に伴い、その基盤となるアーキテクチャは、モノリス型アプリケーションと比較してますます複雑になっています。このため、主に[[Observability]]という課題が発生します。分散アプリケーションの機能をより深く理解することで、実装のボトルネックを把握し、システムのパフォーマンスを向上させることが可能になります。分散アプリケーションの動的トレーシングを行う既存のツールで提供されるObservabilityは、ユーザ空間に限定されており、リクエストフローを追跡するためにアプリケーションをインスツルメント化する必要がある。本論文では、マイクロサービスアプリケーションに入るリクエストのエンドツーエンドのパスを、アプリケーションのインスツルメンテーションや修正を必要とせずにカーネル空間でトレースできる、新しいオープンソースフレームワークMiSeRTraceを紹介します。カーネル空間の包括的な観察が可能なため、ネットワーク転送やIOタスクなどのアクティビティの様々なステップを分解し、根本原因に基づくパフォーマンス解析やホットスポットの正確な特定が可能になります。MiSeRTraceは、[[bpftrace]]や[[ftrace]]などのフレームワークによって提供されるユーザー対応カーネルイベントのトレースをサポートし、最小限のオーバーヘッドで各アプリケーションリクエストに関連するカーネルアクティビティを切り分けます。次に、ベンチマークのマイクロサービス・アプリケーションの結果を用いて、このソリューションの動作を実証します。 [[2022__ICPE__MiSeRTrace - Kernel-level Request Tracing for Microservice Visibility__translations]]