こんにちは
背景
HDFSのデータをsparkでよみとってから、KVSにWriteするバッチが、メモリーリークを起こした
バッチsparkはyarnで動かしているが、KVS今回はcouchbaseに、書き込む部分はdriverで書いている
couchbaseのライブライはJavaのCouchbase-clientを使用している
タスク
メモリーリークの修正
挙動としては、driverサイドのメモリーが、当然、spark-submit的にmaxメモリを指定している、例えば12Gとかにするのだけど、
それ以上に、増加していき,最終的にはホストのメモリを全て食い尽くしOSがエラーをだしプロセスが強制終了された。
まずは原因特定したい。そもそも、
executorsサイドからcouchbaseに書き込んでないのは、KVSの書き込み速度をより制御しやすいのは、driverからだと判断したからだ。
アクション
JVMのメモリの復習と各種設定が正しく反映されているか?
`java -XX:+PrintFlagsFinal -version | grep -iE 'heapsize|permsize|threadstacksize|metaspace' `
AllocatedDictが使用されていないのにメモリリークが発生していることを確認
jcmd $PID VM.native_memory などでメモリーの監視と検知
要は、内部の実装を詳しくしらべて怪しいところをしらみつぶしにした。
効果のあった対策
・autoReleaseを延長した3,4秒とか。https://docs.couchbase.com/java-sdk/2.6/client-settings.html
・singletonで、パーティションの数だけCouchbaseのcluster,bucketが存在していたのを修正
・微調整 poolBufferingEnabled=true と epoll関連。
効かなかった対策
・JVMの設定変更
・ metaspace size を増やす
・ -J-Xmx passing
・Couchbaseの設定変更のなかでも効果が見られなかった変更
・Couchbase libのbufferPoolEnabledを変更 https://developer.couchbase.com/documentation/server/3.x/developer/java-2.0/release-notes.html 怪しかったので。
・requestBufferSize https://developer.couchbase.com/documentation/server/3.x/developer/java-2.1/env-config.html
・nioが怪しんではないの!?nio の nettry, epoll らへんを調べる。。。
・非同期実装を同期に
・Async -> Sync
・Akka streamをつかって同期に。。。
・バグフリーと思われるバージョンでの試行
・だいぶカウチのlibを怪しんでいたので。couchbase.client:java-client 2.4.6 しかし、それはそれで互換性とかで苦労。断念。
調査
export OTHER_JAVA_OPTIONS="-XX:NativeMemoryTracking=summary"を追加して
jstat, jcmd, jmapなどで調査
結果
メモリーリークは解消されて安定稼働に漕ぎ着けた。
ライブラリのバグを設定でかわした。そんな気もしています。
考察
akkaのmax-connectionやlinger-timeoutの設定とその挙動でRST(tcp reset)が送られる訳
でも学んだことですが、大まかのアーキテクチャをイメージできているかどうか、
ブラックボックスをおおまかに理解しているかどうか、が重要です。これができていると、今の解法ではない
別の解法を思いつきやすいからです。
今回のメモリーリークは、蓋をしていない人がいる。それの人を探すゲームです。
自分の実装にあるのかもしれないし、ライブラリーのバグの可能性だってあります。それを
絞り込んでいく作業で、効率よく、重複作業(やり直し)なく、計画的に作業することが大切です。
あとしらみつぶしができる枠組みが欲しいです。MLでいうhyperparameter交差検証のような。
以上です