ホームページ >運用・保守 >Linuxの運用と保守 >高い同時実行条件下での Linux システムとカーネル パラメーターの最適化

高い同時実行条件下での Linux システムとカーネル パラメーターの最適化

Linux中文社区
Linux中文社区転載
2023-08-04 16:41:19965ブラウズ

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

iptables 関連

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

単一プロセスでオープンできるファイルの最大数の制限

一般的なディストリビューションでは、単一プロセスでオープンできるファイルの最大数は 1024 に制限されていますが、これは決して大きくはありません。 # プロンプトで次のように入力します:

# ulimit–n 65535

root によって開始された 1 つのプロセスで開けるファイルの最大数を 65535 に設定します。システムが「操作は許可されていません」のようなメッセージを表示する場合、上記の制限の変更が失敗したことを意味します。実際、指定された値は、ユーザーが開いたファイル数に対する Linux システムのソフト制限またはハード制限を超えています。したがって、ユーザーが開くファイルの数に関する Linux システムのソフト制限とハード制限を変更する必要があります。

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

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

「*」記号は、すべてのユーザーの制限を変更することを示します。ソフトまたはハードは、ソフト制限を変更するかどうかを指定します。またはハード制限。65536 は、変更する新しい制限値、つまり開いているファイルの最大数を指定します (ソフト制限値はハード制限以下である必要があることに注意してください)。変更を加えた後、ファイルを保存します。 2 番目のステップは、/etc/pam.d/login ファイルを変更し、次の行をファイルに追加することです。

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

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

第三步,查看Linux系统级的最大打开文件数限制,使用如下命令:

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

这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)32568个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。修改此硬限制的方法是修改/etc/sysctl.conf文件内fs.file-max= 131072

这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为131072。修改完后保存此文件。

完成上述步骤后重启系统,一般情况下就可以将Linux系统对指定用户的单一进程允许同时打开的最大文件数限制设为指定的数值。如果重启后用ulimit-n命令查看用户可打开文件数限制仍然低于上述步骤中设置的最大值,这可能是因为在用户登录脚本/etc/profile中使用ulimit-n命令已经将用户可同时打开的文件数做了限制。

由于通过ulimit-n修改系统对用户可同时打开文件的最大数限制时,新修改的值只能小于或等于上次ulimit-n设置的值,因此想用此命令增大这个限制值是不可能的。所以,如果有上述问题存在,就只能去打开/etc/profile脚本文件,在文件中查找是否使用了ulimit-n限制了用户可同时打开的最大文件数量,如果找到,则删除这行命令,或者将其设置的值改为合适的值,然后保存文件,用户退出并重新登录系统即可。

通过上述步骤,就为支持高并发TCP连接处理的通讯处理程序解除关于打开文件数量方面的系统限制。

内核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的个数,在这里可以看到,有18000多个TIME_WAIT,这样就占用了18000多个端口。要知道端口的数量只有65535个,占用一个少一个,会严重的影响到后继的新连接。这种情况下,我们就有必要调整下Linux的TCP内核参数,让系统更快的释放TIME_WAIT连接。

编辑配置文件:/etc/sysctl.conf,在这个文件中,加入下面的几行内容:

# vim /etc/sysctl.conf
net.ipv4.tcp_syncookies= 1
net.ipv4.tcp_tw_reuse= 1
net.ipv4.tcp_tw_recycle= 1
net.ipv4.tcp_fin_timeout= 30

输入下面的命令,让内核参数生效:

# sysctl-p

简单的说明上面的参数的含义:

  • 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 修改系統默认的TIMEOUT 时间。

在经过这样的调整之后,除了会进一步提升服务器的负载能力之外,还能够防御小流量程度的DoS、CC和SYN攻击。

此外,如果你的连接数本身就很多,我们可以再优化一下TCP的可使用端口范围,进一步提升服务器的并发能力。依然是往上面的参数文件中,加入下面这些配置:

net.ipv4.tcp_keepalive_time= 1200
net.ipv4.ip_local_port_range= 1024 65535
net.ipv4.tcp_max_syn_backlog= 8192
net.ipv4.tcp_max_tw_buckets= 5000

