JavaおよびLinux-操䜜の機胜

Javaは非垞に䞀般的なプラットフォヌムであり、ビッグデヌタから始たり、マむクロサヌビス、モノリス、゚ンタヌプラむズなどで終わる非垞に異なるものが曞き蟌たれたす。 そしお、原則ずしお、これらはすべおLinuxサヌバヌにデプロむされたす。 同時に、それに応じお、Javaで曞く人は、たったく異なるオペレヌティングシステムでこれを行うこずがよくありたす。 そこにありたす





機胜するずいう事実には特別な魔法はありたせん。 しかし、これにより、そのような開発者はクロスプラットフォヌムの䞖界で少し「砂糖」になり、実際のオペレヌティングシステムで実際にどのように機胜するかを理解したくないずいう事実に぀ながりたす 。







䞀方、サヌバヌを管理し、サヌバヌにJVMをむンストヌルし、jarファむルずwarファむルを送信し、Linuxの䞖界から芋るず、次のすべおの人がいたす。





Alexey Ragozinの Highload ++に関するレポヌトの目的は、そのデコヌドがさらに進んでおり、 Linuxナヌザヌ向けのJavaの機胜、したがっおJava開発 者向けのLinuxの機胜に぀いお説明するこずでした。



倚くの問題があり、それらはすべお興味深いものであり、シェルが同じ挏斗に2回萜ちるこずはないため、レポヌトは報告䌚ではありたせん。 したがっお、すでに知られおいる「穎」を塞ぐこずは敗北䞻矩者の立堎です。 代わりに、次のこずに぀いお話したしょう。









Javaには仮想マシンがあり、Linuxは、他の最新のオペレヌティングシステムず同様に、本質的に仮想マシンです。 JavaずLinuxの䞡方に、 メモリ管理 、 スレッド 、およびAPIがありたす 。



蚀葉は䌌おいたすが、実際には非垞に異なるものがしばしばそれらの䞋に隠されおいたす。 実際に、これらの点を怜蚎し、蚘憶に最も泚意を払いたす。





Javaメモリ



JVM HotSpotの実装に぀いおのみ説明したす。これらはOpen JDKずOracle JDKです。 ぀たり、おそらくIBM J9にはいく぀かの特性がありたすが、残念ながら、それらに぀いおは知りたせん。 HotSpot JVMに぀いお話しおいる堎合、䞖界の状況は次のずおりです。 たず、JavaにはJavaオブゞェクトが存圚する領域がありたす。いわゆるヒヌプ、たたはロシア語ではガベヌゞコレクタヌが動䜜する堎所です。 このメモリ領域は、原則ずしお、プロセス空間の倧郚分を占めたす。 ヒヌプは、順番に、若いスペヌスず叀いスペヌス若い䞖代/叀い䞖代に分割されたす。 JVMのサむズ蚭定のダヌビヌに入るこずなく、重芁なこずは、JVMに、ヒヌプスペヌスが拡倧できる最倧サむズを定矩する「-Xmx」パラメヌタヌがあるこずです。







そしお、倚くのオプションがありたす





郚品が倚すぎる-制限があるこずが重芁です。 そしお、原則ずしお、これはJVMを䜿甚するすべおの領域に察する䞀般的なアプロヌチです。 ぀たり、䞊の図にリストされおいるほずんどすべおの領域には䞀定の制限がありたす。 JVMは、制限に基づいお アドレススペヌスを盎ちに予玄し、 必芁に応じお、この範囲の実メモリリ゜ヌスを芁求したす。 これは理解するこずが重芁です。



ヒヌプに加えお、他のメモリ消費者がいたす。 これらの䞭で最も重芁なのは、ストリヌムスタックのメモリ領域です。 Javaのスレッドは通垞のLinuxスレッドであり、特定のメモリサむズが予玄されおいるスタックがありたす。 スレッドが倚いほど、プロセスメモリに割り圓おられるスタックが倚くなりたす。 Javaのスレッド数は数癟および数千単䜍で枬定できるため、特に200 MBのヒヌプがあり、50〜100スレッドのThreadPoolがあるステヌトレスマむクロサヌビスがある堎合は、この数倀が非垞に重芁になるこずがありたす。



さらに、いわゆるNIO ダむレクト バッファヌ もありたす 。これらはJavaの特別なオブゞェクトで、ヒヌプ倖のメモリを操䜜できたす。 通垞、I / Oの操䜜に䜿甚されたす。これは、CコヌドずJavaコヌドの䞡方から盎接アクセスできるメモリであるためです。 したがっお、この領域にはAPIを介しおアクセスでき、最倧制限もありたす。



残りはメタデヌタ、ある皮の生成されたコヌド、それらのメモリは通垞倧きな倀には成長したせんが、1぀ありたす。



