LinuxでのTCP / IP接続の最大数の増加


214

サーバーをプログラミングしていますが、接続数を「無制限」に設定しても帯域幅が飽和しないため、接続数が制限されているようです。

Ubuntu Linuxボックスが一度に開くことができる接続の最大数を増加または排除するにはどうすればよいですか?OSはこれを制限しますか、それともルーターまたはISPですか?それとも別のものですか?


2
@Software Monkey:とにかく答えました。将来的に実際にサーバーを作成している人に役立つと思います。
デロベルト09年

1
@derobert:私はその+1を見ました。実は前回のコメントも同じように思いましたが、コメントはそのままにしておこうと思いました。
Lawrence Dol、

回答:


395

接続の最大数は、少し異なりますが、クライアント側とサーバー側の両方の特定の制限の影響を受けます。

クライアント側: 境界ポート範囲を増やし、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 = 4701秒あたりのソケット数以上を一貫して保証できないことを意味します。これに満足できない場合は、を増やすことから始めることができますport_range15000 61000最近では、範囲をに設定するのが一般的です。を減らすことで、可用性をさらに高めることができますfin_timeout。両方を行うとすると、1秒あたり1500以上の送信接続がより簡単に表示されるはずです。

値を変更するには

sysctl net.ipv4.ip_local_port_range="15000 61000"
sysctl net.ipv4.tcp_fin_timeout=30

上記は、1秒あたりの発信接続を行うためのシステム機能に影響を与える要素として解釈されるべきではありません。しかし、むしろこれらの要因は、長期間の「アクティビティ」の間、持続的な方法で同時接続を処理するシステムの能力に影響を与えます。

以下のための一般的なLinuxボックス上のsysctl値をデフォルトtcp_tw_recycletcp_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の要素を増やして、クライアント側とサーバー側の両方のアプリケーションを起動することを忘れないでください。

上記に加えて、プログラマが使用するもう1つの一般的な手法は、tcp書き込み呼び出しの数を減らすことです。私の好みは、クライアントに送信するデータをプッシュするバッファーを使用し、適切な時点で、バッファーされたデータを実際のソケットに書き込むことです。この手法により、大きなデータパケットを使用し、断片化を減らし、ユーザーランドとカーネルレベルの両方でCPU使用率を減らすことができます。


4
素晴らしい答え!私の問題は少し異なりました。つまり、セッション情報をアプリケーションレベルのセッションストレージからPHP経由でredisに移動しようとしていました。どういうわけか、私は一度にたくさんの睡眠を追加せずに28230を超えるセッションを追加することができませんでした。問題がphp / redisにあるのではなく、2つを接続するtcp / ipレイヤーにあると私が思うまで、1日中頭を悩ませて、この答えにたどり着きました。その後すぐに問題を解決することができました:)ありがとうございました!
s1d 2013

27
私たちは常にIP + portについて話していることを忘れないでください。多くの異なるIPからポートXYに「無制限」のソケットを開くことができます。制限470は、同じIPに対して同時に開かれたソケットにのみ適用されます。別のIPは、同じポートへの独自の470接続を持つことができます。
Marki555 2014年

6
@ Marki555:あなたのコメントは非常に正しいです。多数のアウトバウンド接続を生成および維持するために開発されたアプリケーションは、アウトバウンド接続を作成するために使用可能なIPを「認識」し、何らかの「ラウンドロビンアルゴリズム」を使用してこれらのIPアドレスに適切にバインドし、維持する必要があります。 「スコアボード」。
mdk 2014年

