同時実行性の高いLinuxカーネルパラメーターの最適化

ここに画像の説明を挿入

序文

Linuxは、デフォルトのパラメーターでは高い同時実行性を十分にサポートしていないことはよく知られています。デフォルトのパラメーターは、主に、単一プロセスで開くファイルの最大数、カーネルTCPパラメーター、およびIOイベント割り当てメカニズムによって制限されます。Linuxシステムが高同時実行環境をサポートできるように、いくつかの側面から次の調整が行われます。

1.関連するIptables

必要がない場合は、iptablesファイアウォールをオフにするかアンインストールして、カーネルがiptablesモジュールをロードしないようにします。これらのモジュールは、同時パフォーマンスに影響します。

2.1つのプロセスで開いているファイルの最大数

一般リリースバージョンでは、単一のプロセスで開くことができる1024ファイルの最大数が制限されており、高い同時実行性の要件を満たすにはほど遠いです。調整プロセスは次のとおりです。

#プロンプトを入力します。

# ulimit–n 65535

ルートによって開始された単一のプロセスで開くことができるファイルの最大数を65535に設定します。システムが「Operationnotpermitted」のようなエコーを返す場合は、上記の制限変更が失敗したことを意味します。実際には、で指定された値が、Linuxシステムによってユーザーに対して開かれるファイル数のソフト制限またはハード制限を超えているためです。したがって、Linuxシステムの開いているファイルの数に対するソフト制限とハード制限を変更する必要があります。

最初のステップは、limits.confファイルを変更して以下を追加することです。

# vim /etc/security/limits.conf
 
* softnofile 65536
* hard nofile65536

その中で、「*」記号はすべてのユーザーの制限を変更することを意味します。softまたはhardは、ソフト制限またはハード制限のどちらを変更するかを指定します。65536は、変更する新しい制限値、つまり最大数を指定します。開いているファイルの数(ソフト制限値はハード制限以下である必要があることに注意してください)。変更後にファイルを保存します。

2番目のステップは、/ etc / pam.d / loginファイルを変更し、ファイルに次の行を追加することです。

vim /etc/pam.d/login
 
sessionrequired /lib/security/pam_limits.so

これは、ユーザーがシステムログインを完了した後、pam_limits.soモジュールを呼び出して、ユーザーが使用できるリソースの数(ユーザーが開くことができるファイルの最大数を含む)のシステムの最大制限を設定する必要があることをLinuxに通知します。およびpam_limits.soモジュール/etc/security/limits.confファイルから構成を読み取り、これらの制限を設定します。変更後にこのファイルを保存します。

3番目のステップは、Linuxシステムレベルで開いているファイルの最大数を確認し、次のコマンドを使用することです。

cat/proc/sys/fs/file-max
32568

これは、このLinuxシステムで最大32568個のファイルを同時に開くことができることを示しています(つまり、すべてのユーザーが開いているファイルの総数を含む)。これは、Linuxシステムレベルのハード制限であり、その数の制限です。すべてのユーザーレベルで開いているファイルの数は、この値を超えてはなりません。通常、このシステムレベルのハード制限は、Linuxシステムの起動時のシステムハードウェアリソースのステータスに応じて計算される、同時に開くファイルの最適な最大数です。特別な必要がない場合は、必要がない限り、この制限を変更しないでください。ユーザーレベルで開くファイルの数を制限するには、この制限を超える値を設定します。このハード制限を変更する方法は、/ etc /sysctl.confファイルのfs.file-max = 131072を変更することです。

これは、起動が完了した後、Linuxが開いているファイルの数のシステムレベルのハード制限を131072に強制的に設定できるようにするためです。変更後にこのファイルを保存します。

上記の手順を完了したら、システムを再起動します。通常の状況では、Linuxシステムで、指定したユーザーの1つのプロセスを同時に開くことができるファイルの最大数を指定した値に設定できます。ulimit-nコマンドを使用して、再起動後にユーザーが開くことができるファイル数の制限を表示した場合でも、上記の手順で設定した最大値よりも低くなっています。これは、ulimit-nコマンドが原因である可能性があります。ユーザーログインスクリプトで/ etc / profileは、すでにユーザーを同時に開いています。ファイルの数には制限があります。ユーザーがulimit-nを介して同時に開くことができるファイルの最大数をシステムが制限している場合、新しく変更された値は、前回ulimit-nで設定された値以下になり、それが不可能になるためです。このコマンドを使用して、この制限値を増やします。したがって、上記の問題が存在する場合は、/ etc / profileスクリプトファイルのみを開くことができます。ファイル内で、ulimit-nを使用して、ユーザーが同時に開くことができるファイルの最大数を制限しているかどうかを確認します。このコマンドを削除するか、設定値を適切な値に変更してファイルを保存すると、ユーザーはログアウトしてシステムに再度ログインできます。