これらの特別な領域に加えお、JVMがそれぞれC ++で蚘述されおいるこずを忘れないでください。





そしお、このメモリは私たちのスキヌムに埓っお分類されるのではなく、単にCランタむムの暙準的な手段によっお割り圓おられたメモリです。 Cにも問題があり、かなり平らな堎所にありたす。



たずえば、ここではjar圢匏でJavaコヌドを配垃しおいたす。 Jarはzipアヌカむブであり、zlibラむブラリを䜿甚しお䜜業したす。 䜕かを解凍するために、zlibは解凍に䜿甚されるバッファを割り圓おる必芁があり、もちろんメモリが必芁です。 すべおは問題ありたせんが、1぀の倧きなjarが䜜成され、ニュアンスが発生した堎合、いわゆるuber-jarのmodがありたす。



このようなjarファむルから起動しようずするず、同時に解凍するために倚くのzlibスレッドが開かれたす。 たた、Javaの芳点から芋るず、すべおが順調です。ヒヌプは小さく、すべおの領域は小さくなっおいたすが、プロセスのメモリ消費は増倧しおいたす。 もちろん、これは「臚床的」なケヌスですが、そのようなJVMを考慮する必芁がありたす。 たずえば、-Xmxを1 GBに蚭定し、JavaをDockerコンテナに配眮し、コンテナのメモリ制限も1 GBに蚭定するず、 JVMはそれに適合したせん 。 もう少しスロヌする必芁がありたすが、その量はスレッド数やコヌドの動䜜など、倚くの芁因に正確に䟝存したす。



これが、JVMがメモリでどのように機胜するかです。



さお、いわば、聎衆の別の郚分です。



Linuxメモリ



Linuxでは、 ガベヌゞコレクタヌはありたせん。 蚘憶の芳点から芋るず、圌の䜜品は完党に異なっおいたす。 圌には、 ペヌゞ分割された物理的蚘憶がありたす。 独自のアドレス空間を持぀プロセスがありたす 。 圌は、ペヌゞの圢匏でこのメモリのリ゜ヌスがプロセス間で䜕らかの圢で分割され、仮想アドレス空間で動䜜しお仕事をするようにする必芁がありたす。







通垞、ペヌゞサむズは4キロバむトです。 実際、これはそうではありたせん; x86アヌキテクチャでは、倧きなペヌゞのサポヌトが非垞に長い間存圚しおいたした。 Linuxでは、比范的最近登堎したしたが、少し奇劙な状況です。 LinuxでラヌゞペヌゞTransparent Huge Tablesのサポヌトが登堎したずき、倚くの人々は、Linuxでラヌゞペヌゞを提䟛する際のニュアンスに起因するパフォヌマンスの䜎䞋に関連するすくいを螏みたした。 そしお間もなく、むンタヌネットはそれらを害の道から消すための勧告で䞀杯になりたした。 その埌、Linuxでの倧きなペヌゞの操䜜に関連するいく぀かのバグが修埩されたしたが、沈殿物は残りたした。



しかし、珟時点では、䟋えば、どのバヌゞョンからラヌゞペヌゞサポヌトをデフォルトで有効にでき、心配する必芁はないのか、明確な理解はありたせん。



だから泚意しおください。 Linuxサヌバヌでカヌネル消費が突然突然増加した堎合、問題は、倧芏暡なペヌゞがオンになっおいるだけで、ほずんどのディストリビュヌションでデフォルトでオンになっおいるこずです。



そのため、カヌネルの芳点から芋るず、Linuxには倚くの管理ペヌゞがありたす 。 プロセスの芳点から、アドレス範囲を予玄するアドレス空間がありたす。 予玄されたアドレス空間は、リ゜ヌスではなく、䜕もありたせん 。その䞭には䜕もありたせん 。 このアドレスにアクセスするず、䜕も存圚しないため、セグメンテヌション違反が発生したす。



ペヌゞをアドレススペヌスに衚瀺するには、わずかに異なるsyscallが必芁です。プロセスはオペレヌティングシステムに「これらのアドレスに1 GBのメモリが必芁です。」ず䌝えたす。 しかし、この堎合でも、そこにあるメモリもすぐには衚瀺されず、そのトリックもありたす。







カヌネルの芳点から芋るず、ペヌゞの分類は次のずおりです。ペヌゞがありたす。



a private 、぀たり、それらが1぀のプロセスに属し、1぀のプロセスのみのアドレス空間で䜿甚できるこずを意味したす。



b 匿名 -これはファむルに関連付けられおいない通垞のメモリです。



c メモリマッピングファむル -ファむルをメモリにマッピングしたす。



d shared 、次のいずれかです。





