2009-04-17 7 views
22

Ich habe ein sehr einfaches Programm in 5 min geschrieben, das einen Server-Socket öffnet und die Anforderung durchläuft und die gesendeten Bytes an den Bildschirm ausgibt.Gibt es eine Grenze für die Anzahl der TCP/IP-Verbindungen zwischen Maschinen unter Linux?

Ich versuchte dann zu Benchmark, wie viele Verbindungen ich es hämmern kann, um herauszufinden, wie viele gleichzeitige Benutzer ich mit diesem Programm unterstützen kann.

Auf einem anderen Rechner (wo das Netzwerk zwischen ihnen nicht gesättigt ist) habe ich ein einfaches Programm erstellt, das in eine Schleife geht und sich mit dem Server verbindet und die Bytes "Hallo Welt" sendet.

Wenn die Schleife 1000-3000 ist, endet der Client mit allen gesendeten Anforderungen. Wenn die Schleife über 5000 hinausgeht, beginnt sie nach Ablauf der ersten X-Anzahl von Anforderungen Zeitüberschreitungen zu haben. Warum ist das? Ich habe sichergestellt, dass ich meine Steckdose in der Schleife schließe.

Können Sie innerhalb eines bestimmten Zeitraums nur so viele Verbindungen erstellen?

Ist diese Grenze nur zwischen den gleichen Maschinen anwendbar und ich muss mich nicht darum kümmern, wenn 5000+ Anfragen von verschiedenen Maschinen kommen?

+0

Sie Ihre Sockets ss es Befehl überwachen können. Und folgen Sie den Schritten, um Socket Limit zu erhöhen, falls erforderlich – Antarus

+0

Sie können TIMED_WAIT Sockets wie: 's = socket.socket (socket.AF_INET, socket.SOCK_STREAM, 0)' 's wiederverwenden.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ' – knutole

Antwort

24

Es gibt ein Limit, ja. Siehe ulimit.

Auch Sie müssen den TIMED_WAIT Zustand betrachten. Sobald ein TCP-Socket geschlossen ist (standardmäßig) bleibt der Port besetzt in TIMED_WAIT Status für 2 Minuten. Dieser Wert ist einstellbar. Dies wird dir auch "aus den Socken rennen", obwohl sie geschlossen sind.

Führen Sie netstat, um die TIMED_WAIT Sachen in Aktion zu sehen.

P.S. Der Grund für TIMED_WAIT ist, den Fall von Paketen zu behandeln, die ankommen, nachdem der Socket geschlossen wurde. Dies kann passieren, weil Pakete verzögert sind oder die andere Seite nicht weiß, dass der Socket bereits geschlossen wurde. Dies ermöglicht dem OS, diese Pakete im Hintergrund zu löschen, ohne eine andere, nicht verwandte Socket-Verbindung "infizieren" zu können.

+0

Ich habe gerade mit netstat auf beiden Maschinen überprüft, und es gibt tatsächlich eine Tonne von TIMED_WAIT auf der Client-Seite, aber keine TIMED_WAIT auf der Serverseite. Ist das das Verhalten, das du beschreibst? Angenommen, ja: 1) Bedeutet dies, dass dies kein Problem in der Produktion sein wird, da das Limit von der Client-Seite zu kommen scheint (kein Socket) und nicht von der Server-Seite (wo keine Sockets erstellt werden) 2) Gibt es eine Möglichkeit, dies zu umgehen, damit ich meinen Server mit einer produktionsähnlichen Auslastung testen kann? – erotsppa

+0

Das Verhalten von TIMED_WAIT ist Betriebssystem-spezifisch. Ja, Sie können es umgehen - es ist möglich, das TIMED_WAIT-Zeitlimit zu ändern, z. von 120 Sekunden bis 30 oder noch weniger. –

+0

ulimit zeigt mir "unlimited" ... aber ich glaube nicht, dass es unbegrenzt ist ... – trillions

1

Vielleicht möchten Sie überprüfen /etc/security/limits.conf

8

Wenn Sie nach der maximalen Leistung suchen, stoßen Sie auf viele Probleme und potenzielle Engpässe. Wenn Sie einen einfachen Hallo-Welt-Test ausführen, werden Sie nicht unbedingt alle finden.

