今日、HAProxy VM の 1 つでフェイルオーバーの小さな問題が発生しました。詳しく調べたところ、次のことがわかりました。
1月26日 07:41:45 haproxy2カーネル: [226818.070059] __ratelimit: 10コールバックが抑制されました 1月26日 07:41:45 haproxy2カーネル: [226818.070064] ソケットメモリ不足 1月26日 07:41:47 haproxy2カーネル: [226819.560048] ソケットメモリ不足 1月26日 07:41:49 haproxy2カーネル: [226822.030044] ソケットメモリ不足
それは、このリンクは、どうやら のデフォルト設定が低いことに関係しているようですnet.ipv4.tcp_mem
。そこで、デフォルトから 4 倍に増やしました (これは Ubuntu Server なので、Linux の種類が関係するかどうかはわかりません)。
現在の値は次のとおりです: 45984 61312 91968 新しい値は次のとおりです: 183936 245248 367872
その後、奇妙なエラー メッセージが表示されるようになりました。
1月26日 08:18:49 haproxy1 カーネル: [ 2291.579726] ルート ハッシュ チェーンが長すぎます。 1月26日 08:18:49 haproxy1 カーネル: [ 2291.579732] secret_interval を調整してください。
シーッ…それは秘密です!!
これは明らかに、/proc/sys/net/ipv4/route/secret_interval
デフォルトで600に設定され、ルートキャッシュの定期的なフラッシュ
secret_interval
これは、ルート ハッシュ エントリの新旧に関係なく、すべてのルート ハッシュ エントリを消去する頻度をカーネルに指示します。私たちの環境では、これは一般的に良くありません。キャッシュがクリアされるたびに、CPU は 1 秒あたり数千のエントリを再構築するのに忙しくなります。ただし、メモリ リークを防ぐために、これを 1 日に 1 回実行するように設定しています (メモリ リークは発生していませんが) 。
これを減らすことは喜ばしいことですが、定期的にルートキャッシュ全体を削除することをお勧めします。ルート キャッシュから古い値を単に高速にプッシュするのではなく、
調査の結果、/proc/sys/net/ipv4/route/gc_elasticity
ルート テーブルのサイズを抑えるには、次のオプションのほうが適していることがわかりました。
gc_elasticity
ルート ハッシュ エントリの期限切れを開始する前にカーネルが受け入れる平均バケット深度として最もよく説明できます。これにより、アクティブ ルートの上限を維持するのに役立ちます。
ルート キャッシュがより積極的にプルーニングされることを期待して、弾力性を 8 から 4 に調整しました。私たちにとっては、これはsecret_interval
正しいとは思えません。しかし、設定はたくさんあるので、どれが本当に正しい方法なのかは不明です。
- /proc/sys/net/ipv4/route/gc_elasticity (8)
- /proc/sys/net/ipv4/route/gc_interval (60)
- ルートの最小間隔 (0)
- ipv4 ルートのタイムアウト (300)
- ルートの秘密間隔 (600)
- ipv4 ルートディレクトリ
- rhash_entries (カーネルパラメータ、デフォルトは不明?)
Linuxのルーティングを悪いそのため、これらの設定のいくつかを変更するのはちょっと不安です。
トラフィック量の多い HAProxy インスタンスの場合、どのルーティング パラメータを調整するのが最適かアドバイスをいただけますか?
答え1
私はこの問題に遭遇したことがありません。ただし、深さを減らすにはハッシュ テーブルの幅を増やす必要があるでしょう。「dmesg」を使用すると、現在いくつのエントリがあるかがわかります。
$ dmesg | grep '^IP route'
IP route cache hash table entries: 32768 (order: 5, 131072 bytes)
この値はカーネル ブート コマンド ライン パラメータを使用して変更できますrhash_entries
。まず手動で試してから、 または に追加しlilo.conf
ますgrub.conf
。
例えば:kernel vmlinux rhash_entries=131072
HAProxy VM に割り当てられたメモリが少ないため、ハッシュ テーブルが非常に制限されている可能性があります (ルート ハッシュ サイズは RAM の合計に応じて調整されます)。
に関してはtcp_mem
、注意してください。初期設定から、1 GB の RAM で実行していて、その 1/3 を TCP ソケットに割り当てることができると思われます。現在、367872 * 4096 バイト = 1.5 GB の RAM が TCP ソケットに割り当てられています。メモリが不足しないように十分注意してください。経験則としては、メモリの 1/3 を HAProxy に割り当て、別の 1/3 を TCP スタックに割り当て、残りの 1/3 をシステムの残りの部分に割り当てることです。
「ソケット メモリ不足」メッセージは、およびのデフォルト設定から発生していると思われますtcp_rmem
。tcp_wmem
デフォルトでは、各ソケットの出力に 64 kB、入力に 87 kB が割り当てられています。つまり、プロキシ接続では、ソケット バッファのみで合計 300 kB になります。これに HAProxy の 16 または 32 kB を追加すると、1 GB の RAM では 3000 の接続しかサポートされないことがわかります。
tcp_rmem
と(中間パラメータ)のデフォルト設定を変更することでtcp_wmem
、メモリ使用量を大幅に削減できます。書き込みバッファの値を 4096 に、tcp_rmem
(5 または 11 の TCP セグメント) の値を 7300 または 16060 に下げると、良好な結果が得られます。これらの設定は再起動せずに変更できますが、新しい接続にのみ適用されます。
触りたくない場合はシステム最新の HAProxy 1.4-dev8 では、グローバル構成から、また側ごと (クライアントまたはサーバー) にこれらのパラメータを微調整できます。
これが役に立つことを願っています!
答え2
はOut of socket memory error
しばしば誤解を招く。ほとんどの場合、インターネットに面したサーバーでは、ないメモリ不足に関連する問題を示します。ブログ投稿、最も一般的な理由は、孤立ソケットの数です。孤立ソケットとは、ファイル記述子に関連付けられていないソケットです。特定の状況では、Out of socket memory error
制限の 2 倍または 4 倍離れている場合でも、カーネルが を発行します ( )。これは、インターネット向けのサービスで頻繁に発生し、完全に正常です。この場合の適切な対処方法は、ピーク時のトラフィックで通常発生する孤立ソケットの数の少なくとも 4 倍になるように/proc/sys/net/ipv4/tcp_max_orphans
調整することです。tcp_max_orphans
tcp_mem
チューニングやtcp_rmem
またはを推奨するアドバイスには耳を傾けないでくださいtcp_wmem
。本当に自分が何をしているか分かっているはずです。こうしたアドバイスをする人はたいてい分かっていません。彼らの魔法は間違っているか、あなたの環境に適していないことが多く、問題を解決しません。むしろ悪化させるかもしれません。
答え3
これらのパラメータのいくつかは定期的に調整されています。高スループット、低レイテンシの取引プラットフォームの標準は次のとおりです。
ネット.ipv4.tcp_rmem = 4096 16777216 33554432 ネット.ipv4.tcp_wmem = 4096 16777216 33554432 ネット.ipv4.tcp_mem = 4096 16777216 33554432 ネットコアrmem_default = 16777216 ネットコアwmem_default = 16777216 ネットコアrmem_max=16777216 ネットコアwmem_max=16777216 ネット.コア.ネットdev_max_backlog = 30000 ネット.コア.ネットdev_max_backlog = 30000