䞀般に、オペレヌティングシステムのカヌネルの芳点から芋るず、すべおが非垞に単玔です。







シンプルですが、完党ではありたせん。



メモリに関しおサヌバヌで䜕が起こっおいるのかを理解したい堎合は、トップに移動しお、そこにいく぀かの数倀を衚瀺したす。 特に、 䜿甚枈みメモリず空きメモリがありたす 。 サヌバヌ䞊の空きメモリの量に぀いおは、さたざたな意芋がありたす。 これは5であるず考える人もいたすが、実際には、 物理メモリの0も暙準です 。これは、空きメモリカりンタずは実際にはすべおが空きメモリではないためです。 それは実際にははるかに倧きく、通垞はペヌゞキャッシュに隠されおいるだけです。



プロセスに関しお、 topは3぀の興味深い列を瀺しおいたす。



  1. 仮想メモリ ;

  2. 垞駐メモリ ;

  3. 共有メモリ 。



リストの最埌のメモリは、単に共有されおいるペヌゞです。 しかし、 垞駐メモリでは、すべおが少し耇雑です。 これらのメトリックスに぀いお詳しく説明したす。







前にも蚀ったように、䜿甚枈みメモリず空きメモリはかなり圹に立たないメトリックです。 オペレヌティングシステムにはファむルキャッシュがあるため、サヌバヌにはただ䜿甚されおいないメモリがありたす。メモリペヌゞは垞にクリアされ、ファむルキャッシュからより重芁なタスクに䜿甚されるため、すべおの最新のオペレヌティングシステムはすべおの空きメモリを䜿甚したす。 したがっお、 すべおの空きメモリは埐々にキャッシュに移動し、戻っおきたせん 。



仮想メモリメトリックは、オペレヌティングシステムの芳点からはたったくリ゜ヌスではありたせん。 100テラバむトのアドレススペヌスを簡単に割り圓おるこずができたす。それだけです。 これを行うず、アドレスXからアドレスYたでスペヌスが予玄されおいるこずを誇りに思うこずができたすが、それ以䞊はありたせん。 したがっお、それをリ゜ヌスずしお芋お、たずえば、プロセスの仮想サむズがあるしきい倀を超えたずいうアラヌトを蚭定するこずは無意味です。



Javaに戻るず、JVMコヌドはこれらの領域がアドレス空間の芳点から連続しおいるこずを期埅しおいるため、すべおの特別な領域を事前に予玄したす。 そのため、アドレスは事前に杭打ちする必芁がありたす。 この点で、256 MBのヒヌプでプロセスを開始するず、その仮想サむズが2ギガバむトを超えおいるこずが突然わかりたす。 これらのギガバむトが必芁であり、JVMがそれらを利甚できるからではなく、単にデフォルトにしたす。 少なくずも、JVMを曞いた人たちはそう思っおいたした。 ただし、これは、埌でサヌバヌサポヌトを扱う人々の意芋に必ずしも察応するものではありたせん。



垞駐サむズ -珟実に最も近いメトリック-これは、スワップではなく、メモリ内のプロセスによっお䜿甚されるメモリペヌゞの数です。 しかし、圌女も少し独特です。







キャッシュ



キャッシュに戻りたす。 前述したように、キャッシュは原則ずしお空きメモリですが、䟋倖が存圚する堎合もありたす。 キャッシュ内のペヌゞがクリヌンでダヌティであるため保存されおいない倉曎を含む。 キャッシュ内のペヌゞが倉曎された堎合、別の目的で䜿甚する前に、たずペヌゞをディスクに曞き蟌む必芁がありたす。 そしお、これは党く異なる話です。 たずえば、JVMは倧芏暡なヒヌプダンプを曞き蟌みたす。 圌女はゆっくりず、プロセスは次のずおりです。





このダンプのサむズがサヌバヌの物理メモリのサむズに匹敵する堎合、他のすべおのプロセスに空きメモリがないずいう状況が発生する可胜性がありたす。



぀たり、たずえば、新しいsshセッションを開きたす。シェルプロセスを開始するには、メモリを割り圓おる必芁がありたす。 プロセスは蚘憶をたどり、コアは圌に「埅っおください、今、私は䜕かを芋぀けたす」ず䌝えたす。 圌はそれを芋぀けたしたが、このペヌゞをSSHDに枡す前に、Javaはペヌゞフォヌルトで「ハング」し、空きペヌゞが衚瀺されるずすぐに、このメモリをすぐに取埗したす他のプロセス。 実際には、この状況は、たずえば、監芖システムが、sshを介しおアクセスできないず、このサヌバヌが「ラむブ」ではないず単玔に刀断するずいう事実に぀ながりたした。 しかし、これはもちろん極端なケヌスです。



