Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo

1

© 2024 NTT DATA Group Corporation
© 2024 NTT DATA Group Corporation
2024/06/29 (Sat.) 15:00 – 15:45
Open Source Conference 2024 Hokkaido
せっかくのOSSなんだし、ソースコード読むよね︖
〜Apache Kafkaを例にしたOSSソースコードリーディングの基本〜
NTT DATA Group Corporation
Research and Development Headquarters, OSS Professional Services
Sasaki Toru / 佐々⽊ 徹

2

© 2024 NTT DATA Group Corporation 2
⾃⼰紹介: 佐々⽊ 徹 (ささき とおる)
過去の登壇の様⼦
NTTデータグループ 技術⾰新統括本部 技術開発本部 OSSプロフェッショナルサービス
所属
Strata Data Conference 2018 New York など多数
外部講演
翔泳社
「Apache Spark⼊⾨ 動かして学ぶ最新並列処理基盤フレームワーク」
「Apache Kafka 分散メッセージングシステムの構築と活⽤」 (ファーストオーサ)
書籍執筆
並列分散処理基盤による⼤量データ処理(バッチ処理/ストリーム処理)
専⾨領域
最近はOSSのApache Kafkaやこれを活⽤したパブリッククラウドサービスの活⽤が主領域

3

© 2024 NTT DATA Group Corporation 3
このセッションでお伝えしたいメッセージ
OSSのソースコードを読もう︕
こんな感じの
ソースコードを
読むことが
⽬標です
Apache Kafkaの
ソースコードの
ごく⼀部

4

© 2024 NTT DATA Group Corporation 4
Section.0
Apache Kafkaについて

5

© 2024 NTT DATA Group Corporation 5
分散メッセージングシステム Apache Kafka
ストリーム処理/リアルタイム処理の処理基盤の中⼼となるOSSのプロダクトで、
処理・活⽤基盤内でのストリームデータ(都度送受信される⼩さなデータの列)の適切な受け渡しを仲介してくれます
Apache Kafkaの詳細については公式のドキュメントも参考にしてください
https://kafka.apache.org/
データの生成 データの活用
Apache
Kafka データの処理
(この流れをデータが⽣成されたときなど必要な時に都度実施する)
⽣成される
データを
順次受信
必要な時に
データを後続に
送信(連携)
これらを適切に/安定的に⾏ってくれることで
都度処理/リアルタイム処理の実現や拡張性の確保が
容易に⾏えるようになる
(かなり乱暴な説明ですが)
ストリーム/リアルタイム処理中のMQ(メッセージングキュー)相当の役割

6

© 2024 NTT DATA Group Corporation 6
本セッションに登場するApache Kafkaのポイント・⽤語
本セッションの後半の説明で登場するApache Kafkaに関する概念をあらかじめ簡単にご紹介しておきます
データ送信元 データ受信先
送受信される
データ
Kafkaサーバ
Kafkaの⽤語
メッセージ
(送受信データ1つ)
Broker
(構成サーバ1台)
Consumer
(AP/コンポーネント)
Producer
(AP/コンポーネント)
特徴・ポイント
Kafkaが提供するAPIを⽤いて
⾃前でAPを実装したり、
関連するFWを利⽤したりする
データ送信元で⽣成/⽤意され次第
Kafkaサーバに送信されて、
通常メッセージ1つのサイズは⼩さい
複数台のサーバ(Broker)で構成され、
サーバ間で分散処理や同期を⾏って
性能や耐障害性を確保する
Producerと同様にAP⾃前実装や
FWの利⽤を⾏ったりする
複数台での分散処理もできる
送受信される
データ

7

© 2024 NTT DATA Group Corporation 7
Section.1
はじめてのOSSソースコードリーティング

8

© 2024 NTT DATA Group Corporation 8
OSSのソースコードを⼿に⼊れよう
プロダクトにより提供⽅法は異なりますので開発者(Contributors/Developers)向けの説明などで確認してください
GitHub/GitLabに存在するケースが多く、Apache KafkaのソースコードもGitHubから⼊⼿することができます
https://github.com/apache/kafka
$ git clone https://github.com/apache/kafka.git
Gitのコマンド ※WebページのURLとは違います (ページ中のCodeのボタンから取得)
多くのOSSの
ドキュメントには
こうした説明が
含まれています

9

© 2024 NTT DATA Group Corporation 9
ソースコードリーディングの環境を⽤意しよう
⼤きなプロジェクト(プロダクト)のソースコードを読むためにはIDE(統合開発環境)を利⽤するのが便利です
Apache Kafkaは⼤部分がJavaとScalaで記述されていますので、これらに対応したIDEを利⽤しましょう
Java/Scalaに対応している代表的なIDE
IDE 開発元 有償 / 無償
IntelliJ IDEA JetBrains 有償(Ultimate) / 無償(Community)
Visual Studio Code Microsoft 無償
Eclipse Eclipse Foundation 無償
Apache NetBeans Apache Software Foundation 無償
IntelliJ IDEAで⾒る
Kafkaのソース
以降の説明はIntelliJを前提に⾏います
IDEによって機能名や挙動に差がありますが、
概念などは同じです
※ 有償版と無償版で機能に差がありますが、
本セッションで紹介する機能や操作は
全て無償版でも利⽤/実施できます
JDKなど環境に
必要なツールは
あらかじめインストール
しておいてください

10

© 2024 NTT DATA Group Corporation 10
⼊⼿したソースコードをIDEにインポートして読める状態にしよう
規模の⼤きい多くのプロジェクト(プロダクト)はビルドツールによって管理されています
これを利⽤してIDEで⼊⼿したソースコードをインポートすると必要な設定などを⾃動で⾏なってくれて楽です
Java/Scalaで利⽤される主なビルドツール
ビルドツール 設定ファイルの例
Apache Maven pom.xml
Gradle build.gradle
sbt (Scala) build.sbt
(snip)
Apache Kafkaは
Gradleを利⽤しています
開く
先に⼊⼿した
Kafkaのソースコード
スクショはGitHubですが、
前項のgit cloneなどで
ローカルにあるはずです
IntelliJには
主なビルドツールが
バンドルされており、
追加のインストールなく
使えます

11

© 2024 NTT DATA Group Corporation 11
さあ、ソースコードを読んでいこう
ここまでの⼿順でソースコードが読めるようになりましたので、張り切って読んでいきましょう
(snip)
(snip)
多くの⼤きなプロジェクトは複数のモジュールから構成されています
server, clientなど⽬的のモジュールを参照してください
モジュール内にはプロダクトコードと
テストコードが存在しており、
Kafkaの場合はその中が
さらにjava/scala/resourcesに
分類されています
ソースコードの
インポートが完了した
IntelliJの
様⼦
プロダクトコード(main):
Kafkaとして実際に動作するコード
テストコード(test):
ビルド時に⾏われるUTのコード

12

