TCP ソケットバッファーをチューニングする方法
Environment
- Red Hat Enterprise Linux (RHEL)
Issue
- ソケットバッファーオーバーランによるパケットロスが発生しています。
- netstat -s は、ソケットバッファーが少ないためにパケットロスを報告します。
Resolution
アプリケーションが setsockopt 呼び出しを使用してバッファーサイズを設定しない場合は、システムのデフォルトサイズが使用されます。
- デフォルトの TCP ソケットバッファーサイズは、以下のファイルによって設定されます。
$ cat /proc/sys/net/ipv4/tcp_rmem
4096 87380 4194304
$ cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4194304
- TCP ソケットバッファーは、カーネルレベルで受信パケットと送信パケットを処理する柔軟なバッファーです。現在の負荷に応じてサイズが変わります。上記のファイル内の 3 つの数字は、バッファーのサイズ制限を示しています。最初の数字は、バッファーが取得する最小の数字です。次の数字はソケットが開かれるデフォルトのサイズで、最後の数字はバッファーの最大サイズです。
- これらの値は、/etc/sysctl.conf ファイルにパラメーターを追加することで変更できます。
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 87380 4194304
十分なメモリーと 1 GB または 10 GB のネットワークカードを備えたマシンでは、バッファープルーニングが行われている場合は最大値を 16 MB まで増やすことができます。実稼働の前に、設定した値を使用して、実際の運用と同等の負荷条件下でマシンをテストすることを推奨します。
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
- これらの変更は、以下を実行してロードする必要があります。
# sysctl -p
-
バッファーを大きくしすぎないように注意してください。バッファーを大きく設定しすぎると、パフォーマンスに影響が出る可能性もあります。これらのバッファーは、システム上の物理メモリーを使用しています。つまり、各 TCP 接続ごとに、その量のメモリーを占めるソケットバッファーが存在します。バッファーの設定が大きすぎる場合、接続数が多くなり、メモリー不足の問題が発生する可能性があります。また、バッファーにデータを読み書きするたびに、ソケット全体を読み取る必要があります。つまり、バッファーが受信または送信される通常のパケットよりも大きい場合、ソケット内のデータ量に関係なく、アプリケーションによってファイル全体が読み取られるため、オーバーヘッドが発生します。
-
ソケットバッファーサイズの増加による影響の詳細は、What are the implications of changing socket buffer sizes? を参照してください。
独自のバッファーサイズを設定するアプリケーションの場合は、setsockopt(SO_RCVBUF) を呼び出します。
上記の sysctl メモリー設定でスループットが十分に向上しない場合は、setsockopt(SO_RCVBUF) 呼び出しを増やすか、アプリケーションコードから setsockopt(SO_RCVBUF) 呼び出しを削除することを推奨します。setsockopt(SO_RCVBUF) 呼び出しを削除すると、カーネルはメモリー値を自動チューニングできるようになります。
- また、
setsockopt(SO_RCVBUF)を使用する場合、アプリケーションで設定されるバッファーサイズは、net.core.rmem_defaultとnet.core.rmem_maxの値に制限される点に注意してください。たとえば、アプリケーション側で 1MB のバッファーを指定しても、net.core.rmem_maxの値が 256K しかない場合、アプリケーションソケットバッファーはこの値に制限されます。
SO_RCVBUF
Sets or gets the maximum socket receive buffer in bytes. The kernel doubles this value (to allow
space for bookkeeping overhead) when it is set using setsockopt(2), and this doubled value is
returned by getsockopt(2). The default value is set by the /proc/sys/net/core/rmem_default file, and
the maximum allowed value is set by the /proc/sys/net/core/rmem_max file. The minimum (doubled)
value for this option is 256.
Diagnostic Steps
- netstat -s の出力を確認することで、ソケットバッファーが過負荷になっているか確認できます。
$ netstat -s | grep socket
1617 packets pruned from receive queue because of socket buffer overrun
798 TCP sockets finished time wait in fast timer
29 delayed acks further delayed because of locked socket
346941 packets collapsed in receive queue due to low socket buffer
-
ソケットバッファー内でパケットの「プルーニング」や「コラプシング」が発生している場合、何らかのチューニングが必要な可能性があります。
-
アクティビティーが少ないサーバーでは、負荷やメモリープレッシャーに変化が見られない場合があることに留意してください。
sysctl による設定変更の影響は、数千もの接続が同時に発生しているような高負荷なサーバーにおいて、より顕著に現れます。
テストは、状況に応じて実行する必要があります。
BEFORE CHANGE (On non busy server)
10:00:01 AM kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
10:50:01 AM 611988 15515156 96.21 1368 8560820 10050932 62.30 8101972 6045188 4604
11:00:01 AM 224920 15902224 98.61 1284 8917416 10182208 63.11 8204204 6331076 4952
AFTER CHANGE (On non busy server)
10:00:01 AM kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
10:53:39 AM 752268 15374876 95.34 1168 8388744 10207324 63.26 8826552 5067064 768
10:53:40 AM 752832 15374312 95.33 1168 8388744 10206940 63.26 8826848 5067064 768
10:53:41 AM 752052 15375092 95.34 1168 8388744 10207068 63.26 8827452 5067064 880
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.
Comments