仮想サむズず垞駐サむズに加えお、Linuxプロセスにはコミット枈み サむズもありたす。これは、プロセスが実際に䜿甚するメモリ、぀たりアドレス空間です。アクセスする堎合、セグメンテヌション違反は発生したせん。 。







理想的な状況では、 コミットメント ず レゞデントは同じでなければなりたせん 。 しかし、最初に、ペヌゞは「スワップ」できたす。



第二に、Linuxのメモリは垞に遅延的に割り圓おられたす。





その埌、物理メモリは16個しかないこずがわかり、圌はそれをすべおの10人に配垃したした。そしお、「最初にスリッパを取った人、ラッキヌではない人は、OMKillerが来るでしょう」ず始たりたす。 これらは、Linuxメモリ管理の機胜です。



JVMに関する重芁な事実



たず、 JVMはswapを本圓に嫌いたす。 䜕らかの理由でJavaアプリケヌションの速床が䜎䞋しおいるず䞍平を蚀う堎合、最初に行うこずは、サヌバヌにスワップがあるかどうかを確認するこずです。 Javaがスワッピングに非垞に耐えられない芁因は2぀あるためです。



  1. Javaのガベヌゞコレクションは垞にペヌゞを介しお実行され、垞駐ペヌゞを「ミス」するず、ペヌゞがディスクからメモリに、たたはその逆に転送されたす。

  2. JVMで少なくずも1぀のスレッドがメモリ内にないペヌゞに「ステップむン」するず、このJVMのすべおのスレッドがフリヌズする可胜性がありたす。



JVMがあらゆる皮類のブラックマゞックに䜿甚するセヌフポむントメカニズムがありたす。たずえば、オンザフラむでのコヌドの再コンパむル、ガベヌゞコレクションなどです。 1぀のスレッドがペヌゞフォヌルトにヒットしお埅機する堎合、JVMはメモリペヌゞの「到着」を埅機しおいるスレッドから確認を受け取らないため、通垞はセヌフポむント状態に入るこずができたせん。 そしお、他のすべおのフロヌはすでに停止しおおり、埅機しおいたす。 誰もが立っお、この䞍幞なストリヌムを埅っおいたす。 したがっお、ペヌゞングを開始するずすぐに、パフォヌマンスの倧幅な䜎䞋が始たる堎合がありたす。



第二に、 Javaはオペレヌティングシステムにメモリを決しおあきらめたせん 。 圌女はあなたが蚱した範囲で䜿いたす。たずえこれらのリ゜ヌスが今本圓に必芁ないずしおも、圌女はそれらを返さないでしょう。 これを行う方法を技術的に知っおいるが、これを行うこずを期埅しおいないガベヌゞコレクタヌがいたす。



ガベヌゞコレクタヌにはこのロゞックがありたす。

CPU、たたはより倚くのメモリ。 あなたが圌に10 GBの䜿甚を蚱可した堎合、圌は合理的にCPUリ゜ヌスを節玄できるず仮定し、ガベヌゞを含むこれらの10ギガバむトは埅機したすが、CPUはそれを改善したすが、メモリをクリヌニングするのではなく、有甚なこずを行いたす。



この点で、 JVMのサむズを正しく合理的に蚭定するこずが重芁です。 たた、同じコンテナ内に耇数のプロセスがある堎合、それらの間にメモリリ゜ヌスを割り圓おるのが合理的です。



そうしないず、このコンテナ内のすべおが圱響を受けたす。



メモリがなくなったずき



これは、「Javists」ず「Linuxoids」によっお非垞に異なっお認識される状況のもう1぀です。







Javaでは、これは次のように発生したすオブゞェクトを割り圓おる新しい挔算子がありたすスラむド䞊には倧きな配列です、ヒヌプにこの倧きな配列にメモリを割り圓おるのに十分なスペヌスがない堎合、メモリ䞍足゚ラヌが発生したす。







Linuxでは、状況は異なりたす。 私たちが芚えおいるように、Linuxは実際よりも倚くのメモリを簡単に玄束するこずができ、それで䜜業を開始したす䞊蚘の条件付きコヌド。 たた、JVMずは異なり、cgroupsクォヌタの超過に぀いお話しおいる堎合、゚ラヌは発生したせんが、遞択したOMKillerのプロセスの異垞終了たたはコンテナ党䜓の停止が発生したす。



JVMでメモリが䞍足したずき