© 2024 NTT DATA Group Corporation 12
上⼿にソースコードを読み進めていこう
IDEの機能を利⽤することで効率よく⽬的のソースコードの箇所を探せるようになります
ソースコードを読み進めるために利⽤するIntelliJの主な機能
機能 できること ショートカットキー (Mac) ショートカットキー (Win)
Go To
クラス・メソッド・変数・データ型などの定義や
クラス・メソッドの実装を参照
command(⌘) + B Ctrl + B
Call Hierarchy メソッドの呼び出し階層を検索 command(⌘) + shift(⇧) + H Ctrl + Shift + H
Find Usages クラス・メソッド・変数などの参照・利⽤箇所を検索 option(⌥) + F7 Ctrl + F7
Implementation(s) クラス・メソッドの実装を検索・参照 option(⌥) + command(⌘) + B Ctrl + Shift + B
Search 指定ファイル内で⽂字列検索 command(⌘) + F Ctrl + F
Find in Files プロジェクトで⽂字列検索 command(⌘) + shift(⇧) + F Ctrl + Shift + F
Search Everywhere
プロジェクト全体で
クラス・メソッド・ファイル・シンボルなどを検索
shift(⇧) × 2 Shift × 2
Back / Forward 定義の参照などのジャンプから戻る / 進む
option(⌥) + command(⌘) + ←
option(⌥) + command(⌘) + →
Ctrl + Alt + →
Ctrl + Alt + ←
※他のIDEでも概ね同種の機能が存在します
これ以外にも便利な機能やショートカットキーあります
ショートカットキーは
設定などによって
異なることがあります
(カスタマイズできます)

13

© 2024 NTT DATA Group Corporation 13
規模の⼤きいプロダクト(プロジェクト)では頻繁に他のメソッドの呼び出しを⾏いながら処理を実施します
これらの⾏程を追跡しながらソースコードを読み進めるために定義の確認や呼び出し元の検索などを⾏います
Go To (各種定義の参照/実装の参照)
IDEの機能を使って効率的に読み進めよう (1/3)
クラス・メソッド・フィールド・変数などの選択しているもの(カーソルの当たっているもの)の定義を参照します
インタフェース、抽象クラス、抽象メソッドを選択しているときはその実装を参照します
command(⌘) + B
メソッドを選択しているときはこのメソッドの定義を参照
Call Hierarchy (呼び出し階層の検索) command(⌘) + shift(⇧) + H
選択している(カーソルの当たっている)メソッド・フィールド・変数を呼び出しているメソッドを検索します
メソッドを選択しているときはこのメソッドを呼び出している階層を検索
検索対象のメソッド
から複数階層の
呼び出しが
検索できます

14

© 2024 NTT DATA Group Corporation 14
IDEの機能を使って効率的に読み進めよう (2/3)
規模の⼤きいプロダクト(プロジェクト)では定義されているクラス・メソッド・フィールド・変数が複数場所から参照されることがあります
キーとなるオブジェクトの変更が⾏われる箇所を検索することで全体の動作やロジックが把握できます
Find Usages (参照の検索)
クラス・メソッド・フィールド・変数などの選択しているもの(カーソルの当たっているもの)の参照を検索します
option(⌥) + F7
Implementation(s) (実装の検索) option(⌥) + command(⌘) + B
インタフェース、抽象クラス、抽象メソッドの実装を検索します
通常メソッドでOverrideされているメソッドがある場合はその検索を⾏います
クラスを選択しているときはこのクラスを参照している箇所を検索
クラスの参照検索では
staticメンバ、
フィールド定義、
インスタンス⽣成など
参照の種類別に
グルーピングされます
※変数の場合は
read/writeで区分
メソッドの場合はOverrideされているメソッドを検索
Overrideされた
複数のメソッドが
存在するときは
その全てがリストアップ
されます

15

© 2024 NTT DATA Group Corporation 15
IDEの機能を使って効率的に読み進めよう (3/3)
プロジェクト内で検索したいものがわかっている時は全体または指定範囲で⽂字列/シンボルの検索を⾏います
IntelliJを始めとする多くのIDEはあらかじめ検索⽤のインデックスを作成しているため、⾼速に検索できます
Find in Files (指定範囲で⽂字列検索)
プロジェクト全体、モジュールなど指定された範囲で⽂字列検索を⾏います
⼤⽂字⼩⽂字の区別や正規表現など詳細の条件指定もできます
command(⌘) + shift(⇧) + F
Search Everywhere (各種検索) shift(⇧) × 2
クラス、メソッド、変数など定義されているシンボルの検索を⾏います
IntelliJではソースコード中のシンボルのほか
IDEの操作(アクション)なども検索できます
検索キーワードの指定
検索結果
フィルタ指定や
正規表現指定
検索キーワードの指定
検索結果
緑の網掛けは
テストコード

16

© 2024 NTT DATA Group Corporation 16
動作状態の詳細を把握してさらに踏み込んで理解しよう (1/3)
処理やロジックが複雑なところではデバッガを使うと動作状態の詳細が把握でき、処理内容が理解しやすなります
Apache Kafkaのようなサーバソフトウェアに対してデバッガを利⽤するときはリモートデバッグを⾏います
デバッギ
(状態把握される側)
※ここではApache Kafka
IntelliJを含め
ほとんどのIDEには
デバッガ機能が
備わっています
デバッガ
(状態把握する側)
※ここではIntelliJ
NW接続して状態の取得や任意の処理の実⾏などのデバッグ操作
起動時にJVMのオプションとしてデバッギの設定を付与
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
※ポート番号などの設定は適宜変更してください
Run→
Edit Configuration
Remote
JVM
Debug
接続先(デバッギ)の
設定を⾏なって、
デバッギに接続

17

© 2024 NTT DATA Group Corporation 17
デバッガを利⽤することで実⾏中の任意の箇所/タイミングの変数/オブジェクトの状態の確認などが⾏えます
動作状態の詳細を把握してさらに踏み込んで理解しよう (2/3)
BreakPointの設定 (リモートデバッグ中⼀時停⽌する場所の設定)
リモートデバッグ中にこの箇所のコードが実⾏されて
処理が⼀時停⽌したとき
当該箇所の処理を
⾏うときの変数の状態が
読み取れる
必ず⼀時停⽌させるほか、特定の条件を
満たした時にのみ停⽌させる設定なども可能です
スレッドごと/
オブジェクトごとに
どのスレッドが
どういう過程(階層)で
当該箇所の処理を
⾏うかなどが読み取れる
(スレッドダンプ)

18

© 2024 NTT DATA Group Corporation 18
動作状態の詳細を把握してさらに踏み込んで理解しよう (3/3)
状態の確認以外にも処理のステップでの実⾏や任意の処理の実⾏をさせることもデバッガの利⽤で可能になります
BreakPointで停⽌した箇所から指定の⽅法で処理を進める
Step Over
Step Out
Step Into
その時停⽌しているBreakPointの次の⾏まで実⾏
BreakPointの⾏にメソッドの呼び出しがあるときはその呼び出し完了まで移動
その時停⽌しているBreakPointの次の⾏まで実⾏
BreakPointの⾏にメソッドの呼び出しがあるときはそのメソッド中の最初の⾏まで移動
その時停⽌しているBreakPointが存在するメソッドまで実⾏し、呼び出し元に移動
BreakPointの箇所で任意の処理を実⾏
ここでは異常時の動作再現の⽬的で
RuntimeExceptionをスローさせようとしている
⾏単位での動作の結果を都度確認し、詳細を把握したい場合などに利⽤
環境設定では再現が難しい例外スローなどの動作を再現したい場合などに利⽤