这几个参数,建议只在流量非常大的服务器上开启,会有显著的效果。一般的流量小的服务器上,没有必要去设置这几个参数。

  • net.ipv4.tcp_keepalive_time= 1200 キープアライブが有効な場合に TCP がキープアライブ メッセージを送信する頻度を示します。デフォルトは 2 時間ですが、20 分に変更します。
  • 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 の最大数を、それを超えている限り制御できます。その他のカーネル TCP パラメータの説明
  • net.ipv4.tcp_max_syn_backlog= 65536 クライアント確認情報をまだ受信していない、記録された接続要求の最大値。 128M のメモリを備えたシステムの場合、デフォルト値は 1024 で、メモリが小さいシステムの場合、デフォルト値は 128 です。
  • net.core.netdev_max_backlog= 32768 各ネットワーク インターフェイスがカーネルの処理よりも速くパケットを受信した場合に、キューに入れることができるパケットの最大数。
  • net.core.somaxconn= 32768 たとえば、Web アプリケーションの listen 関数のバックログは、カーネル パラメーターの net.core.somaxconn をデフォルトで 128 に制限しますが、 nginx で定義されている NGX_LISTEN_BACKLOG のデフォルトは 128.511 なので、この値を調整する必要があります。
  • net.core.wmem_default= 8388608
  • net.core.rmem_default= 8388608
  • net.core.rmem_max= 16777216 #最大ソケット読み取りバッファー、参照最適化値: 873200
  • #net.core.wmem_max= 16777216 #最大ソケット書き込みバッファー、参照最適化値:873200
  • net.ipv4.tcp_timestsmps= シーケンス番号の折り返しを避けるためのタイムスタンプは 0 です。 1Gbps リンクでは、以前に使用されたシーケンス番号が必ず発生します。タイムスタンプにより、カーネルはそのような「異常な」パケットを受け入れることができます。ここでオフにする必要があります。
  • net.ipv4.tcp_synack_retries= 2 ピアへの接続を開くには、カーネルは前の SYN に対する応答として ACK を含む SYN を送信する必要があります。これは、いわゆる 3 ウェイ ハンドシェイクにおける 2 回目のハンドシェイクです。この設定は、カーネルが接続を放棄する前に送信される SYN ACK パケットの数を決定します。
  • net.ipv4.tcp_syn_retries= 2 カーネルが接続の確立を断念する前に送信された SYN パケットの数。
  • #net.ipv4.tcp_tw_len= 1
  • net.ipv4.tcp_tw_reuse= 1 再利用を有効にします。新しい TCP 接続に TIME-WAIT ソケットを再利用できるようにします。
  • net.ipv4.tcp_wmem= 8192 436600 873200 TCP 書き込みバッファ、参照最適化値: 8192 436600 873200
  • net.ipv4.tcp_rmem = 32768 436600 873200 TCP 読み取りバッファ、参照最適化値: 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 はソケットの割り当てを拒否します。上記のメモリ単位はバイトではなくページです。参照最適化値は次のとおりです: 7864321048576 1572864
  • ##net.ipv4.tcp_max_orphans= 3276800 ユーザー ファイル ハンドルに関連付けられていない、システム内の TCP ソケットの最大数。この数を超えると、接続はただちにリセットされ、警告メッセージが出力されます。この制限は、単純な DoS 攻撃を防ぐためだけのものです。この制限に頼りすぎたり、この値を人為的に減らすことはできません。(メモリを増やす場合は) この値を増やす必要があります。
  • net.ipv4.tcp_fin_timeout= 30 ソケットがローカル エンドによって閉じるように要求された場合、このパラメータはソケットが FIN-WAIT-2 状態に留まる時間を決定します。ピアがエラーを起こして接続を閉じなかったり、予期せずクラッシュしたりする可能性があります。デフォルト値は 60 秒です。 2.2 カーネルの通常の値は 180 秒です。この設定を押すことはできますが、マシンの負荷が軽い WEB サーバーであっても、多数のデッドソケットによるメモリ オーバーフローのリスクがあることに注意してください。 2 は、最大 1.5K のメモリしか消費できないため、FIN-WAIT-1 より危険性は低くなりますが、生存期間は長くなります。
  • # これには、TCP 輻輳アルゴリズムの問​​題も関係しています。次のコマンドを使用して、このマシンが提供する輻輳アルゴリズム制御モジュールを表示できます:

    • sysctl net.ipv4.tcp_available_congestion_control
    複数のアルゴリズムの分析については、以下を参照してください。TCP 輻輳制御アルゴリズムの長所と短所、適用環境、パフォーマンス分析、たとえば、遅延が大きい場合は hybla を、中程度の遅延の場合は htcp アルゴリズムを試すことができます。

    TCP 輻輳アルゴリズムを hybla net.ipv4.tcp_congestion_control=hybla

    に設定する場合は、カーネル バージョン 3.7.1 以降では、tcp_fastopen: net.ipv4 を有効にできます。 . tcp_fastopen= 3

    IO イベント分散メカニズム

    Linux で高同時実行 TCP 接続を有効にするには、アプリケーションが適切なネットワーク I/O テクノロジを使用しているかどうかを確認する必要があります。 I/O OEvent ディスパッチ メカニズム。利用可能な 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() はサポートされる同時接続数が限られているため (通常は 1024 以内)、select() を使用するのは不適切です。パフォーマンスを考慮すると、poll() も不適切です。より多くの TCP 同時実行をサポートできますが、その「ポーリング」メカニズムにより、同時実行数が多い場合、その動作効率は非常に低くなり、問題が発生する可能性があります。 I/O イベントが不均一に分散されるため、一部の TCP 接続で I/O の「枯渇」が発生します。 epoll または AIO を使用する場合、上記の問題は発生しません (Linux カーネルにおける AIO テクノロジの初期の実装は、I/O リクエストごとにカーネル内にスレッドを作成することで実現されました。この実装メカニズムは、高負荷の場合にうまく機能します)同時 TCP 接続。実際、これを使用するとパフォーマンスに重大な問題が発生します。しかし、最新の Linux カーネルでは、AIO の実装が改善されています。

    要約すると、高同時 TCP 接続をサポートする Linux アプリケーションを開発する場合は、epoll または AIO テクノロジを使用して同時 TCP 接続の I/O 制御を実現するようにしてください。これにより、プログラムの高同時接続のサポートが向上します。 TCP 接続は効率的な I/O を保証します。

    このように構成を最適化すると、サーバーの TCP 同時処理能力が大幅に向上します。上記の構成は参考値ですので、本番環境で使用する場合は、実際の状況に応じて観察および調整してください。

    以上が高い同時実行条件下での Linux システムとカーネル パラメーターの最適化の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はLinux中文社区で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。