sysctlで設定可能な項目について調査した内容。
-
-
Save matsukaz/806a006f60a3cbde255dbb6e651f3555 to your computer and use it in GitHub Desktop.
fs.file-max
で設定。
プロセス単位の制限については /etc/security/limits.conf
で設定する必要がある。
これらの値はPAM認証(sudoやユーザーでログインした場合)がないと反映されないため、デーモンプロセスなどでファイルディスクリプタ数を増やしたいときには ulimit
コマンドを起動スクリプト( /etc/rc.d/init.d/
など)で指定する必要がある。
fs.aio-max-nr
で設定。
デフォルトは65536で、Oracleなどは1048576といった大きめの値を推奨している。
値が小さいとアプリケーションが起動できないといったケースが発生する。
現在値は /proc/sys/fs/aio-nr
で確認できる。
システム全体のスレッド数は kernel.threads-max
で設定。デフォルトではメモリサイズに応じて算出された値となる。
なおLinuxではスレッドもプロセスとして扱われるため、スレッドにもpidを必要とする。 kernel.threads-max
を設定した場合は、同じ値を kernel.pid_max
にも設定しなければならない。
プロセス番号の最大値のデフォルト値は 32768 (1 << 15)。 32 bit 環境では上げられない。 64 bit 環境では 2^22 (4Mぐらい) まで上げることが可能。 http://www.yunabe.jp/docs/maximum_number_of_threads.html
またpthreadは1スレッドあたり、2つのメモリマップを必要としているため、メモリマップの最大数の半分を超えるスレッドを作ることはできない。 kernel.threads-max
を設定する場合は、合わせて vm.max_map_count
に倍の値を設定する。
大量のスレッドを利用する環境で Cannot allocate memory
エラーが発生した場合に、このチューニングを行う。
vm.swappiness
で設定。
0 から 100 の値でシステムがスワップを行う程度を制御します。値が高い場合はシステムのパフォーマンスを優先し、物理メモリがアクティブでない場合にメモリからプロセスを積極的にスワップします。値が低いと対話機能を優先し、できるだけ長く物理メモリからのプロセスのスワップを回避することから、反応の待ち時間が低下します。デフォルト値は 60 です。 https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-memory-tunables
一般的に低く設定するのが良いが、ネットで見かけるような0などの値は問題になることがあるので注意。 詳細は こちら 。
ユースケースとしては
- DBサーバなど起動してるアプリケーションが少ない環境下では1〜10など
- 様々なアプリケーションを同時に起動してるような環境下では10〜20程度?
前提として知っておく情報。
listen()システムコールでLISTEN状態にあるソケットはbacklogというキューを持つ。backlogにはクライアントからのTCP接続要求が確立(ESTABLISH状態)し、まだaccept()されていない接続が並ぶ。 LISTENソケットは、backlog以外にもTCP接続中(SYN_RECV状態)の接続を格納しておくsyn backlogというキューも持つ(実際にはハッシュテーブルで実装)
listen()時に指定されるbacklog引数の値
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd, int backlog);
ただし、 net.core.somaxconn < backlog
の場合は net.core.somaxconn
の値に切り詰められる。
backlogと net.ipv4.tcp_max_syn_backlog
の値を元に決定する。
syn backlogのサイズはbacklog値を 8 〜
net.ipv4.tcp_max_syn_backlog
の範囲に収めた後、一つ上の2のべき乗の値に切り上げた値になる。
表1 syn backlogサイズ計算例 (tcp_max_syn_backlog = 400の場合)
backlog | syn backlog |
---|---|
128 | 256 |
200 | 256 |
256 | 512 |
512 | 512 (net.ipv4.tcp_max_syn_backlog < backlogなので400を切り上げた512となる) |
net.core.netdev_max_backlog
で設定。
カーネルの処理速度よりも早い速度でネットワーク・インタフェースがパケットを受信する場合に、カーネルがバッファ(キューイング)するパケットの最大個数を指定します。
net.ipv4.tcp_window_scaling
で設定。
RFC1323のTCPウィンドウスケーリングを有効にするためのもので、64KB以上にしたいときに1を設定する。
最近のカーネルはデフォルト1なので、意識しなくても大丈夫。
以下で設定。
net.ipv4.tcp_rmem
net.ipv4.tcp_wmem
いずれも、 min default max
の3つの値をスペース区切りで指定する。
値が小さいと一度に送信できるデータ量が制限され、場合によってはACK待ちとなる。 大きくするとメモリ使用量や通信エラー時のリカバリに影響がある。
デフォルト値がかなり小さい場合があるので、1回でやりとりするデータ量が大きいサーバの場合はチューニングすると効果的。
またOS全体のあらゆるコネクションのバッファサイズを設定する項目もある。
net.core.rmem_default
- 受信バッファサイズのデフォルト値
net.core.rmem_max
- 受信バッファサイズの最大値
net.core.wmem_default
- 送信バッファサイズのデフォルト値
net.core.wmem_max
- 送信バッファサイズの最大値
net.core.[r|w]mem_[default|max]
と net.ipv4.tcp_[r|w]mem
で内容的にはかぶるが、max値はnet.coreが優先され、デフォルト値はnet.ipv4が優先される。
net.ipv4.tcp_slow_start_after_idle
で設定。
輻輳制御アルゴリズムの一つであるSlow Startを利用しないときに0を設定する。Slow Startは、Keepaliveしててもしばらく通信がない場合に、TCPウィンドウサイズが増えたままだと適切な値じゃなくなってる場合があるので、その辺を調整してくれるための機構。
デフォルトは1が多そう。輻輳が少ない環境下でKeepaliveが使われている場合に0にしておくと効率が良さそう。
net.core.optmem_max
で設定。
以下、関連する個人的な説明。
まずソケットの補助データにアクセスするために利用するのがCMSGマクロで、補助データはソケット上に乗るものではない。例えばドメインソケットでは、これを利用してファイルディスクリプタやプロセスのcredential情報などを受け渡してる。 補助データ用のバッファサイズが小さいとバッファ内に収まらなくなり、一部のデータを切り捨てられたことを示すMSG_CTRUNCフラグが立つとのこと。 ただMSG_CTRUNCフラグが立ったときの挙動はわからず… 自分で実装した場合は、バッファサイズを増やして再度ハンドリングするとかになるみたいだけど https://stackoverflow.com/questions/48861927/how-do-i-get-the-size-of-the-msg-control-buffer-for-recvmsg/48913873#48913873 実際にnet.core.optmem_maxを調整してパフォーマンスが向上してるケースはあるみたい。 「転送効率がよくなって」という説明だったけど、バッファサイズが直接効率につながる気はしないので、MSG_CTRUNCフラグが立った場合のハンドリングに何かがありそう。 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=2405&forum=11 ネットでみかけるnet.core.optmem_maxのチューニング値は、40960もあれば16777216(EMQとか)とだいぶまちまち。 補助データがどれだけ利用されるアプリケーションを実行しているか次第、というところかもしれない。
net.ipv4.tcp_max_tw_buckets
で設定。
この制限が存在するのは、 単純な使用不能 (denial-of-service) 攻撃を防ぐために過ぎない。 デフォルト値は NR_FILE で、システムのメモリーに応じて調整される。この数値を越えると、そのようなソケットはクローズされ、警告が表示される。 https://linuxjm.osdn.jp/html/LDP_man-pages/man7/tcp.7.html
net.ipv4.tcp_tw_reuse = 1
で設定。
net.ipv4.tcp_tw_reuse を有効にすると、 TIME_WAIT 状態のソケットでもタイムスタンプが1秒でも新しければ、新しい接続で再利用できるようになります。 ただしすぐに再利用されるというわけではなく、外向きの接続で、なおかつ接続先が同じ場合に限られます。 https://qiita.com/tmshn/items/b49f1b51bfc472968b30
以下の条件を満たした場合のみ利用される。
- 送信元も受信先も、
net.ipv4.tcp_timestamps=1
でTCP Timestamp Optionを有効にしている - 送信元のIPとポート番号、受信元のIPとポート番号が一致している
net.ipv4.ip_local_port_range
で設定。
可能であればどちらかを偶数、もう片方を奇数にした方が良い。
詳しくは https://patchwork.ozlabs.org/patch/476002/
デフォルトの値は基本的に 32768 60999
net.ipv4.tcp_fin_timeout
で秒数を設定。
TIME_WAIT状態のセッションが大量に残ってしまうような場合、この値を短く設定することで解決できる。
サーバの用途によって最適値は異なる。
Webサーバは 20〜30秒
程度が目安の模様。
ISUCONでは同一クライアントからの大量アクセスが行われるため、 10秒
程度が良さそう。
- @IT - 信頼性のある通信を実現するTCPプロトコル
- Linuxカーネルメモ
- Linux Programmer's Manual - TCP
- Kernel Document - /proc/sys/net/ipv4/* Variables
- Slideshare - TIME_WAITに関する話
- Ubuntu(Linux)カーネル・チューニングでネットワークを高速化!
- backlog あれこれ
- Qiita - net.ipv4.tcp_tw_recycle は廃止されました ― その危険性を理解する
- tcp_fin_timeout 設定は本当に効果あるのか
- 題名:ネットワークについて
- High Performance Browser Networking
- oneのはてなダイアリー - Linuxカーネルパラメータの設定とチューニング、デフォルト値の調べ方