8
この答えには間違いがあります。まず、net.ipv4.tcp_fin_timeoutはFIN_WAIT_2状態(cs.uwaterloo.ca/~brecht/servers/ip-sysctl.txt専用です。次に、@ Ericが言ったように、「いつでも470ソケット」は正しくありません。
Sharvanath 2014年

3
@mdk:この計算の部分ははっきりしません(61000 - 32768) / 60 = 470 sockets per second。これについて詳しく説明していただけますか?
トムテイラー

64

接続の最大数を設定するいくつかの変数があります。ほとんどの場合、最初にファイル番号が不足しています。ulimit -nを確認してください。その後、/ procに設定がありますが、デフォルトでは数万に設定されています。

さらに重要なことに、何か間違ったことをしているようです。1つのTCP接続で、2つのパーティ間のすべての帯域幅を使用できる必要があります。そうでない場合:

  • TCPウィンドウ設定が十分に大きいかどうかを確認します。Linuxのデフォルトは、本当に高速なinetリンク(数百mbps)または高速な衛星リンクを除くすべてに適しています。あなたの帯域幅*遅延製品は何ですか?
  • 大きなパケットでpingを使用してパケット損失を確認します(ping -s 1472...)
  • レート制限を確認します。Linuxでは、これはtc
  • 存在すると思われる帯域幅が実際に存在することを確認するには、たとえば、 iperf
  • プロトコルが正しいことを確認します。待ち時間を覚えておいてください。
  • これがGigabit + LANの場合、ジャンボパケットを使用できますか?あなたは?

誤解しているのかもしれません。たぶん、あなたはたくさんの接続が必要なビットトレントのようなことをしているでしょう。その場合は、実際に使用している接続の数を確認する必要があります(netstatまたはを試してくださいlsof)。その数が多い場合は、次のことが考えられます。

  • 100mbps以上など、帯域幅を十分に確保します。この場合、実際にはをアップする必要がありますulimit -n。それでも、1000接続(私のシステムのデフォルト)はかなりの数です。
  • 接続を遅くしているネットワークの問題(たとえば、パケット損失)がある
  • 特にIO帯域幅など、特に必要な場合は、何かを遅くしてください。確認しましたiostat -xか?

また、コンシューマーグレードのNATルーター(Linksys、Netgear、DLinkなど)を使用している場合は、何千もの接続でその能力を超える可能性があることに注意してください。

これが何らかの助けとなることを願っています。あなたは本当にネットワーキングの質問をしています。


16

デロバートの答えを改善するために、

nf_conntrack_maxをキャッチすることで、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}'

3
which awkawkへのパスを決定するあなたの友達です
。SunOS

2
@PanagiotisM。完全なパスを提供する代わりに使用することができる場合which、プログラムに依存しています。(とはいえ、スクリプト内のソリューションが完全に近いかどうかはわかりませんが、これがスクリプトの目的ではありません)。PATHawk
マイケルクレリン-ハッカー、2014年

5
このスクリプトがどのように弾道を決めてawk場所を決定するかが気に入っていますが、シェルは常にあると想定しています/bin/bash (プロヒント:デフォルトでは、AIX5 / 6にはbashさえありません)。
kubanczyk 2016年

あるawk検出が便利?個人的に私は単純に正しいを持つことが前提となりPATHますが、合理的な選択肢が考えられ/usr/bin/env awkそして/usr/bin/env bashそれぞれ。それが価値があるのは、私のLinuxシステムの場所が間違っていることです。それは/usr/bin/awkない/bin/awk
Wolph

1
このスクリプトを実行すると798になるので、どういう意味ですか?

10

アプリケーションレベルで、開発者ができることは次のとおりです。

サーバー側から:

  1. ロードバランサー(ある場合)が正しく動作するかどうかを確認します。

  2. 遅いTCPタイムアウトを503 Fast Immediate応答に変換します。ロードバランサーが正しく機能している場合、サービスする作業リソースを選択する必要があり、予期しないエラーマッサージでハングするよりも優れています。

例:ノードサーバーを使用している場合、uは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

クライアント側でもいくつかの作業を行うことができます。

  1. 呼び出しをバッチでグループ化し、トラフィックとリクエストの総数をクライアントとサーバーの数で減らします。

  2. 不要な重複リクエストを処理するために、キャッシュの中間層を構築してみてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.