web-dev-qa-db-ja.com

Linuxでのtcp / ip接続の最大数を増やします

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

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

182
jbu

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

クライアント側:サーマルポートの範囲を広げ、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個以上のソケットを一貫して保証できないことを意味します。あなたがそれに満足していないのなら、あなたは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およびtcp_tw_reuseの一般的なLinuxボックスのデフォルトのSysctl値は次のようになります。

net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_tw_reuse=0

これらは "待機"状態の "used"ソケットからの接続を許可せず、ソケットに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 deviceの背後にある2台の異なるコンピュータからの接続を処理しないため、一般向けのサーバーでは非常に問題があります。噛むnet.ipv4.tcp_tw_recycleはLinux4.12から 削除 されています。

サーバー側:net.core.somaxconn値は重要な役割を果たします。待機ソケットに対してキューに入れられる要求の最大数を制限します。サーバーアプリケーションの機能が確実な場合は、デフォルトの128から128から1024のような値に増やしてください。これで、アプリケーションのlisten呼び出しのlisten backlog変数を同等またはそれ以上の整数に変更することで、この増加を利用できます。

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_backlognet.ipv4.tcp_max_syn_backlogの値を増やします。デフォルト値はそれぞれ1000と1024です。

sysctl net.core.netdev_max_backlog=2000
sysctl net.ipv4.tcp_max_syn_backlog=2048

シェルでFD ulimtを増やして、クライアント側とサーバー側の両方のアプリケーションを起動することを忘れないでください。

プログラマーによって使用される上記の1つのよりポピュラーなテクニックに加えて、tcp write呼び出しの数を減らすことです。私自身の好みは、私がクライアントに送りたいデータをプッシュし、それから適切な時点でバッファリングされたデータを実際のソケットに書き出すバッファを使うことです。このテクニックを使用すると、大きなデータパケットを使用したり、断片化を減らしたり、ユーザーレベルでもカーネルレベルでもCPU使用率を減らしたりできます。

343
mdk

最大接続数を設定するための変数がいくつかあります。たぶん、あなたは最初にファイル番号を使い果たしています。 ulimit -nを確認してください。その後、/ procに設定がありますが、デフォルトでは何万にも設定されています。

さらに重要なのは、何か問題があるように思われることです。単一のTCP接続は、2者間のすべての帯域幅を使用できるはずです。そうでない場合:

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

おそらく私は誤解しています。多分あなたはたくさんの接続が必要なBittorrentのようなことをしているのでしょう。そうであれば、実際に使用している接続数を把握する必要があります(netstatまたはlsofを試してください)。その数が多い場合は、次のようにします。

  • 多くの帯域幅、例えば100mbps +を持ってください。この場合、実際にはulimit -nを上げる必要があるかもしれません。それでも、〜1000接続(私のシステムのデフォルト)はかなりの数です。
  • あなたの接続を遅くしているネットワークの問題を抱えている(例えばパケットロス)
  • 特にあなたが探している場合はIO帯域幅など、あなたを遅くする何か他のものがあります。 iostat -xをチェックしましたか?

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

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

57
derobert

Derobertによって与えられた答えを改善するために、

あなたはあなたのOS接続制限がnf_conntrack_maxを捕獲することによって何であるか決定することができます。

たとえば、次のようになります。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}'
15
whitehat237

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

サーバー側から:

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

  2. ロードバランサが正しく動作する場合は、slow 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. 不要な重複要求を処理するためにキャッシュ中間層を構築してみてください。

10
Kev