
約1,000の持続的で非常に低い帯域幅のTCP接続を備えたフロントエンドシステムがあります。メモリが少し制限されているので、何百MBはどこに行くのかを調べたいと思います。 TCPバッファが原因の1つである可能性がありますが、次の問題を解決できませんでした。
- 記憶レポートはどこにありますか?
buff/cache
プロジェクトの一部ですかtop
、それともRES
プロセス測定の一部ですか? - プロセスごとのレベルでそれを減らしたい場合は、減少が望ましい効果を持つようにするにはどうすればよいですか。
- 最小限のトラフィックであってもバッファがメモリを占有し続けるのか、それともバッファサイズが動的に増加し、バッファサイズが単に許容される最大サイズですか?
考えられる答えの1つは、「カーネルがこれを行うことを信頼すること」であることを知っていますが、TCPバッファをメモリの圧迫の原因として除外したいと思います。
調査:質問1
このページ「バッファ」メモリは、Linuxがネットワークとディスク接続をバッファリングするために使用するメモリです。これはRES
mesometricの一部ではないことを意味しますtop
。
実際のメモリ使用量を見つけるには、/proc/net/sockstat
最も有望なものは次のとおりです。
sockets: used 3640
TCP: inuse 48 orphan 49 tw 63 alloc 2620 mem 248
UDP: inuse 6 mem 10
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
これ私が見つけることができる最高の説明ですが、そこmem
では解決されませんでした。解決済みここただし、248 * 4k〜= 1MBまたはシステム全体の最大値の約1/1000です。これは、数百の継続的な接続と一定の0.2-.3 Mbit / secネットワークトラフィック番号を持つサーバーの場合、とんでもない低いようです。
もちろん、システムメモリ制限自体は次のとおりです。
$ grep . /proc/sys/net/ipv4/tcp*mem
/proc/sys/net/ipv4/tcp_mem:140631 187510 281262
/proc/sys/net/ipv4/tcp_rmem:4096 87380 6291456
/proc/sys/net/ipv4/tcp_wmem:4096 16384 4194304
tcp_mem
3番目のパラメータは、TCPバッファ専用のシステム全体の最大4kページ数です。バッファサイズの合計がこの値を超えると、カーネルはパケットドロップを開始します。特別でないワークロードの場合、この値を調整する必要はありません。
以下は/proc/meminfo
謎Buffers
とCached
アイテムと共にです。私はいくつかのソースを見ましたが、TCPバッファを説明すると主張するソースが見つかりませんでした。
...
MemAvailable: 8298852 kB
Buffers: 192440 kB
Cached: 2094680 kB
SwapCached: 34560 kB
...
調査:質問2-3
プロセスレベルでTCPバッファサイズを確認するための多くのオプションがありますが、どちらも現在のキューサイズや最大値ではなく、実際に割り当てられたメモリを提供していないようです。
持っているss -m --info
:
State Recv-Q Send-Q
ESTAB 0 0
... <snip> ....
skmem:(r0,rb1062000,t0,tb2626560,f0,w0,o0,bl0) ...<snip> rcv_space:43690
だから私たちは
Recv-Q
およびSend-Q
現在のバッファ使用量r
そしてt
、説明はこの素晴らしい記事Recv-Q
しかし、とはどう違うのか明確ではありません。Send-Q
- というのは
rb
疑わしく最大バッファサイズのように見えますが、ドキュメントが見つかりません。 rcv_space
、どちらこのページ宣言は、呼び出す必要がある実際のバッファサイズではありません。getsockopt
この回答提案されていますが、lsof
size / offは次のようなバッファ使用量を報告しているようですss
。
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sslocal 4032 michael 82u IPv4 1733921 0t0 TCP localhost:socks->localhost:59594 (ESTABLISHED)
それからこの回答lsofが実際のバッファサイズを返すことができないことを示します。トリックを実行するカーネルモジュールを提供しますが、ただ働いているようですバッファサイズが渡されますsetsockopt
。固定ソケットでない場合、SO_SNDBUFおよびSO_RCVBUFは含まれません。
答え1
/proc/net/sockstat
特にmem
フィールドを見てみましょう。この値はカーネルページに報告されます/proc/sys/net/ipv4/tcp_mem
。
個々のソケットレベルでは、メモリはユーザー空間コードがそれを読み取るまでカーネル空間にのみ割り当てられ、この時点でカーネルメモリは解放されます(参照:ここ)。sk_buff->truesize
バッファリングされたデータ量とソケット構造自体の合計です(参照:ここ、メモリアライメントを修正するためのパッチについて説明します。ここ)
私が疑うフィールドはmem
単にすべてのソケットを合計/proc/net/sockstat
してsk_buff->truesize
計算されますが、カーネルソースコードに慣れていないので、どこで見つけるべきかわかりません。
確認を通じて、この機能リクエストネットデータ監視システムのコンテンツには、多くの良い議論と関連リンクが含まれており、これらの解釈をサポートしています/proc/net/sockstat
。
この投稿「ソケットメモリ不足」エラーには、さまざまなメモリ問題に関するより一般的な議論が含まれています。
答え2
これは非常に複雑な質問であり、答えを見つけるためにカーネルソースコードを掘り下げる必要があるかもしれません。
バッファがプロセスのRES統計に含まれていないようです。バラよりこれ記事(まだ読んでいない場合)の著者によると:
デバイスドライバは、着信パケットに対してDMAを実行するためにデバイスにメモリ領域を割り当てる。
「調整:ソケット受信キューメモリ」セクションには、最大バッファサイズが表示されますnet.core.wmem_max
。net.core.rmem_max
繰り返しますが、実際にどのくらいのメモリが使用されているかを確認する方法はわかりません。
明らかに、ネットワークスタック内には文書化レベルが低く、複雑性が高いという問題がある。ここにいる
また、バッファリングがどのように処理されるかを読むほど、バニラカーネルはバッファに割り当てられたメモリの量以外に他のものを見ることをサポートしていないようです。
これカーネルのDMAに関するいくつかのドキュメントもあなたにとって役に立つかもしれませんし、少なくともここでどこに行くべきかについてのアイデアを提供するかもしれませんが、私たちは現在提供されているカーネルモジュールがあなたが得ることができる最も近いモジュールだと思います。
答え3
前述のように、memフィールドはあなたの質問に関連するフィールドです。
# cat /proc/net/sockstat
sockets: used 2512
TCP: inuse 2301 orphan 48 tw 3187 alloc 2304 mem 981
UDP: inuse 12 mem 2
UDPLITE: inuse 0
RAW: inuse 2
FRAG: inuse 0 memory 0
# echo $(( 981 * 4096 / 2**20 ))MB
3MB