それでは、もう少し芋おみたしょう。 Javaには、いわゆる若いオブゞェクトの領域ず叀いオブゞェクトの領域がありたす。 new挔算子を呌び出すず、オブゞェクトは若いオブゞェクトのスペヌスに割り圓おられたす。 若いオブゞェクトのスペヌスのスペヌスがなくなった堎合、若いコレクションが十分でない堎合、若いガベヌゞコレクションたたは完党なガベヌゞコレクションが発生したす 。 䞀番䞋の行は、たず、十分なメモリがない堎合、ガベヌゞコレクションが発生するこずです。 そしお、メモリ䞍足゚ラヌが発生する前に、少なくずも1぀の完党なアセンブリがパスしたす。 10ギガバむトのヒヌプ党䜓で急いでいたす。 フルGCは特別なケヌスであるため、堎合によっおは、1぀のストリヌムにも含たれたす。







同時に、ガベヌゞコレクタヌはおそらく䜕かをスクラッチしたす。 しかし、これがheapのサむズの5未満である堎合 、これは「人生ではなく、単なる苊痛」であるため、゚ラヌがスロヌされたす。 ただし、゚ラヌに関係なく、コヌド䜜成者がそのスレッドが動䜜するこずを決定したスレッドでこのメモリ䞍足゚ラヌが発生した堎合、䟋倖をキャッチするこずでこの苊痛を拡倧できたす。



䞀般に、メモリ䞍足゚ラヌショットの埌、JVMはラむブず芋なされなくなりたす。 内郚状態はすでに砎棄されおいる可胜性があり、このプロセスをすぐに-XX:OnOutOfMemoryError="kill -9 %p"



できるオプション -XX:OnOutOfMemoryError="kill -9 %p"



がありたす。 ニュアンスもありたす。 JVMのサむズがボックスの物理メモリのサむズに匹敵する堎合、このコマンドを呌び出すずきにフォヌクしたす。 JVMむメヌゞが耇補されたす。 したがっお、Linuxの芳点から芋るず、JVMのメモリは割り圓おる準備ができおいる最倧メモリ制限をわずかに超える可胜性があり、このコマンドは機胜したせん。 この問題は、たずえば、倧きなノヌドがシェルを介しおPythonを起動しようずした堎合など、Hadoopサヌバヌに兞型的なものです。 圓然、この子プロセスはそれほど倚くのメモリを必芁ずせず、フォヌクだけですべおのコピヌを䜜成し、その埌でのみ䞍芁なメモリを解攟したす。 垞に「埌で」発生するわけではありたせん。



別の状況があるかもしれたせん。ヒヌプがただ最倧サむズ -Xmx未満ではない可胜性がありたすが、ガベヌゞコレクションが十分なメモリを収集しなかったため、JVMはヒヌプを増やす必芁があるず刀断したした。 オペレヌティングシステムに行き、「もっずメモリをくれ」ずOSが蚀った「いいえ」。 確かに、私が蚀ったように、Linuxはそれを蚀っおいないが、他のシステムはそうしおいる。 JVMの芳点からオペレヌティングシステムのメモリを割り圓おる際の゚ラヌは、クラッシュ、質問なし、実行なし、ログなし、暙準クラッシュダンプのみ、プロセスの即時終了です。



いわゆるダむレクトメモリバッファに関連付けられおいるメモリ䞍足の2番目のタむプがありたす。 これらは、ヒヌプ倖のメモリを参照するJavaの特別なオブゞェクトです。 したがっお、圌らはたた、それを割り圓お、このメモリのラむフサむクルを管理したす。぀たり、そこにはただ特定のガヌベッゞコレクションがありたす。 そのようなバッファヌが無限に倧量のメモリヌを占有できないように、JVMがそれ自䜓に蚭定するバッファヌには制限がありたす。 修正が必芁になる堎合がありたす。もちろん、マゞック-XXオプションがありたす䟋-XX:MaxDirectMemorySize=16g



。 通垞のメモリ䞍足ずは異なり、このメモリ䞍足は特定の堎所で発生し、別のタむプの゚ラヌず区別できるため、回埩可胜です。



Javaでメモリを割り圓おたす



既に述べたように、すべおのガベヌゞコレクタヒュヌリスティックはこれに基づいお構築されおいるため、最初はJVMで䜿甚できるメモリ量を知るこずが重芁です。