上記の手順により、高い同時TCP接続処理をサポートする通信処理プログラムのオープンファイル数のシステム制限が解除されます。

3.カーネルTCPパラメーター

Linuxでは、TCP接続が切断された後、ポートを解放する前に、一定期間TIME_WAIT状態のままになります。同時リクエストが多すぎると、TIME_WAIT状態の接続が多数生成され、時間内に切断できない場合は、大量のポートリソースとサーバーリソースが占有されます。現時点では、TCPカーネルパラメータを最適化して、時間内にTIME_WAIT状態のポートをクリアできます。

以下に説明する方法は、多数のTIME_WAIT状態の接続によって引き起こされるシステムリソースの消費に対してのみ有効です。そうでない場合、効果は明ら​​かではない可能性があります。netstatコマンドを使用して、TIME_WAIT状態の接続ステータスを確認し、次の組み合わせコマンドを入力できます。

現在のTCP接続のステータスと対応する接続​​数を表示します。

# netstat-n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
 
#这个命令会输出类似下面的结果:
LAST_ACK16
SYN_RECV348
ESTABLISHED70
FIN_WAIT1229
FIN_WAIT230
CLOSING33
TIME_WAIT18098

ここでわかるように、TIME_WAITの数だけを気にする必要があります。これは、18,000を超えるTIME_WAITがあるため、18,000を超えるポートが占有されています。ポートの数は65,535であり、占有するポートの数は1つ未満であるため、後続の新しい接続に深刻な影響を与えることを知っておくことが重要です。この場合、LinuxのTCPカーネルパラメータを調整して、システムがTIME_WAIT接続をより速く解放できるようにする必要があります。

構成ファイルを編集します。/etc/sysctl.conf、このファイルに次の行を追加します。

vim /etc/sysctl.conf
 
net.ipv4.tcp_syncookies= 1#表示开启SYNCookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse= 1#表示开启重用。允许将TIME-WAITsockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle= 1#表示开启TCP连接中TIME-WAITsockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_fin_timeout= 30#修改系統默认的TIMEOUT 时间。
 
#输入下面的命令,让内核参数生效:
sysctl-p

このような調整の後、サーバーの負荷容量をさらに増やすことに加えて、トラフィックレベルの低いDoS、CC、およびSYN攻撃から防御することもできます。

さらに、接続数が多い場合は、TCPポート範囲を最適化して、サーバーの同時実行性をさらに向上させることができます。それでも、上記のパラメータファイルに次の設定を追加します。

net.ipv4.tcp_keepalive_time= 1200#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range= 1024 65535#表示用于向外连接的端口范围。缺省情况下很小,改为1024到65535。
net.ipv4.tcp_max_syn_backlog= 8192#表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets= 5000#表示系统同时保持TIME_WAIT的最大数量,如果超过这个数字,TIME_WAIT将立刻被清除并打印警告信息。默认为180000,改为5000。此项参数可以控制TIME_WAIT的最大数量,只要超出了。

これらのパラメータは、トラフィックが非常に多いサーバーでのみ有効にすることをお勧めします。これは大きな影響を及ぼします。通常、トラフィックの少ないサーバーでは、これらのパラメーターを設定する必要はありません。

4.カーネルの他のTCPパラメータの説明

net.ipv4.tcp_max_syn_backlog= 65536#记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有128M内存的系统而言,缺省值是1024,小内存的系统则是128。
net.core.netdev_max_backlog= 32768#每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
net.core.somaxconn= 32768#例如web应用中listen函数的backlog默认会给我们内核参数的net.core.somaxconn限制到128,而nginx定义的NGX_LISTEN_BACKLOG默认为511,所以有必要调整这个值。
net.core.wmem_default= 8388608
net.core.rmem_default= 8388608
net.core.rmem_max= 16777216 #最大socket读buffer,可参考的优化值:873200
net.core.wmem_max= 16777216 #最大socket写buffer,可参考的优化值:873200
net.ipv4.tcp_timestsmps= 0#时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。
net.ipv4.tcp_synack_retries= 2#为了打开对端的连接,内核需要发送一个SYN并附带一个回应前面一个SYN的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK包的数量。
net.ipv4.tcp_syn_retries= 2#在内核放弃建立连接之前发送SYN包的数量。
#net.ipv4.tcp_tw_len= 1
net.ipv4.tcp_tw_reuse= 1#开启重用。允许将TIME-WAITsockets重新用于新的TCP连接。
net.ipv4.tcp_wmem= 8192 436600 873200#TCP写buffer,可参考的优化值:8192 436600 873200
 
