【sysctl】Linux カーネルパラメータのチューニング

HTTP(S)サーバの負荷テストをしている中でネットワーク関連の Linux カーネルパラメータのチューニングについて興味を持ったので調べてみた。

参考文献は 詳解 システム・パフォーマンス の 10章 ネットワーク 10.8 チューニング 辺り。

環境は Ubuntu 14.04

ulimit(3)

クライアントからの同時接続に対してサーバのファイルディスクリプタ数を上限を変えてみる。ファイルディスクリプタ数 (open files) は 1024 となっていた。

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7781
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7781
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

オープン可能なファイルディスクリプタ数の上限は以下で確認できる。

$ cat /proc/sys/fs/file-max
98946

ulimitコマンドで変更できる。ただし, この方法だと実行したシェル内のみで有効。

$ sudo ulimit -n 4096

実際に確認するにはクライアント側で, 例えば ad コマンドの c オプションで同時接続数を設定してHTTP(S)リクエストを投げる。

$ ab -f TLS1.2 -n 40960 -c 4096 https://example.com/index.html

サーバのプロセスがオープンしているファイルディスクリプタ数は以下で確認できる。

$ sudo ls /proc/{PID}/fd | wc -l 

sysctl(8)

ネットワークでチューニング可能なパラメータは sysctl(8) で確認・変更できる。 または, /proc/sys/net 以下でも変更できる。
HTTP(S)は TCP/IP 上で動くプロトコルなので TCP のパラメータ調整によりパフォーマンスを向上できる場合がある。
ただし, 本の中でも書かれている通り先に netstat, sar, ip, wireshark etc を使って使用状況を掴み静的パフォーマンスチューニングを試してみた方が良いかもしれない。

TCPの送受信の NIC と Application 間の流れは以下。

TCP関連で設定可能なパラメータを確認。

$ sudo sysctl -a | grep tcp | wc -l
52

$ sudo sysctl -a | grep tcp
net.ipv4.tcp_abort_on_overflow = 0
net.ipv4.tcp_adv_win_scale = 1
net.ipv4.tcp_allowed_congestion_control = cubic reno
net.ipv4.tcp_app_win = 31
net.ipv4.tcp_available_congestion_control = cubic reno
net.ipv4.tcp_base_mss = 512
net.ipv4.tcp_challenge_ack_limit = 1000
net.ipv4.tcp_congestion_control = cubic
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_early_retrans = 3
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_fack = 1
net.ipv4.tcp_fastopen = 1
...

設定変更は以下のように書く。

$ sysctl -w parameter=value

設定可能なパラメータの代表例が以下。

  • ソケットとTCPバッファ
  • TCPバッファログ
  • TCP輻輳制御
  • TCPオプション

ソケットとTCPバッファ

全てのプロトコルのソケットバッファサイズの read/write の上限。

$ sysctl -a | grep mem_max
net.core.optmem_max = 20480
net.core.rmem_max = 212992
net.core.wmem_max = 212992

TCPの受信バッファの自動チューニングが有効かどうかの確認。

$ sysctl -a | grep tcp_moderate_rcvbuf
net.ipv4.tcp_moderate_rcvbuf = 1

自動チューニングパラメータは左から下限、デフォルト、上限となる。IPのスループットを上げるには上限をあげると良い。

$ sysctl -a | grep -e tcp_rmem -e tcp_wmem
net.ipv4.tcp_rmem = 4096        87380   6291456
net.ipv4.tcp_wmem = 4096        16384   4194304

TCPバッファログ

負荷のバーストを適切に処理するために, ハーフオープン接続のための backlog queueの長さと, accept() に接続を渡す listen backlog のための backlog queueの長さのデフォルト値を増やす。

$ sysctl -a | grep -e max_syn_backlog -e core.somaxconn
net.core.somaxconn = 128
net.ipv4.tcp_max_syn_backlog = 128

TCP輻輳制御

Linux は plugable な輻輳制御アルゴリズムをサポートする。現在、選択できるアルゴリズムは以下。

$ sudo sysctl -a | grep tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = cubic reno

現在のアルゴリズムを確認。

$ sysctl -a | grep tcp_congestion_control
net.ipv4.tcp_congestion_control = cubic

その他のアルゴリズムも modprobe で動的に追加できる。

TCPオプション

TCPパラメータのオプション設定。
FACK, SACK 拡張は CPU負荷が高まるがレイテンシの高いネットワークのスループットを向上できる場合がある。
reuse はTIME-WAITセッションを再利用できるようになる。recycle は reuse より安全性に乏しい。

$ sysctl -a | grep -e tcp_sack -e tcp_fack -e reuse -e recycle
net.ipv4.tcp_fack = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0


[1] tcp_tw_なんとかの違い
[2] 覚えておきたいカーネルパラメータの変更方法
[3] /procによるLinuxチューニング
[4] Increasing the maximum number of tcp/ip connections in linux