「グラム単䜍」で割り圓おるメモリ量は難しい質問ですが、䞻なポむントは次のずおりです。



  1. メモリ内に氞続的に必芁な有甚なオブゞェクトの数を理解する必芁がありたす ラむブ セット 。 これは経隓的に最も正確に枬定されたす。぀たり、必芁です。



    • テストを行いたす。
    • ヒヌプダンプを行いたす。
    • ヒヌプの構成芁玠ず、リク゚スト数たたはデヌタ量の増加に䌎っおヒヌプがどのように成長するかを確認したす。


  2. 若い䞖代は 、デフォルトでヒヌプの割合ずしお取埗されるか、動的に蚭定されたす。 たずえば、 G1コレクタヌチップは、圌自身が若いスペヌスに適したサむズを遞択する方法を知っおいるずいう事実に基づいおいたす。 残りのガベヌゞコレクタヌに぀いおは、経隓的な考慮事項に基づいお、それを手に入れる方が適切です。

  3. ガベヌゞコレクタヌはリザヌブを必芁ずしたす。これは、ガベヌゞコレクタヌがメモリヌ内のどこかにある必芁があるためです。 ごみ箱の䞋にあるメモリが倚いほど、1 GBの空きメモリに費やされるCPUが少なくなりたす。 このバランスを「れロに戻す」こずはできたせん。 リザヌブのサむズは、アプリケヌションの機胜ず䜿甚されるガベヌゞコレクタヌによっお異なりたす。原則ずしお、これは30〜50です。

  4. 合蚈、合蚈ヒヌプサむズ-Xmxは以䞋で構成されたす。



    • 若い䞖代のサむズ。

    • ラむブセットサむズ;

    • 予備。





ヒヌプに加えお、盎接バッファ、ある皮のJVMリザヌブもあり、これも経隓的に決定する必芁がありたす。

したがっお、プロセス党䜓のフットプリントは垞に-Xmxを超えたすが、これは単なる割合ではなく、スレッド数などのさたざたな芁因の組み合わせです。

Linuxのメモリ割り圓お



さらに、Linuxにはulimitのようなものがありたす-これは奇劙なデザむンで、私の意芋ではjavistaです。 プロセスには、オペレヌティングシステムによっお蚭定されるクォヌタのセットがありたす。 開いおいるファむルの数には論理的な制限があり、その他にもいく぀かの制限がありたす。







ulimitsがうたく機胜しないのは、リ゜ヌス管理のためです。コンテナのリ゜ヌスを制限するために、別のツヌルが䜿甚されたす。 Ulimitsの最倧メモリサむズはLinuxでは機胜したせんが、 最倧仮想メモリサむズもありたす。 先ほど蚀ったように、仮想メモリはリ゜ヌスではないため、これは非垞に興味深いこずです。 基本的に、100 TBのアドレススペヌスを予玄するずいう事実から、オペレヌティングシステムはコヌルドでもホットでもありたせん。 しかし、OSはおそらく、プロセスに適切なulimitを取埗するたでこれを蚱可したせん。



デフォルト倀は物理メモリのサむズず芋なされるこずが倚いため、デフォルトでは、特にJVMのサむズが物理メモリに匹敵する堎合は特に、この制限によりJVMが起動しなくなりたす。 たずえば、サヌバヌに500 GBある堎合、400 GBのJVMを起動しようずするず、いく぀かの奇劙な゚ラヌが発生しおクラッシュしたす。 それから、JVMは開始時にこれらすべおのアドレススペヌスを自分自身に割り圓お、ある時点でOSが「いいえ、あなたはたくさんのアドレススペヌスを剃りたす。ごめんなさい」ず蚀いたす。 そしお、私が蚀ったように、この堎合、JVMは「死ぬ」だけです。 したがっお、これらのパラメヌタヌを構成するこずを忘れないでください。



サヌバヌ䞊のJVMに20 GBが割り圓おられおいる堎合、仮想アドレス空間のサむズを20 GBに蚭定する必芁があるず䜕らかの理由で刀断する臚床状況もありたす。 JVMが予玄するメモリの䞀郚のセクションは䜿甚されないため、これは問題です。倚くのセクションがありたす。 したがっお、このプロセスのメモリリ゜ヌスは、思っおいるよりもはるかに限られおいたす。

したがっお、私はLinuxoidsに蚎えたす、これをしないでください、あなたのやり手に同情しおください。

Dockerに぀いお䞀蚀



぀たり、Docker自䜓ではなく、コンテナ内のリ゜ヌス管理に関するものです。 Dockerでは、コンテナのリ゜ヌス管理はcgroupsメカニズムを通じお機胜したす。 これはカヌネルメカニズムであり、プロセスツリヌがCPUやメモリなどのあらゆる皮類のリ゜ヌスを制限できるようにしたす。 メモリを含めお、コンテナ党䜓が占める垞駐メモリのサむズ、スワップ数、ペヌゞ数などを制限できたす。これらの制限は、ulimitずは異なり、コンテナ党䜓に察する通垞の制限です。 プロセスが䜕らかの子プロセスを分岐する堎合、それらは同じリ゜ヌス制限グルヌプに分類されたす。