net.ipv4.tcp_rmem = 32768 436600 873200#TCP读buffer,可参考的优化值:32768 436600 873200
 
net.ipv4.tcp_mem= 94500000 91500000 92700000
 
#同样有3个值,意思是:
#net.ipv4.tcp_mem[0]:低于此值,TCP没有内存压力。
#net.ipv4.tcp_mem[1]:在此值下,进入内存压力阶段。
#net.ipv4.tcp_mem[2]:高于此值,TCP拒绝分配socket。
#上述内存单位是页,而不是字节。可参考的优化值是:7864321048576 1572864
 
net.ipv4.tcp_max_orphans= 3276800
#系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上,如果超过这个数字,连接将即刻被复位并打印出警告信息,这个限制仅仅是为了防止简单的DoS攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。
 
net.ipv4.tcp_fin_timeout= 30
#如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。对端可以出错并永远不关闭连接,甚至意外当机。缺省值是60秒。2.2 内核的通常值是180秒,你可以按这个设置,但要记住的是,即使你的机器是一个轻载的WEB服务器,也有因为大量的死套接字而内存溢出的风险,FIN-WAIT-2的危险性比FIN-WAIT-1要小,因为它最多只能吃掉1.5K内存,但是它们的生存期长些。

同時に、TCP輻輳アルゴリズムも含まれます。次のコマンドを使用して、このマシンが提供する輻輳アルゴリズム制御モジュールを表示できます。

$ sysctl net.ipv4.tcp_available_congestion_control
#对于几种算法的分析,详情可以参考下:TCP拥塞控制算法的优缺点、适用环境、性能分析,比如高延时可以试用hybla,中等延时可以试用htcp算法等。
 
net.ipv4.tcp_congestion_control=hybla#如果想设置TCP 拥塞算法为hybla
net.ipv4.tcp_fastopen= 3#额外的,对于内核版高于于3.7.1的,我们可以开启tcp_fastopen

5.IOイベント配布メカニズム

Linuxで同時実行性の高いTCP接続を有効にするには、アプリケーションが適切なネットワークI / OテクノロジとI / Oイベントディスパッチメカニズムを使用しているかどうかを確認する必要があります。使用可能なI / Oテクノロジは、同期I / O、ノンブロッキング同期I / O、および非同期I / Oです。TCPの同時実行性が高い場合、同期I / Oを使用すると、TCP接続I / Oごとにスレッドが作成されない限り、プログラムの動作が大幅にブロックされます。ただし、スレッドが多すぎると、システムのスレッドのスケジューリングにより、大きなオーバーヘッドが発生します。

したがって、TCPの同時実行性が高い場合は、同期I / Oを使用することはお勧めしません。現時点では、非ブロッキング同期I / Oまたは非同期I / Oの使用を検討できます。ノンブロッキング同期I / O手法には、select()、poll()、epollおよびその他のメカニズムの使用が含まれます。非同期I / Oの手法は、AIOを使用することです。

I / Oイベントディスパッチメカニズムの観点からは、select()を使用することは不適切です。これは、select()がサポートする同時接続の数が制限されているためです(通常は1024以内)。パフォーマンスを考慮すると、poll()も不適切ですが、より高いTCP同時実行性をサポートできますが、「ポーリング」メカニズムのため、同時実行性の数が多いと、動作効率が非常に低く、存在する可能性があります。 I / Oイベントの分散により、一部のTCP接続でI / Oが「不足」します。

epollまたはAIOを使用する場合、そのような問題はありません(LinuxカーネルでのAIOテクノロジーの初期の実装は、カーネルでのI / O要求ごとにスレッドを作成することによって達成されました。この実装メカニズムは、同時TCPが多い場合です。実際、深刻なパフォーマンスの問題がありますが、最新のLinuxカーネルでは、AIOの実装が改善されています)。

要約すると、同時TCP接続をサポートするLinuxアプリケーションを開発する場合、同時TCP接続のI / O制御を実現するために、epollまたはAIOテクノロジーを可能な限り使用する必要があります。これにより、プログラムの同時TCP接続のサポートが向上します。効果的なI / O保証を提供します。

このように最適化された構成の後、サーバーのTCP並行処理機能が大幅に向上します。上記の構成は参考用です。実稼働環境では、実際の状況に応じて調整、観察、調整してください。

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/liuxingjiaoyu/article/details/112762730