CentOS 5.4(Linuxカーネル2.6.16.33-xenU)で実行されているVPS Webサーバーが不定期に(月に1度、数週間かかるなど)、oom-killerが起動するために応答しなくなります。サーバーを監視すると、通常は、メモリ不足が頻繁に発生します。
以下のsysctl設定を使用してオーバーコミットをより適切に管理するためのカーネルの構成について説明している このページ を参照するいくつかのブログを読みました。
vm.overcommit_memory = 2
vm.overcommit_ratio = 80
これについての私の理解(これは間違っているかもしれませんが、明確な定義を見つけることができません)は、これにより、カーネルがスワップ+ 80%の物理メモリを超えてメモリを過剰に割り当てるのを防ぐことができます。
しかし、私は some 他のソースも読んだので、これらの設定は良い考えではないことを示唆しています。ただし、このアプローチの批評家は、「システムを壊すようなことはしないでください。因果関係は常に知られているという前提で、このクラッジ」。
だから私の質問は、このアプローチの長所と短所は何ですか、約10の低トラフィックサイトをホストしているApache2 Webサーバーのコンテキストでは?私の場合、Webサーバーには512MbのRAMがあり、1024Mbのスワップスペースがあります。ほとんどの場合、これで十分です。
設定overcommit_ratio
から80は、おそらく正しいアクションではありません。値を100未満に設定すると、ほとんどの場合正しくありません。
これは、Linuxアプリケーションが実際に必要とする以上の割り当てを行うためです。たとえば、2文字のテキスト文字列を格納するために8kbを割り当てるとします。まあそこに数KB未使用です。アプリケーションはこれを頻繁に行い、これがオーバーコミットの目的です。
したがって、基本的に100のオーバーコミットでは、カーネルはアプリケーションがあなたが持っている以上のメモリを割り当てることを許可しません(スワップ+ ram)。 100未満に設定すると、メモリをすべて使用することはありません。この設定を設定する場合は、前述のシナリオが一般的であるため、100より大きく設定する必要があります。
さて、OOMキラートリガーの問題については、手動でオーバーコミットを設定しても、これはおそらく修正されません。デフォルト設定(ヒューリスティック決定)はかなりインテリジェントです。
これが本当に問題の原因であるかどうかを確認したい場合は、/proc/meminfo
OOMキラーの実行時。あなたがそれを見た場合Committed_AS
はCommitLimit
に近いですが、free
はまだ利用可能な空きメモリを表示しているので、シナリオのオーバーコミットを手動で調整できます。この値の設定が低すぎると、メモリに十分な空きがあるときにOOMキラーがアプリケーションを強制終了します。設定が高すぎると、割り当てられたメモリを使用しようとしたときにランダムなアプリケーションが停止する可能性がありますが、実際には使用できません(実際にすべてのメモリが使い果たされた場合)。
@dunxdが言及しているドキュメントのセクション9.6「オーバーコミットとOOM」は、オーバーコミットを許可することの危険性について特に図解されています。ただし、_80
_も私にとって興味深いように見えたため、いくつかのテストを行いました。
私が見つけたのは、_overcommit_ratio
_がすべてのプロセスで使用できる合計RAMに影響することです。ルートプロセスは、通常のユーザープロセスとは異なる方法で処理されているようには見えません。
比率を_100
_以下に設定すると、_malloc/sbrk
_からの戻り値が信頼できる従来のセマンティクスが提供されます。比率を_100
_よりも低く設定すると、キャッシングなどの非プロセスアクティビティ用に、より多くのRAMを予約できるようになる場合があります。
したがって、24 GiBのRAMがあり、スワップが無効になっている私のコンピューターでは、9 GiBが使用されており、top
が表示されています
_Mem: 24683652k total, 9207532k used, 15476120k free, 19668k buffers
Swap: 0k total, 0k used, 0k free, 241804k cached
_
ここに、いくつかの_overcommit_ratio
_設定と、どの程度RAM ram-consumerプログラムが(各ページをタッチして)取得できるかを示します。どちらの場合も、malloc
が失敗すると、プログラムは正常に終了しました。
_ 50 ~680 MiB
60 ~2900 MiB
70 ~5200 MiB
100 ~12000 MiB
_
いくつかをrootユーザーとして使用して一度にいくつかを実行しても、一緒に消費される合計量は変わりませんでした。興味深いのは、最後の3+ GiB程度を消費できなかったことです。 free
は、ここに示されているものを大きく下回りませんでした。
_Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
_
多くのプログラマーはCでmallocの失敗をチェックすることに恐ろしいため、すべてのRAMが使用されているときにmallocを使用するものはすべてクラッシュする傾向があり、一部の一般的なコレクションライブラリは完全に無視します。C++そして他の様々な言語はさらに悪いです。
想像上の初期の実装のほとんどRAMは、非常に特殊なケースを処理するためのものであり、単一の大きなプロセス(たとえば、使用可能なメモリの51%以上)がfork()
に必要であり、exec()
いくつかのサポートプログラム、通常ははるかに小さいプログラム。コピーオンライトセマンティクスを持つOSはfork()
を許可しますが、フォークされたプロセスが実際に多すぎるメモリページを変更しようとした場合(各ページは独立した新しいページとしてインスタンス化する必要があります)最初の巨大なプロセス)それは殺されてしまうでしょう。親プロセスは、より多くのメモリを割り当てた場合にのみ危険にさらされ、場合によっては、他のプロセスが終了するのを少し待ってから続行することで、メモリ不足を処理できます。子プロセスは通常、exec()
を介してそれ自体を(通常はより小さな)プログラムに置き換えただけで、但し書きはありませんでした。
Linuxのオーバーコミットの概念は、fork()
を発生させるだけでなく、単一のプロセスが大規模に全体を割り当てることを可能にする極端なアプローチです。 doが責任を持ってメモリ割り当てを処理するプログラムであっても、OOM-killerが原因の死は非同期に発生します。私は個人的にsystem-wideオーバーコミット、特にoom-killerを大嫌いです-それは、ライブラリに感染し、それらを使用するすべてのアプリを介して、メモリ管理に対する悪魔のようなケアのアプローチを促進します。
比率を100に設定し、スワップパーティションを用意することをお勧めします。これにより、通常、最終的に巨大なプロセスでのみ使用されるようになります。これは、スワップに詰め込まれる部分のごく一部しか使用しないことが多いため、プロセスの大部分をOOMのキラー機能から保護します。これにより、Webサーバーがランダムな死から安全に保護され、malloc
を責任を持って処理するように作成されている場合は、それ自体が強制終了されることもありません(ただし、後者には賭けないでください)。
つまり、これを_/etc/sysctl.d/10-no-overcommit.conf
_で使用しています
_vm.overcommit_memory = 2
vm.overcommit_ratio = 100
_