サーバーをプログラミングしていますが、接続数を「無制限」に設定しても帯域幅が飽和していないため、接続数が制限されているようです。
Ubuntu Linux ボックスが一度に開くことができる接続の最大数を増やしたり、削除したりするにはどうすればよいですか? OSがこれを制限していますか、それともルーターまたはISPですか?それとも別のものですか?
サーバーをプログラミングしていますが、接続数を「無制限」に設定しても帯域幅が飽和していないため、接続数が制限されているようです。
Ubuntu Linux ボックスが一度に開くことができる接続の最大数を増やしたり、削除したりするにはどうすればよいですか? OSがこれを制限していますか、それともルーターまたはISPですか?それとも別のものですか?
接続の最大数は、クライアント側とサーバー側の両方で特定の制限の影響を受けますが、少し異なります。
クライアント側:
一時ポートの範囲を増やし、ポート範囲を減らします。tcp_fin_timeout
デフォルト値を確認するには:
sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_fin_timeout
一時ポート範囲は、ホストが特定の IP アドレスから作成できるアウトバウンド ソケットの最大数を定義します。は、これらのソケットが状態 (一度使用されると使用不可) にfin_timeout
とどまる最小時間を定義します。TIME_WAIT
通常のシステム デフォルトは次のとおりです。
net.ipv4.ip_local_port_range = 32768 61000
net.ipv4.tcp_fin_timeout = 60
(61000 - 32768) / 60 = 470
これは基本的に、システムが1 秒あたりのソケット数を超えることを一貫して保証できないことを意味します。これに満足できない場合は、 を増やすことから始めることができますport_range
。範囲を に設定すること15000 61000
は、最近ではかなり一般的です。を減らすことで、可用性をさらに高めることができますfin_timeout
。両方を実行すると、1 秒あたり 1500 を超えるアウトバウンド接続がより簡単に表示されるはずです。
値を変更するには:
sysctl net.ipv4.ip_local_port_range="15000 61000"
sysctl net.ipv4.tcp_fin_timeout=30
上記は、1 秒あたりのアウトバウンド接続を作成するシステム機能に影響を与える要因として解釈されるべきではありません。むしろ、これらの要因は、長時間の「アクティビティ」に対して持続可能な方法で同時接続を処理するシステムの能力に影響を与えます。
tcp_tw_recycle
&の典型的な Linux ボックスのデフォルトの Sysctl 値は次のtcp_tw_reuse
ようになります。
net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_tw_reuse=0
これらは、「使用済み」ソケット (待機状態) からの接続を許可せず、ソケットを完全なtime_wait
サイクルで持続させます。設定をお勧めします:
sysctl net.ipv4.tcp_tw_recycle=1
sysctl net.ipv4.tcp_tw_reuse=1
これにより、状態のソケットを高速に循環さtime_wait
せて再利用することができます。ただし、この変更を行う前に、これらのソケットを必要とするアプリケーションに使用するプロトコルと競合しないことを確認してください。Vincent Bernat の投稿「TCP TIME-WAIT への対処」を読んで、その意味を理解してください。このnet.ipv4.tcp_tw_recycle
オプションは、同じNATデバイスの背後にある2つの異なるコンピューターからの接続を処理しないため、公開サーバーにとっては非常に問題があります. Linux 4.12 から削除されたことに注意しnet.ipv4.tcp_tw_recycle
てください。
サーバー側:
値net.core.somaxconn
には重要な役割があります。リッスン ソケットのキューに入れられるリクエストの最大数を制限します。サーバー アプリケーションの機能に確信がある場合は、デフォルトの 128 から 128 から 1024 などに増やしてください。アプリケーションのリッスン コールのリッスン バックログ変数を同じかそれ以上の整数に変更することで、この増加を利用できます。
sysctl net.core.somaxconn=1024
txqueuelen
イーサネット カードのパラメータにも役割があります。デフォルト値は 1000 であるため、システムが処理できる場合は 5000 またはそれ以上に増やしてください。
ifconfig eth0 txqueuelen 5000
echo "/sbin/ifconfig eth0 txqueuelen 5000" >> /etc/rc.local
net.core.netdev_max_backlog
同様にとの値を上げますnet.ipv4.tcp_max_syn_backlog
。デフォルト値はそれぞれ 1000 と 1024 です。
sysctl net.core.netdev_max_backlog=2000
sysctl net.ipv4.tcp_max_syn_backlog=2048
ここで、シェルで FD ulimts を増やして、クライアント側とサーバー側の両方のアプリケーションを開始することを忘れないでください。
上記のほかに、プログラマーが使用するもう 1 つの一般的な手法は、 tcp 書き込み呼び出しの数を減らすことです。私自身の好みは、クライアントに送信したいデータをプッシュするバッファを使用し、適切な時点でバッファリングされたデータを実際のソケットに書き出すことです。この手法により、大きなデータ パケットを使用し、断片化を減らし、ユーザー ランドとカーネル レベルの両方で CPU 使用率を減らすことができます。
接続の最大数を設定する変数がいくつかあります。ほとんどの場合、最初にファイル番号が不足しています。確認してくださいulimit -n
。その後、 に設定がありますが/proc
、それらはデフォルトで数万に設定されています。
さらに重要なことに、何か間違ったことをしているように聞こえます。1 つの TCP 接続で、2 つのパーティ間のすべての帯域幅を使用できる必要があります。そうでない場合:
ping -s 1472
...)tc
iperf
多分私は誤解しました。おそらく、Bittorrent のような、多くの接続が必要な作業を行っていると思います。その場合は、実際に使用している接続数を把握する必要があります (netstat
またはを試してくださいlsof
)。その数がかなりの場合、次のことを行うことができます。
ulimit -n
。それでも、約 1000 接続 (私のシステムのデフォルト) はかなりの数です。iostat -x
か?また、コンシューマー グレードの NAT ルーター (Linksys、Netgear、DLink など) を使用している場合は、何千もの接続でその能力を超える可能性があることに注意してください。
これが何らかの助けになることを願っています。あなたは本当にネットワーキングの質問をしています。
derobert の回答を改善するには、
nf_conntrack_max を cat することで、OS 接続の制限を判断できます。
例: cat /proc/sys/net/netfilter/nf_conntrack_max
次のスクリプトを使用して、特定の範囲の tcp ポートへの tcp 接続の数をカウントできます。デフォルトでは 1 ~ 65535 です。
これにより、OS の接続制限を超えているかどうかを確認できます。
これがスクリプトです。
#!/bin/bash
OS=$(uname)
case "$OS" in
'SunOS')
AWK=/usr/bin/nawk
;;
'Linux')
AWK=/bin/awk
;;
'AIX')
AWK=/usr/bin/awk
;;
esac
netstat -an | $AWK -v start=1 -v end=65535 ' $NF ~ /TIME_WAIT|ESTABLISHED/ && $4 !~ /127\.0\.0\.1/ {
if ($1 ~ /\./)
{sip=$1}
else {sip=$4}
if ( sip ~ /:/ )
{d=2}
else {d=5}
split( sip, a, /:|\./ )
if ( a[d] >= start && a[d] <= end ) {
++connections;
}
}
END {print connections}'
アプリケーション レベルで、開発者ができることは次のとおりです。
サーバー側から:
ロード バランサー (ある場合) が正しく動作するかどうかを確認します。
遅い TCP タイムアウトを 503 Fast Immediate 応答に変えます。ロード バランサーが正しく機能している場合、サービスを提供する作業リソースを選択する必要があり、予期しないエラー メッセージでハングアップするよりはましです。
例: ノード サーバーを使用している場合は、npm から toobusy を使用できます。次のような実装:
var toobusy = require('toobusy');
app.use(function(req, res, next) {
if (toobusy()) res.send(503, "I'm busy right now, sorry.");
else next();
});
なぜ503?過負荷に関するいくつかの良い洞察を次に示します: http://ferd.ca/queues-don-t-fix-overload.html
クライアント側でもいくつかの作業を行うことができます。
呼び出しをバッチでグループ化し、クライアントとサーバーのトラフィックと合計要求数を減らすようにしてください。
不要な重複リクエストを処理するためにキャッシュ中間層を構築してみてください。