19

© 2024 NTT DATA Group Corporation 19
Section.2
OSSのソースコードリーディングの進め⽅

20

© 2024 NTT DATA Group Corporation 20
ソースコードを読むとは⾔っても、どこからどうやって読んでいけば良いのさ︖
ソースコードを読んで調べたいことや確認したいこと(⽬的)を確認してください
⽬的ごとにソースコードの該当箇所や⽬的の情報に到達しやすいアプローチがあります
ソースコードを読んで何かを調べる際の典型的なパターン ※典型的なアプローチであり、必ずこの通りでなければならないというわけではないです
パターン1: 調べたいものに関連するキーワードが存在する場合
パターン2: 特定の処理の動作の流れを調べたい場合
パターン3: 全体の構造や機構を把握したい場合
下に⾏くほど
煩雑/難しい
n 出⼒されたログの出⼒条件や正確な意味
n 設定(パラメタ)ごとの正確な動作や影響
n 記録された例外の発⽣箇所や発⽣条件
調べたいことの例
n 処理の過程で⾏われている具体の処理やその副作⽤
n 期待通りの処理結果とならないときの原因
調べたいことの例
n 内部構造の全体像やその相互関係
n 特定の処理によらない機構の動作や外部への副作⽤
調べたいことの例
典型的なアプローチ
典型的なアプローチ
典型的なアプローチ
キーワードをもとに全⽂検索(Find in Files)し、
当該場所から関連/⽬的箇所を探し出す
特定の処理の開始場所(e.g. 呼び出しメソッド)から
処理の流れを順に追っていく
内部構造/処理を司るオブジェクトなどの
⽣成箇所〜利⽤終了〜破棄までのサイクルを確認する
ここではこの2つの
エッセンスを観点に
ご説明します

21