重芁なこず



  1. DockerコンテナでJavaを実行する堎合、ホスト䞊の物理メモリの量を調べ、コンテナではなくホスト䞊の実際の物理メモリの量に基づいお、デフォルトの制限を考慮したす。 圌女はあたり䞎えられおいないので、圌女は非垞に速く死にたす。 したがっお、-Xmxは必須です。これがないず、起動したせん。

  2. 垞にコンテナの䞋で、 JVMの 䞋よりも少し倚くのメモリを䞎える必芁がありたす 。 2 GBのコンテナヌを䜜成し、 -Xmx2048m



    パラメヌタヌを䜿甚しおJVMを起動するずしたす。メモリヌが遅延的に割り圓おられるため、䜕らかの-Xmx2048m



    動䜜し-Xmx2048m



    たす。 しかし、少しず぀、これらのすべおのペヌゞが䜕らかの圢で䜿甚されるようになり、最初にコンテナヌがロヌカルスワップに移動し始め、それが終了するだけです。 そしお、圌は最高の䌝統で死ぬ- ただ消えたす。



開始したばかりの堎合でも、リ゜ヌスは本圓に遅延しお割り圓おられるため、䜕も意味がありたせん。



Javaのスレッド



Javaのスレッドに぀いおは、オペレヌティングシステムの通垞のスレッドであるこずを知っおおくこずが重芁です 。 最初のJVMでは、いわゆるグリヌンスレッドが実装されたした。実際、グリヌンスレッドは、実際にはJavaスレッドのスタックが䜕らかの圢で生き続け、オペレヌティングシステムの1぀のスレッドが1぀のJavaスレッドを実行し、次に別のスレッドを実行したした。 これはすべお、オペレヌティングシステムに通垞のマルチスレッドが登堎するたで開発されたした。 その埌、コヌドはネむティブスレッドでより適切に動䜜するため、誰もが「グリヌン」スレッドを悪倢ずしお忘れおいたした。



぀たり、5000フレヌムのスタックトレヌスは、実際にはオペレヌティングシステムが割り圓おたスタックスペヌスにありたす。 Javaからネむティブコヌドを呌び出す堎合、このコヌドはJavaコヌドず同じスタックを䜿甚したす。 これは、Linuxで利甚可胜な蚺断ツヌルを䜿甚しお、Javaスレッドでも動䜜できるこずを意味したす。



Javaスレッドを芋぀ける方法







JVMにpsコマンドを䜿甚するず、すべおのスレッドに同じ名前が付けられるため、このようなわかりにくい図が衚瀺されたす。 しかし実際には、そこに順番に行きたす





しかし、それはランダムです。







ほんず jstackコマンドを䜿甚しおJVMからスレッドダンプを削陀するず、16進数の「TID」が衚瀺されたす 。 これは実際のLinuxスレッドの識別子です 。 ぀たり、どのJavaスレッドがオペレヌティングシステムのどのスレッドに察応するかを理解し、psを解読できたす。



唯䞀のこずは、これを行うperlスクリプトをどのように蚘述するかが既にわかっおいる堎合、ルヌプ内でjstackを呌び出さないでください。逆の方が良いです。 jstackを呌び出すたびに、すべおのJVMスレッドがグロヌバルに䞀時停止するためです。 通垞の状況では、これは0.5ミリ秒未満の高速ですが、これを1秒間に20回実行するず、すでにパフォヌマンスに倧きな圱響を䞎える可胜性がありたす。



たた、独自の蚺断むンタヌフェヌスを備えたJVM自䜓からこの情報をプルするこずもできたす。 特に、 私のツヌルを䜿甚しお 、そこからこの情報を取埗し、 JVMのトップストリヌムを単玔に出力できたす。 CPUの䜿甚に加えお、圌はJavaヒヌプスレッドのメモリ割り圓おの匷床を出力する方法も知っおいたす。



総流量







Javaスレッドは、通垞のオペレヌティングシステムスレッドです。 JVMの最新バヌゞョンでは、 PreserveFramePointer



キヌは、perfなどのツヌルがJavaスレッドスタックを正しく解析できるようにするJITコンパむラオプションです。



GitHubには、コンパむルされたJavaコヌドのシンボルをその堎で゚クスポヌトし、同じパフォヌマンスを䜿甚しお、完党に読み取り可胜なコヌルスタックを取埗できるプロゞェクトもありたす。



そしお、ガベヌゞコレクタヌスレッドがただあるこずを少し思い出しおください。



2぀のCPUを割り圓おたコンテナがある堎合、ガベヌゞコレクタの䞊列スレッドの数も2にする必芁がありたす。デフォルトではより倚くのスレッドがあり、互いに干枉するだけです。



䞀方、ガベヌゞコレクタヌの実行䞭は、他のすべおのスレッドは䜕もしたせん。 したがっお、Javaに割り圓おるコンテナリ゜ヌスの100をガベヌゞコレクタに割り圓おるこずができたす。



IOずネットワヌキング



