最近、非常に興味深い問題に遭遇しました。頻繁に問題が発生する HAProxy のグループがあります。サーバーにログインし、CPU、メモリ、ネットワーク、IO を確認します。最終的に、マシンの TIME_WAIT 状態にある接続が 60,000 を超えていることが判明しました。
TIME_WAIT 状態は通常、HAProxy や Nginx などのプロキシ マシンで発生します。主に頻繁なアクティブ シャットダウンが原因です。再利用およびリサイクルのパラメータを変更することで、問題は比較的迅速に解決できます。
ネットワーク状態の統計情報は、次のコマンドを使用して計算できます。
netstat -ant|awk '/^tcp/ {++S[$NF]} END {for(a in S) print (a,S[a])}' ESTABLISHED 70 FIN_WAIT2 30 CLOSING 33 TIME_WAIT 65520
これには特別なことは何もありませんが、65535 という数字は機密性が高すぎます。何らかの上限が発動したはずだ。
私たちをさらに混乱させるのは、TIME_WAIT 状態の接続が 65535 に達するだけなのに、サービスが利用できないのはなぜですか?
マシンごとに数百万の接続があるという主張は自慢なのでしょうか? ?その理由は次のとおりです。トラブルに耐えられませんか?
65535 は、2 の 16 乗マイナス 1 に等しいという意味の魔法の数です。この小さな数字をひとまず脇に置いて、まず Linux がサポートする接続容量を理解しましょう。
1. Linux はいくつの接続をサポートできますか?
答えは無数にあります。しかし、ポートは 65535 個しかありません。
なぜポートが 65535 個しかないのですか?
TCP プロトコルと UDP プロトコルは、それぞれ送信元ポート番号と宛先ポート番号を格納するために最初に 16 ビットを使用します。これは歴史的な理由に基づいています。残念ながら、この値は short 型であり、サイズも 2^16-1 です。
歴史的理由による不変の基準は非常に根深いものです。
Linux はいくつの接続をサポートできますか? 答えは無数にあります。
nginx を例として、ポート 80 で監視します。現時点では、マシン A は Nginx に接続し、最大 60,000 の長い接続を開始できます。マシン B が Nginx に接続する場合、60,000 の複数の接続を開始することもできます。これは、接続の決定が src と dst によって決定されるためです。
Linux が 65535 の接続しか受け入れられないという考えは、非常に表面的な仮定であるとしか言えません。
65535 ポートは、ストレス テスターとしては小さすぎるかもしれません。しかし、サーバーの場合はこれで十分です。
2. 数百万の接続をサポートするにはどうすればよいですか?
上記からわかるように、接続数に制限はありません。しかし、Linux にはファイル ハンドルの数という別の保護層があります。 lsof コマンドを通じて表示されるものは、いわゆるファイル ハンドルです。
いくつかのコマンドの表示を見てみましょう。
ulmit は、各プロセスが占有できるファイル ハンドルの数を示します。
ulimit -n 65535
file-max は、すべてのプロセスについて、オペレーティング システムが占有できるファイル ハンドルの合計数を示します。
cat /proc/sys/fs/file-max 766722
file-nr は、現在使用されているハンドルの数とハンドルの総数を示します。モニタリングに使用できます。
cat /proc/sys/fs/file-nr 1824 0 766722
数百万の接続をサポートするには、オペレーティング システム レベルのハンドルとプロセス レベルのハンドルを解放する必要があります。つまり、ulimit と file-max の表示は 100 万を超える必要があります。
3. 設定方法
一般的に使用される解決策はプロセス ハンドルの数を ulimit に設定することですが、私はそれを強くお勧めしません。他の理由なく、同じシェルで開始されたプロセスのみが ulimit 設定の影響を受けます。別のシェルを開くか、マシンを再起動すると、ulimit の変更は消えます。これは次の方法です:
ulimit -n 1000000
正しい方法は、/etc/security/limits.conf ファイルを変更することです。例えば以下のような内容です。
root soft nofile 1000000 root hard nofile 1000000 * soft nofile 1000000 * hard nofile 1000000
ご覧のとおり、特定のユーザーのハンドル数を変更できます。これは、es などのアプリケーションをインストールするときによく発生します。
es - nofile 65535
この方法を使用しても、操作するには新しいシェルを開く必要があります。このコマンドは、変更後のシェルでも変更前のシェルでも有効になりません。 xjjdog では、制限が解除されたにもかかわらず依然として問題が発生するケースを複数発生しました。
プロセスのメモリ マップ ファイルを表示して、これらの変更が有効になっているかどうかを確認します。たとえば、「cat /proc/180323/limits」コマンドでは、詳細情報が表示されます。
この値は、設定したいほど大きくありません。サイズの上限は nr_open によって決まります。サイズを増やすには、/ect/sysct.conf の fs.nr_open の値を変更します。
cat /proc/sys/fs/nr_open 1048576
file-max パラメータを変更する場合は、/etc/sysctl.conf ファイルに次の内容を追加することをお勧めします。 600 万以上あります!
fs.file-max = 6553560
ファイルの数が超過すると、「カーネル: VFS: ファイル最大制限 65535 に達しました」というエラーが報告されます。 ######結論は。
# Linux はポートを開いていても、多数の接続を受け入れることができます。これらの接続の上限は、単一プロセス内のファイル ハンドルの数とオペレーティング システムのファイル ハンドルの数、つまり ulimit と file-max によって制限されます。
パラメータの変更を永続化するために、変更をファイルに書き込む傾向があります。プロセスのファイル ハンドル制限は /etc/security/limits.conf に設定でき、その上限は fs.nr_open によって制限されます。オペレーティング システムのファイル ハンドル制限は /etc/sysctl.conf に設定できます。ファイル。最後に、/proc/$id/limits ファイルを必ずチェックして、変更がプロセス内で有効になっているかどうかを確認してください。
以上がUlimit の障害を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。