© 2024 NTT DATA Group Corporation 21
パターン1: 調べたいものに関連するキーワードが存在する場合
ログの出⼒や発⽣した例外中のエラーメッセージなどのキーワードが存在するときは、これを利⽤して⽂字列検索から始めます
例1: 出⼒されたログについて調べるとき
例2: 設定(パラメタ)について調べるとき
エラーログに関連して
記録されたエラーメッセージ
(キーワード)
記録されたエラーログについて
エラー内容の正確な意味や発⽣原因を調べたいケースなど
Apache Kafkaのドキュメントから引⽤
(https://kafka.apache.org/documentation/#brokerconfigs_min.insync.replicas)
設定ファイルに
記載するパラメタ
(キーワード)
パラメタの設定ごとの正確な挙動や、
設定による影響などを調べたいケースなど

22

© 2024 NTT DATA Group Corporation 22
パターン1のソースコードリーディングの例 (1/5)
前項のエラーログを例として、ログメッセージの意味や対策を調べるためのソースコードリーディングを⾏なっていきます
Find in Files(⽂字列検索)でエラーメッセージ(キーワード)を検索
command(⌘) + shift(⇧) + F エラーメッセージには変数などその時の状態を動的に表⽰するものも多くあります
そのような内容と思われる項⽬が含まれるときはその箇所を外して検索するか、
正規表現でその箇所に何らかの⽂字列があるなどとして検索してください
コードの都合による途中の改⾏など、エラーメッセージが
ログ出⼒のコードにそのままの形で書かれていない場合もあるので、
マッチしないときは範囲を変えたりするなどして検索してください
当該のログメッセージを出⼒するコードが⾒つかる
複数⾒つかったときは
プレビューで詳細を確認して絞り込み

23

© 2024 NTT DATA Group Corporation 23
パターン1のソースコードリーディングの例 (2/5)
⾒つかったコードを確認して、当該のエラーメッセージが出⼒される原因や背景を理解していきます
前項で⾒つけた当該のエラーメッセージを出⼒するコード
当該エラーメッセージの
出⼒箇所
Kafka⽤語: HighWatermark
Broker間で同期を⾏う各Partitionのメッセージ(データ)のうち、
同期が完了した末尾(最新)のメッセージのOffset(通番)
当該のエラーメッセージはHighWatermarkの更新前のバリデーションに引っかかっており、
何らかの理由で期待されない(負数の)HighWatermarkが指定されたことが直接原因
HighWatermarkの
更新処理
当該のHighWatermarkはこのメソッドの呼び出し元から渡されてきているので、
この呼び出し階層を辿って、期待されないHighWatermarkが指定される箇所を探す
(分析)
(次⼿)
Call Hierarchy(呼び出し階層検索)で
このメソッドの呼び出し階層を調べる
command(⌘) + shift(⇧) + H

24

© 2024 NTT DATA Group Corporation 24
パターン1のソースコードリーディングの例 (3/5)
当該エラーメッセージを出⼒するメソッドの呼び出し階層を調べて期待しない値(HighWatermark)の出所を調べます
前項のメソッドに対してのCall Hierarchy(呼び出し階層検索)の実⾏結果
今回はスタックトレースが出⼒されているので、それと付き合わせることで呼び出し階層がわかる
スタックトレースがないログの記録を調べたい場合は、
その際に⾏なっていた処理を考慮するなどして呼び出し階層を特定してください
Go To(各種定義などを参照)で
このメソッドの定義を確認する
command(⌘) +B
このnextOffsetMetadataが動作に伴ってどういった変化をするか(変遷を辿るか)を確認する
そのためにこのnextOffsetMetadataが利⽤(特に書き換え)される場所を探す
(分析)
(次⼿)
このnextOffsetMetadataが問題の(期待外の負数である)HighWatermarkの出所
Find Usages(利⽤箇所の検索)で利⽤される箇所を探す
option(⌥) + F7
前項の
メソッド
処理コード⾃体の他に
コード中のコメントなども
参考になります

25

© 2024 NTT DATA Group Corporation 25
パターン1のソースコードリーディングの例 (4/5)
期待しない値(HighWatermark)の出所となる変数(nextOffsetMetadata)に関する操作を調べます
前項のnextOffsetMetadataのFind Usages(利⽤箇所の検索)の結果
テストコードなので
今回は関係ない
コメント中の
参照なので
今回は関係ない
nextOffsetMetadataの
オブジェクトに変更を及ぼす
処理の存在を確認する
→ 今回は存在せず
新たにオブジェクトを
代⼊する箇所があるので、
何が代⼊されるかを確認
最終的にHighWatermarkの値として
利⽤される末尾のOffsetが
ここで代⼊されている
このendOffsetの出所を探すために
updateLogEndOffsetのCall Hierarchy(呼び出し階層)を調べ、
今回の事象/処理に関連してendOffsetが変更される箇所を特定する
※流れはここまでと同じなので詳細は割愛
ここでLong型の値(lastOffset)に1を加算しているものの、
値の範囲のチェックを⾏なっていないため状況によってはオーバーフローすることがあり、
これによって期待外の値(負数のHighWatermark)が処理に⽤いられることになる
(分析)
※ 実際にはappendにlastOffsetが渡される前の段階での値の範囲のチェックの有無なども
確認した上で結論を出す必要がありますが、ここでは⽂量の問題で記載省略しています

26

© 2024 NTT DATA Group Corporation 26
パターン1のソースコードリーディングの例 (5/5)
ここまでのソースコードの調査でエラーメッセージの意味や発⽣原因を理解することができました
※実際にはこの後に裏取りのための再現試験や
デバッガによる確認などを⾏った上で断定します
エラーメッセージの意味、背景 HighWatermarkの更新時に本来期待しない負数が指定されたことで更新処理が継続できなかった
エラー発⽣の原因 Partition内のメッセージの記録数が多すぎて、付与するOffset(通番)がLong型で扱える範囲を超えてオーバーフローした
ソースコードの調査から理解できたエラー発⽣の背景と原因
補⾜1: KafkaのOffset(通番)のオーバーフローについて
記録されたエラーメッセージの原因はLong型のOffsetのオーバーフローと理解できましたが、通常の利⽤では本事象はまず起こらないことがわかっています
本事象はKafkaの耐性考慮の⼀環で、Maliciousなデータファイルを使⽤した場合(悪意を持ってデータファイルを改竄された場合)を模した検証で発⽣したものです
Long型の値空間は⾮常に広⼤なので、10〜15年程度の正当な運⽤でこの間⼀切の停⽌なく(24/365で)メッセージ(データ)の送信を⾏い続けた場合でも、
現在の計算機の性能では現実的に不可能な⾼スループットでなければ当該のオーバーフローは発⽣しない計算です
補⾜2: ご紹介したソースコードの確認の過程について
ここでは⼿法の紹介としてオーソドックスなソースコードリーディングの過程を説明しましたが、時間/紙⾯の都合で本来は実施すべき⼀部の確認が省略されている点に留意してください
こうした頻出しないエラーの情報は
検索してもヒットしづらいですが、
ソースコードの確認など適切なアプローチによって
確実に追求することができると考えてください
※ 主なところでは途中のlogEndOffsetMetadataの参照からのnextOffsetMetadataの変更や
LocalLogのオブジェクト⽣成時にコンストラクタ(apply)で参照渡しされる時点のnextOffsetMetadataの値などは確認する必要があります

27

© 2024 NTT DATA Group Corporation 27
パターン2: 特定の処理の動作の流れを調べたい場合
特定の処理の詳細の処理内容や挙動を調べたいときは呼び出しているメソッドなどをヒントに調べます
例: クライアントAPが呼び出すAPIの処理内容を調べたいとき
ProducerのAPがメッセージをBrokerに送信するコード
メッセージの送信を⾏う箇所で、
KafkaProducer.sendを呼び出している
呼び出した処理(メソッド)について期待通りの結果が得られないなどで、
内部で⾏われる処理の詳細/過程を調べたいケースなど

28

© 2024 NTT DATA Group Corporation 28
パターン2のソースコードリーディングの例 (1/2)
前項のProducerがメッセージを送信する処理の流れを例として、コードの読み⽅を確認していきます
KafkaProducer.sendを
呼び出して
メッセージ(データ)送信を
⾏なっている
Kafkaを利⽤するAPのサンプル
Search Everywhere
(クラスなどの検索)で
KafkaProducerクラスを
検索
shift(⇧) × 2
KafkaProducerのクラス

29

© 2024 NTT DATA Group Corporation 29
パターン2のソースコードリーディングの例 (2/2)
挙動を調べたいメソッド(sendメソッド)を順に処理内容を確認していきます
前項で開いたKafkaProducerのクラス
Search(ファイル内検索)で
⽬的のメソッド定義を探す
command(⌘) + F
別のメソッドを呼び出しているのでGo Toで定義を参照して読み進める
command(⌘) + B
以降同様に定義クラス/メソッドの
定義を確認しながら
処理完了まで読み進める

30

© 2024 NTT DATA Group Corporation 30
処理内容を読み進めやすくするポイント (1/2)
クラス/メソッドの定義の確認だけでは処理の流れを追いきれない箇所があります
プロダクトごとのお作法を把握しておくと途中で処理の流れを⾒失うことなく読み進められます
クラス/メソッドの定義の確認だけでは処理の流れが追いづらい主なポイント
Apache Kafkaの例: クライアント/サーバ間、サーバ間の通信
l クライアント/サーバ間の通信、プロセス間通信
l ファイルや外部データストアへのデータのRead/Write
l キューなどを⽤いた⾮同期処理
送受信や読み込み/書き込みが別のコードとして記載され、
呼び出し階層でのつながりがない場合があるので定義の確認のみでは把握できないことがある
※ ⼀部のRPC通信のライブラリではIDEでの追跡を楽にするような構造を有するものもあります
対象とするプロダクトが利⽤しているライブラリの仕様などを確認してください
Kafkaの送受信では全ての送受信でリクエスト/レスポンスの形式をとり、送受信されるペイロードのデータ形式が定義されています
送受信する箇所では必ずBuilderでリクエスト/レスポンスのオブジェクトを⽣成します
Produceリクエスト(メッセージ送信リクエスト)を⽣成する箇所のコード(Sender.javaに存在)

31

© 2024 NTT DATA Group Corporation 31
処理内容を読み進めやすくするポイント (2/2)
処理の流れを追っていく⼊り⼝としてAPが利⽤するAPI(メソッドなど)以外にも扱いやすいポイントを設けておくと良いです
処理の流れを追う⼊り⼝としやすいポイント
Apache Kafkaの例: Brokerのリクエスト種類別の分岐箇所
l 内部処理などのスレッドの処理の開始地点 (Thread.runなど)
l 外部から受け付けるリクエストに対応する処理の開始時点
KafkaのBrokerにはクライアント/別サーバから受け取ったリクエストの種類を判別して⽬的の処理に振り分ける箇所があります
Broker内部のリクエストに関連する処理はここを起点とすると確認しやすくなります
Brokerのリクエスト別の処理に振り分ける箇所のコード(KafkaApis.scalaに存在)
リクエスト別に処理メソッドが⽤意されているため、
処理の流れを確認したいリクエストに対応する
メソッドの定義を確認すれば良い
command(⌘) + B
60以上の
リクエストに対する
定義が存在している

32

© 2024 NTT DATA Group Corporation 32
Section.3
クロージング

33

© 2024 NTT DATA Group Corporation 33
本セッションでお話ししたこと
OSSの分散メッセージングシステムApache Kafkaを例にソースコードリーティングの基本についてお話ししました
ソースコードリーティングの
基本的な⽅法の紹介
Apache Kafkaを例にした
具体的な進め⽅の紹介

34

せっかくのOSSなんだし、ソースコード読むよね? 〜Apache Kafkaを例にしたOSSソースコードリーディングの基本〜 (Open Source Conference 2024 Hokkaido 発表資料)

More Related Content

せっかくのOSSなんだし、ソースコード読むよね? 〜Apache Kafkaを例にしたOSSソースコードリーディングの基本〜 (Open Source Conference 2024 Hokkaido 発表資料)

  • 1. © 2024 NTT DATA Group Corporation © 2024 NTT DATA Group Corporation 2024/06/29 (Sat.) 15:00 – 15:45 Open Source Conference 2024 Hokkaido せっかくのOSSなんだし、ソースコード読むよね︖ 〜Apache Kafkaを例にしたOSSソースコードリーディングの基本〜 NTT DATA Group Corporation Research and Development Headquarters, OSS Professional Services Sasaki Toru / 佐々⽊ 徹
  • 2. © 2024 NTT DATA Group Corporation 2 ⾃⼰紹介: 佐々⽊ 徹 (ささき とおる) 過去の登壇の様⼦ NTTデータグループ 技術⾰新統括本部 技術開発本部 OSSプロフェッショナルサービス 所属 Strata Data Conference 2018 New York など多数 外部講演 翔泳社 「Apache Spark⼊⾨ 動かして学ぶ最新並列処理基盤フレームワーク」 「Apache Kafka 分散メッセージングシステムの構築と活⽤」 (ファーストオーサ) 書籍執筆 並列分散処理基盤による⼤量データ処理(バッチ処理/ストリーム処理) 専⾨領域 最近はOSSのApache Kafkaやこれを活⽤したパブリッククラウドサービスの活⽤が主領域
  • 3. © 2024 NTT DATA Group Corporation 3 このセッションでお伝えしたいメッセージ OSSのソースコードを読もう︕ こんな感じの ソースコードを 読むことが ⽬標です Apache Kafkaの ソースコードの ごく⼀部
  • 4. © 2024 NTT DATA Group Corporation 4 Section.0 Apache Kafkaについて
  • 5. © 2024 NTT DATA Group Corporation 5 分散メッセージングシステム Apache Kafka ストリーム処理/リアルタイム処理の処理基盤の中⼼となるOSSのプロダクトで、 処理・活⽤基盤内でのストリームデータ(都度送受信される⼩さなデータの列)の適切な受け渡しを仲介してくれます Apache Kafkaの詳細については公式のドキュメントも参考にしてください https://kafka.apache.org/ データの生成 データの活用 Apache Kafka データの処理 (この流れをデータが⽣成されたときなど必要な時に都度実施する) ⽣成される データを 順次受信 必要な時に データを後続に 送信(連携) これらを適切に/安定的に⾏ってくれることで 都度処理/リアルタイム処理の実現や拡張性の確保が 容易に⾏えるようになる (かなり乱暴な説明ですが) ストリーム/リアルタイム処理中のMQ(メッセージングキュー)相当の役割
  • 6. © 2024 NTT DATA Group Corporation 6 本セッションに登場するApache Kafkaのポイント・⽤語 本セッションの後半の説明で登場するApache Kafkaに関する概念をあらかじめ簡単にご紹介しておきます データ送信元 データ受信先 送受信される データ Kafkaサーバ Kafkaの⽤語 メッセージ (送受信データ1つ) Broker (構成サーバ1台) Consumer (AP/コンポーネント) Producer (AP/コンポーネント) 特徴・ポイント Kafkaが提供するAPIを⽤いて ⾃前でAPを実装したり、 関連するFWを利⽤したりする データ送信元で⽣成/⽤意され次第 Kafkaサーバに送信されて、 通常メッセージ1つのサイズは⼩さい 複数台のサーバ(Broker)で構成され、 サーバ間で分散処理や同期を⾏って 性能や耐障害性を確保する Producerと同様にAP⾃前実装や FWの利⽤を⾏ったりする 複数台での分散処理もできる 送受信される データ
  • 7. © 2024 NTT DATA Group Corporation 7 Section.1 はじめてのOSSソースコードリーティング
  • 8. © 2024 NTT DATA Group Corporation 8 OSSのソースコードを⼿に⼊れよう プロダクトにより提供⽅法は異なりますので開発者(Contributors/Developers)向けの説明などで確認してください GitHub/GitLabに存在するケースが多く、Apache KafkaのソースコードもGitHubから⼊⼿することができます https://github.com/apache/kafka $ git clone https://github.com/apache/kafka.git Gitのコマンド ※WebページのURLとは違います (ページ中のCodeのボタンから取得) 多くのOSSの ドキュメントには こうした説明が 含まれています
  • 9. © 2024 NTT DATA Group Corporation 9 ソースコードリーディングの環境を⽤意しよう ⼤きなプロジェクト(プロダクト)のソースコードを読むためにはIDE(統合開発環境)を利⽤するのが便利です Apache Kafkaは⼤部分がJavaとScalaで記述されていますので、これらに対応したIDEを利⽤しましょう Java/Scalaに対応している代表的なIDE IDE 開発元 有償 / 無償 IntelliJ IDEA JetBrains 有償(Ultimate) / 無償(Community) Visual Studio Code Microsoft 無償 Eclipse Eclipse Foundation 無償 Apache NetBeans Apache Software Foundation 無償 IntelliJ IDEAで⾒る Kafkaのソース 以降の説明はIntelliJを前提に⾏います IDEによって機能名や挙動に差がありますが、 概念などは同じです ※ 有償版と無償版で機能に差がありますが、 本セッションで紹介する機能や操作は 全て無償版でも利⽤/実施できます JDKなど環境に 必要なツールは あらかじめインストール しておいてください
  • 10. © 2024 NTT DATA Group Corporation 10 ⼊⼿したソースコードをIDEにインポートして読める状態にしよう 規模の⼤きい多くのプロジェクト(プロダクト)はビルドツールによって管理されています これを利⽤してIDEで⼊⼿したソースコードをインポートすると必要な設定などを⾃動で⾏なってくれて楽です Java/Scalaで利⽤される主なビルドツール ビルドツール 設定ファイルの例 Apache Maven pom.xml Gradle build.gradle sbt (Scala) build.sbt (snip) Apache Kafkaは Gradleを利⽤しています 開く 先に⼊⼿した Kafkaのソースコード スクショはGitHubですが、 前項のgit cloneなどで ローカルにあるはずです IntelliJには 主なビルドツールが バンドルされており、 追加のインストールなく 使えます
  • 11. © 2024 NTT DATA Group Corporation 11 さあ、ソースコードを読んでいこう ここまでの⼿順でソースコードが読めるようになりましたので、張り切って読んでいきましょう (snip) (snip) 多くの⼤きなプロジェクトは複数のモジュールから構成されています server, clientなど⽬的のモジュールを参照してください モジュール内にはプロダクトコードと テストコードが存在しており、 Kafkaの場合はその中が さらにjava/scala/resourcesに 分類されています ソースコードの インポートが完了した IntelliJの 様⼦ プロダクトコード(main): Kafkaとして実際に動作するコード テストコード(test): ビルド時に⾏われるUTのコード
  • 12. © 2024 NTT DATA Group Corporation 12 上⼿にソースコードを読み進めていこう IDEの機能を利⽤することで効率よく⽬的のソースコードの箇所を探せるようになります ソースコードを読み進めるために利⽤するIntelliJの主な機能 機能 できること ショートカットキー (Mac) ショートカットキー (Win) Go To クラス・メソッド・変数・データ型などの定義や クラス・メソッドの実装を参照 command(⌘) + B Ctrl + B Call Hierarchy メソッドの呼び出し階層を検索 command(⌘) + shift(⇧) + H Ctrl + Shift + H Find Usages クラス・メソッド・変数などの参照・利⽤箇所を検索 option(⌥) + F7 Ctrl + F7 Implementation(s) クラス・メソッドの実装を検索・参照 option(⌥) + command(⌘) + B Ctrl + Shift + B Search 指定ファイル内で⽂字列検索 command(⌘) + F Ctrl + F Find in Files プロジェクトで⽂字列検索 command(⌘) + shift(⇧) + F Ctrl + Shift + F Search Everywhere プロジェクト全体で クラス・メソッド・ファイル・シンボルなどを検索 shift(⇧) × 2 Shift × 2 Back / Forward 定義の参照などのジャンプから戻る / 進む option(⌥) + command(⌘) + ← option(⌥) + command(⌘) + → Ctrl + Alt + → Ctrl + Alt + ← ※他のIDEでも概ね同種の機能が存在します これ以外にも便利な機能やショートカットキーあります ショートカットキーは 設定などによって 異なることがあります (カスタマイズできます)
  • 13. © 2024 NTT DATA Group Corporation 13 規模の⼤きいプロダクト(プロジェクト)では頻繁に他のメソッドの呼び出しを⾏いながら処理を実施します これらの⾏程を追跡しながらソースコードを読み進めるために定義の確認や呼び出し元の検索などを⾏います Go To (各種定義の参照/実装の参照) IDEの機能を使って効率的に読み進めよう (1/3) クラス・メソッド・フィールド・変数などの選択しているもの(カーソルの当たっているもの)の定義を参照します インタフェース、抽象クラス、抽象メソッドを選択しているときはその実装を参照します command(⌘) + B メソッドを選択しているときはこのメソッドの定義を参照 Call Hierarchy (呼び出し階層の検索) command(⌘) + shift(⇧) + H 選択している(カーソルの当たっている)メソッド・フィールド・変数を呼び出しているメソッドを検索します メソッドを選択しているときはこのメソッドを呼び出している階層を検索 検索対象のメソッド から複数階層の 呼び出しが 検索できます
  • 14. © 2024 NTT DATA Group Corporation 14 IDEの機能を使って効率的に読み進めよう (2/3) 規模の⼤きいプロダクト(プロジェクト)では定義されているクラス・メソッド・フィールド・変数が複数場所から参照されることがあります キーとなるオブジェクトの変更が⾏われる箇所を検索することで全体の動作やロジックが把握できます Find Usages (参照の検索) クラス・メソッド・フィールド・変数などの選択しているもの(カーソルの当たっているもの)の参照を検索します option(⌥) + F7 Implementation(s) (実装の検索) option(⌥) + command(⌘) + B インタフェース、抽象クラス、抽象メソッドの実装を検索します 通常メソッドでOverrideされているメソッドがある場合はその検索を⾏います クラスを選択しているときはこのクラスを参照している箇所を検索 クラスの参照検索では staticメンバ、 フィールド定義、 インスタンス⽣成など 参照の種類別に グルーピングされます ※変数の場合は read/writeで区分 メソッドの場合はOverrideされているメソッドを検索 Overrideされた 複数のメソッドが 存在するときは その全てがリストアップ されます
  • 15. © 2024 NTT DATA Group Corporation 15 IDEの機能を使って効率的に読み進めよう (3/3) プロジェクト内で検索したいものがわかっている時は全体または指定範囲で⽂字列/シンボルの検索を⾏います IntelliJを始めとする多くのIDEはあらかじめ検索⽤のインデックスを作成しているため、⾼速に検索できます Find in Files (指定範囲で⽂字列検索) プロジェクト全体、モジュールなど指定された範囲で⽂字列検索を⾏います ⼤⽂字⼩⽂字の区別や正規表現など詳細の条件指定もできます command(⌘) + shift(⇧) + F Search Everywhere (各種検索) shift(⇧) × 2 クラス、メソッド、変数など定義されているシンボルの検索を⾏います IntelliJではソースコード中のシンボルのほか IDEの操作(アクション)なども検索できます 検索キーワードの指定 検索結果 フィルタ指定や 正規表現指定 検索キーワードの指定 検索結果 緑の網掛けは テストコード
  • 16. © 2024 NTT DATA Group Corporation 16 動作状態の詳細を把握してさらに踏み込んで理解しよう (1/3) 処理やロジックが複雑なところではデバッガを使うと動作状態の詳細が把握でき、処理内容が理解しやすなります Apache Kafkaのようなサーバソフトウェアに対してデバッガを利⽤するときはリモートデバッグを⾏います デバッギ (状態把握される側) ※ここではApache Kafka IntelliJを含め ほとんどのIDEには デバッガ機能が 備わっています デバッガ (状態把握する側) ※ここではIntelliJ NW接続して状態の取得や任意の処理の実⾏などのデバッグ操作 起動時にJVMのオプションとしてデバッギの設定を付与 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 ※ポート番号などの設定は適宜変更してください Run→ Edit Configuration Remote JVM Debug 接続先(デバッギ)の 設定を⾏なって、 デバッギに接続
  • 17. © 2024 NTT DATA Group Corporation 17 デバッガを利⽤することで実⾏中の任意の箇所/タイミングの変数/オブジェクトの状態の確認などが⾏えます 動作状態の詳細を把握してさらに踏み込んで理解しよう (2/3) BreakPointの設定 (リモートデバッグ中⼀時停⽌する場所の設定) リモートデバッグ中にこの箇所のコードが実⾏されて 処理が⼀時停⽌したとき 当該箇所の処理を ⾏うときの変数の状態が 読み取れる 必ず⼀時停⽌させるほか、特定の条件を 満たした時にのみ停⽌させる設定なども可能です スレッドごと/ オブジェクトごとに どのスレッドが どういう過程(階層)で 当該箇所の処理を ⾏うかなどが読み取れる (スレッドダンプ)
  • 18. © 2024 NTT DATA Group Corporation 18 動作状態の詳細を把握してさらに踏み込んで理解しよう (3/3) 状態の確認以外にも処理のステップでの実⾏や任意の処理の実⾏をさせることもデバッガの利⽤で可能になります BreakPointで停⽌した箇所から指定の⽅法で処理を進める Step Over Step Out Step Into その時停⽌しているBreakPointの次の⾏まで実⾏ BreakPointの⾏にメソッドの呼び出しがあるときはその呼び出し完了まで移動 その時停⽌しているBreakPointの次の⾏まで実⾏ BreakPointの⾏にメソッドの呼び出しがあるときはそのメソッド中の最初の⾏まで移動 その時停⽌しているBreakPointが存在するメソッドまで実⾏し、呼び出し元に移動 BreakPointの箇所で任意の処理を実⾏ ここでは異常時の動作再現の⽬的で RuntimeExceptionをスローさせようとしている ⾏単位での動作の結果を都度確認し、詳細を把握したい場合などに利⽤ 環境設定では再現が難しい例外スローなどの動作を再現したい場合などに利⽤
  • 19. © 2024 NTT DATA Group Corporation 19 Section.2 OSSのソースコードリーディングの進め⽅
  • 20. © 2024 NTT DATA Group Corporation 20 ソースコードを読むとは⾔っても、どこからどうやって読んでいけば良いのさ︖ ソースコードを読んで調べたいことや確認したいこと(⽬的)を確認してください ⽬的ごとにソースコードの該当箇所や⽬的の情報に到達しやすいアプローチがあります ソースコードを読んで何かを調べる際の典型的なパターン ※典型的なアプローチであり、必ずこの通りでなければならないというわけではないです パターン1: 調べたいものに関連するキーワードが存在する場合 パターン2: 特定の処理の動作の流れを調べたい場合 パターン3: 全体の構造や機構を把握したい場合 下に⾏くほど 煩雑/難しい n 出⼒されたログの出⼒条件や正確な意味 n 設定(パラメタ)ごとの正確な動作や影響 n 記録された例外の発⽣箇所や発⽣条件 調べたいことの例 n 処理の過程で⾏われている具体の処理やその副作⽤ n 期待通りの処理結果とならないときの原因 調べたいことの例 n 内部構造の全体像やその相互関係 n 特定の処理によらない機構の動作や外部への副作⽤ 調べたいことの例 典型的なアプローチ 典型的なアプローチ 典型的なアプローチ キーワードをもとに全⽂検索(Find in Files)し、 当該場所から関連/⽬的箇所を探し出す 特定の処理の開始場所(e.g. 呼び出しメソッド)から 処理の流れを順に追っていく 内部構造/処理を司るオブジェクトなどの ⽣成箇所〜利⽤終了〜破棄までのサイクルを確認する ここではこの2つの エッセンスを観点に ご説明します
  • 21. © 2024 NTT DATA Group Corporation 21 パターン1: 調べたいものに関連するキーワードが存在する場合 ログの出⼒や発⽣した例外中のエラーメッセージなどのキーワードが存在するときは、これを利⽤して⽂字列検索から始めます 例1: 出⼒されたログについて調べるとき 例2: 設定(パラメタ)について調べるとき エラーログに関連して 記録されたエラーメッセージ (キーワード) 記録されたエラーログについて エラー内容の正確な意味や発⽣原因を調べたいケースなど Apache Kafkaのドキュメントから引⽤ (https://kafka.apache.org/documentation/#brokerconfigs_min.insync.replicas) 設定ファイルに 記載するパラメタ (キーワード) パラメタの設定ごとの正確な挙動や、 設定による影響などを調べたいケースなど
  • 22. © 2024 NTT DATA Group Corporation 22 パターン1のソースコードリーディングの例 (1/5) 前項のエラーログを例として、ログメッセージの意味や対策を調べるためのソースコードリーディングを⾏なっていきます Find in Files(⽂字列検索)でエラーメッセージ(キーワード)を検索 command(⌘) + shift(⇧) + F エラーメッセージには変数などその時の状態を動的に表⽰するものも多くあります そのような内容と思われる項⽬が含まれるときはその箇所を外して検索するか、 正規表現でその箇所に何らかの⽂字列があるなどとして検索してください コードの都合による途中の改⾏など、エラーメッセージが ログ出⼒のコードにそのままの形で書かれていない場合もあるので、 マッチしないときは範囲を変えたりするなどして検索してください 当該のログメッセージを出⼒するコードが⾒つかる 複数⾒つかったときは プレビューで詳細を確認して絞り込み
  • 23. © 2024 NTT DATA Group Corporation 23 パターン1のソースコードリーディングの例 (2/5) ⾒つかったコードを確認して、当該のエラーメッセージが出⼒される原因や背景を理解していきます 前項で⾒つけた当該のエラーメッセージを出⼒するコード 当該エラーメッセージの 出⼒箇所 Kafka⽤語: HighWatermark Broker間で同期を⾏う各Partitionのメッセージ(データ)のうち、 同期が完了した末尾(最新)のメッセージのOffset(通番) 当該のエラーメッセージはHighWatermarkの更新前のバリデーションに引っかかっており、 何らかの理由で期待されない(負数の)HighWatermarkが指定されたことが直接原因 HighWatermarkの 更新処理 当該のHighWatermarkはこのメソッドの呼び出し元から渡されてきているので、 この呼び出し階層を辿って、期待されないHighWatermarkが指定される箇所を探す (分析) (次⼿) Call Hierarchy(呼び出し階層検索)で このメソッドの呼び出し階層を調べる command(⌘) + shift(⇧) + H
  • 24. © 2024 NTT DATA Group Corporation 24 パターン1のソースコードリーディングの例 (3/5) 当該エラーメッセージを出⼒するメソッドの呼び出し階層を調べて期待しない値(HighWatermark)の出所を調べます 前項のメソッドに対してのCall Hierarchy(呼び出し階層検索)の実⾏結果 今回はスタックトレースが出⼒されているので、それと付き合わせることで呼び出し階層がわかる スタックトレースがないログの記録を調べたい場合は、 その際に⾏なっていた処理を考慮するなどして呼び出し階層を特定してください Go To(各種定義などを参照)で このメソッドの定義を確認する command(⌘) +B このnextOffsetMetadataが動作に伴ってどういった変化をするか(変遷を辿るか)を確認する そのためにこのnextOffsetMetadataが利⽤(特に書き換え)される場所を探す (分析) (次⼿) このnextOffsetMetadataが問題の(期待外の負数である)HighWatermarkの出所 Find Usages(利⽤箇所の検索)で利⽤される箇所を探す option(⌥) + F7 前項の メソッド 処理コード⾃体の他に コード中のコメントなども 参考になります
  • 25. © 2024 NTT DATA Group Corporation 25 パターン1のソースコードリーディングの例 (4/5) 期待しない値(HighWatermark)の出所となる変数(nextOffsetMetadata)に関する操作を調べます 前項のnextOffsetMetadataのFind Usages(利⽤箇所の検索)の結果 テストコードなので 今回は関係ない コメント中の 参照なので 今回は関係ない nextOffsetMetadataの オブジェクトに変更を及ぼす 処理の存在を確認する → 今回は存在せず 新たにオブジェクトを 代⼊する箇所があるので、 何が代⼊されるかを確認 最終的にHighWatermarkの値として 利⽤される末尾のOffsetが ここで代⼊されている このendOffsetの出所を探すために updateLogEndOffsetのCall Hierarchy(呼び出し階層)を調べ、 今回の事象/処理に関連してendOffsetが変更される箇所を特定する ※流れはここまでと同じなので詳細は割愛 ここでLong型の値(lastOffset)に1を加算しているものの、 値の範囲のチェックを⾏なっていないため状況によってはオーバーフローすることがあり、 これによって期待外の値(負数のHighWatermark)が処理に⽤いられることになる (分析) ※ 実際にはappendにlastOffsetが渡される前の段階での値の範囲のチェックの有無なども 確認した上で結論を出す必要がありますが、ここでは⽂量の問題で記載省略しています
  • 26. © 2024 NTT DATA Group Corporation 26 パターン1のソースコードリーディングの例 (5/5) ここまでのソースコードの調査でエラーメッセージの意味や発⽣原因を理解することができました ※実際にはこの後に裏取りのための再現試験や デバッガによる確認などを⾏った上で断定します エラーメッセージの意味、背景 HighWatermarkの更新時に本来期待しない負数が指定されたことで更新処理が継続できなかった エラー発⽣の原因 Partition内のメッセージの記録数が多すぎて、付与するOffset(通番)がLong型で扱える範囲を超えてオーバーフローした ソースコードの調査から理解できたエラー発⽣の背景と原因 補⾜1: KafkaのOffset(通番)のオーバーフローについて 記録されたエラーメッセージの原因はLong型のOffsetのオーバーフローと理解できましたが、通常の利⽤では本事象はまず起こらないことがわかっています 本事象はKafkaの耐性考慮の⼀環で、Maliciousなデータファイルを使⽤した場合(悪意を持ってデータファイルを改竄された場合)を模した検証で発⽣したものです Long型の値空間は⾮常に広⼤なので、10〜15年程度の正当な運⽤でこの間⼀切の停⽌なく(24/365で)メッセージ(データ)の送信を⾏い続けた場合でも、 現在の計算機の性能では現実的に不可能な⾼スループットでなければ当該のオーバーフローは発⽣しない計算です 補⾜2: ご紹介したソースコードの確認の過程について ここでは⼿法の紹介としてオーソドックスなソースコードリーディングの過程を説明しましたが、時間/紙⾯の都合で本来は実施すべき⼀部の確認が省略されている点に留意してください こうした頻出しないエラーの情報は 検索してもヒットしづらいですが、 ソースコードの確認など適切なアプローチによって 確実に追求することができると考えてください ※ 主なところでは途中のlogEndOffsetMetadataの参照からのnextOffsetMetadataの変更や LocalLogのオブジェクト⽣成時にコンストラクタ(apply)で参照渡しされる時点のnextOffsetMetadataの値などは確認する必要があります
  • 27. © 2024 NTT DATA Group Corporation 27 パターン2: 特定の処理の動作の流れを調べたい場合 特定の処理の詳細の処理内容や挙動を調べたいときは呼び出しているメソッドなどをヒントに調べます 例: クライアントAPが呼び出すAPIの処理内容を調べたいとき ProducerのAPがメッセージをBrokerに送信するコード メッセージの送信を⾏う箇所で、 KafkaProducer.sendを呼び出している 呼び出した処理(メソッド)について期待通りの結果が得られないなどで、 内部で⾏われる処理の詳細/過程を調べたいケースなど
  • 28. © 2024 NTT DATA Group Corporation 28 パターン2のソースコードリーディングの例 (1/2) 前項のProducerがメッセージを送信する処理の流れを例として、コードの読み⽅を確認していきます KafkaProducer.sendを 呼び出して メッセージ(データ)送信を ⾏なっている Kafkaを利⽤するAPのサンプル Search Everywhere (クラスなどの検索)で KafkaProducerクラスを 検索 shift(⇧) × 2 KafkaProducerのクラス
  • 29. © 2024 NTT DATA Group Corporation 29 パターン2のソースコードリーディングの例 (2/2) 挙動を調べたいメソッド(sendメソッド)を順に処理内容を確認していきます 前項で開いたKafkaProducerのクラス Search(ファイル内検索)で ⽬的のメソッド定義を探す command(⌘) + F 別のメソッドを呼び出しているのでGo Toで定義を参照して読み進める command(⌘) + B 以降同様に定義クラス/メソッドの 定義を確認しながら 処理完了まで読み進める
  • 30. © 2024 NTT DATA Group Corporation 30 処理内容を読み進めやすくするポイント (1/2) クラス/メソッドの定義の確認だけでは処理の流れを追いきれない箇所があります プロダクトごとのお作法を把握しておくと途中で処理の流れを⾒失うことなく読み進められます クラス/メソッドの定義の確認だけでは処理の流れが追いづらい主なポイント Apache Kafkaの例: クライアント/サーバ間、サーバ間の通信 l クライアント/サーバ間の通信、プロセス間通信 l ファイルや外部データストアへのデータのRead/Write l キューなどを⽤いた⾮同期処理 送受信や読み込み/書き込みが別のコードとして記載され、 呼び出し階層でのつながりがない場合があるので定義の確認のみでは把握できないことがある ※ ⼀部のRPC通信のライブラリではIDEでの追跡を楽にするような構造を有するものもあります 対象とするプロダクトが利⽤しているライブラリの仕様などを確認してください Kafkaの送受信では全ての送受信でリクエスト/レスポンスの形式をとり、送受信されるペイロードのデータ形式が定義されています 送受信する箇所では必ずBuilderでリクエスト/レスポンスのオブジェクトを⽣成します Produceリクエスト(メッセージ送信リクエスト)を⽣成する箇所のコード(Sender.javaに存在)
  • 31. © 2024 NTT DATA Group Corporation 31 処理内容を読み進めやすくするポイント (2/2) 処理の流れを追っていく⼊り⼝としてAPが利⽤するAPI(メソッドなど)以外にも扱いやすいポイントを設けておくと良いです 処理の流れを追う⼊り⼝としやすいポイント Apache Kafkaの例: Brokerのリクエスト種類別の分岐箇所 l 内部処理などのスレッドの処理の開始地点 (Thread.runなど) l 外部から受け付けるリクエストに対応する処理の開始時点 KafkaのBrokerにはクライアント/別サーバから受け取ったリクエストの種類を判別して⽬的の処理に振り分ける箇所があります Broker内部のリクエストに関連する処理はここを起点とすると確認しやすくなります Brokerのリクエスト別の処理に振り分ける箇所のコード(KafkaApis.scalaに存在) リクエスト別に処理メソッドが⽤意されているため、 処理の流れを確認したいリクエストに対応する メソッドの定義を確認すれば良い command(⌘) + B 60以上の リクエストに対する 定義が存在している
  • 32. © 2024 NTT DATA Group Corporation 32 Section.3 クロージング
  • 33. © 2024 NTT DATA Group Corporation 33 本セッションでお話ししたこと OSSの分散メッセージングシステムApache Kafkaを例にソースコードリーティングの基本についてお話ししました ソースコードリーティングの 基本的な⽅法の紹介 Apache Kafkaを例にした 具体的な進め⽅の紹介