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