Mögliche Einschränkungen sind:

  • Kernel Buchse Einschränkungen: für viele Kernel-Tuning in /proc/sys/net aussehen ..
  • Prozessgrenzen: Check out ulimit wie andere hier
  • erklärt haben, wie Ihre Anwendung in wächst Komplexität, kann es nicht genug CPU-Leistung haben, um mit der Anzahl der eingehenden Verbindungen Schritt zu halten. Verwenden Sie top, um zu sehen, ob Ihre CPU maximal ist
  • Anzahl der Threads? Ich habe keine Erfahrung mit Threading, aber dies kann in Verbindung mit den vorherigen Elementen ins Spiel kommen.
2

Ist Ihr Server single-threaded? Wenn ja, welche Polling/Multiplexing-Funktion verwenden Sie?

Die Verwendung von select() funktioniert nicht über die festgeschriebene maximale Dateideskriptorgrenze hinaus, die zur Kompilierungszeit festgelegt wurde, was hoffnungslos ist (normalerweise 256 oder ein paar mehr).

poll() ist besser, aber Sie werden mit dem Skalierbarkeitsproblem mit einer großen Anzahl von FDs enden, die den Satz jedes Mal um die Schleife auffüllen.

epoll() sollte gut bis zu einem anderen Limit funktionieren, das Sie getroffen haben.

10k Verbindungen sollten einfach genug sein, um zu erreichen. Verwenden Sie einen aktuellen (ish) 2.6-Kernel.

Wie viele Client-Computer haben Sie verwendet? Sind Sie sicher, dass Sie kein clientseitiges Limit erreicht haben?

+0

Auf meinem System war das Limit 1024, und es ist in der Tat unmöglich, darüber hinauszugehen (das Limit wird durch einen Datentyp auferlegt, der die Karte der zu beobachtenden Dateideskriptoren). –

2

Die schnelle Antwort ist 2^16 TCP-Ports, 64K.

Die Probleme mit systembedingten Grenzwerten sind ein Konfigurationsproblem, das bereits in früheren Kommentaren angesprochen wurde.

Die internen Auswirkungen auf TCP ist nicht so klar (für mich). Jeder Port benötigt Speicher für seine Instanziierung, geht auf eine Liste und benötigt Netzwerkpuffer für Daten, die übertragen werden.

Angesichts 64K TCP-Sitzungen der Aufwand für Instanzen der Ports möglicherweise ein Problem auf einem 32-Bit-Kernel, aber nicht ein 64-Bit-Kernel (Korrektur hier gerne akzeptiert). Der Nachschlagevorgang mit 64K-Sitzungen kann die Vorgänge etwas verlangsamen und jedes Paket trifft auf die Zeitgeberwarteschlangen, was ebenfalls problematisch sein kann. Speicher für Transit-Daten kann theoretisch auf die Fenstergröße Zeiten Ports (vielleicht 8 GByte) anschwellen.

Das Problem mit der Verbindungsgeschwindigkeit (oben erwähnt) ist wahrscheinlich, was Sie sehen. TCP braucht normalerweise Zeit, um Dinge zu tun. Es ist jedoch nicht erforderlich. Ein TCP-Connect, Transact und Disconnect kann sehr effizient durchgeführt werden (überprüfen Sie, wie die TCP-Sitzungen erstellt und geschlossen werden).

Es gibt Systeme, die Dutzende von Gigabits pro Sekunde übertragen, daher sollte die Skalierung auf Paketebene in Ordnung sein.

Es gibt Maschinen mit viel physischem Speicher, so dass es OK aussieht.

Die Leistung des Systems, wenn sorgfältig konfiguriert, sollte in Ordnung sein.

Die Server-Seite der Dinge sollte in ähnlicher Weise skalieren.

Ich wäre besorgt über Dinge wie Speicherbandbreite.

Betrachten Sie ein Experiment, bei dem Sie sich 10.000 Mal beim lokalen Host anmelden. Dann tippe ein Zeichen ein. Der gesamte Stapel durch den Benutzerraum würde an jedem Zeichen beteiligt sein. Der aktive Footprint würde wahrscheinlich die Datencache-Größe überschreiten. Das Durchlaufen von viel Speicher kann das VM-System belasten. Die Kosten für Kontextwechsel könnten sich einer Sekunde nähern!

Dies wird in einer Vielzahl von anderen Themen diskutiert: https://serverfault.com/questions/69524/im-designing-a-system-to-handle-10000-tcp-connections-per-second-what-problems

Verwandte Themen