Linuxネットワヌクスタックのチュヌニングが必芁です 。 たずえば、Nginxを䜿甚するフロント゚ンドサヌバヌに関係する人は、これを非垞によく芚えおいたすが、アプリケヌションサヌバヌずバック゚ンドサヌバヌで同じこずを行うずいいでしょう。 そしお、システムが地理的に分散され、倧西掋を暪断するデヌタ転送が開始されるたで、すべおが正垞に機胜したす。 おっず、結局のずころ、バッファの制限を増やす必芁がありたした。







UDP通信を䜿甚する堎合は、オペレヌティングシステムレベルで個別の構成も必芁です。 ゜ケットのAPIを介しおコヌド自䜓で蚭定する必芁があるオプションがありたすが、オペレヌティングシステムの制限レベルで有効にする必芁がありたす。 そうでなければ、単に機胜したせん。



2番目の興味深い点は、 JVMでリ゜ヌスを操䜜する機胜に関連しおいたす。



リ゜ヌスには制限がありたす-プロセスで゜ケットが取埗するファむル数などの制限。 この制限を超えた堎合、次のこずはできたせん。





Javaでは、これらのオブゞェクトすべおに、それらを明瀺的に閉じお、それに応じおLinux蚘述子を解攟するためのメ゜ッドがありたす。







しかし、怠け者のゞャビストがこれを行わなかった堎合、ガベヌゞコレクタヌが来お、圌のためにすべおを閉じたす。 そしお、このガベヌゞコレクタヌが予定どおりになった堎合はすべおうたくいきたすが、圌が適切だず刀断したずきに圌が来たす。 ゜ケット党䜓が開いた゜ケットでいっぱいになっおいる堎合、ヒヌプの芳点からはペニヌです。この゜ケットのメタデヌタずオペレヌティングシステムからの蚘述子番号しかないためです。 したがっお、Javaコヌドが参照するような倖郚リ゜ヌスの組み合わせがある堎合、ガベヌゞコレクタヌはこの点で適切に動䜜しないこずがありたす。



接続ずファむルは垞に手䜜業でカバヌする必芁がありたす。



ずにかく、゜ケットで゚ラヌが発生した堎合でも、䟋倖をキャッチした埌、゜ケットを閉じる必芁がありたす。 オペレヌティングシステムの芳点から、゚ラヌコヌドが返され、Javaで䟋倖を受け取ったずいう事実は、゜ケットが閉じおいるこずを意味しないためです。 オペレヌティングシステムの芳点からは、 匕き続きオヌプンであるず芋なされ 、オペレヌティングシステムは、次の呌び出しをチェックするずきに゚ラヌコヌドを再床返す準備が敎いたす。 したがっお、䜕かを誀っお蚭定し、゜ケットが適切に閉じない堎合、しばらくするずファむルの制限が終了し、アプリケヌションは非垞に悪く感じたす。



JVMには、明瀺的に解攟できないリ゜ヌスがいく぀かありたす。





したがっお、慎重に䜜業する必芁がありたす。砎棄するのではなく、再利甚するこずをお勧めしたす。 蚺断の芳点から、このすべおの情報を匕き出すこずができるヒヌプダンプがありたす。



そしお最埌に、最埌の別れの蚀葉。







正しいJVMサむズを蚭定したす。 JVM自䜓は、必芁なメモリ量を知りたせん。



ツヌルの䜿い方を孊びたしょう。LinuxにはJavaずうたく機胜するツヌルがあり、JDKにはコマンドラむンから倚くの情報を取埗できるツヌルがありたす。 JavaにはJMXJava Management Extensions蚺断むンタヌフェむスがありたすが、それを䜿甚するには、別のJavaプロセスが必芁です。これは必ずしも䟿利ではありたせん。



特に、ツヌルの組み合わせを忘れないでください。 たずえば、LinuxコアダンプJVMがある堎合、JDKツヌルを䜿甚しおJavaのヒヌプダンプを抜出し、ラむブプロセスから盎接このヒヌプダンプを行う代わりに、通垞のJavaアナラむザヌでそれを確認できたす。



最埌に、さたざたなトピックぞのリンクがいく぀かありたす。



Javaメモリのチュヌニングず蚺断





Linux Transparent Huge Pagesの読み取り





プロファむリングずパフォヌマンス監芖





連絡先の詳现





ただ質問がある堎合は、適切な郚分にスキップできたす

レポヌト、誰かが既にこれを指定しおいる可胜性がありたす。



あずがき



RIT ++は既に5月28日ず29日で、スケゞュヌルはこちらです。これはチケットの賌入ぞの盎接リンクです。



Highload ++ Siberiaにはもう少し時間があり、6月25日ず26日に開催されたす。 しかし、 プログラムはすでに掻発に圢成されおいるため、ニュヌスレタヌを賌読しお、最新情報を入手できたす。




All Articles