2010-05-14 11 views
36

Ich bin ein Server zu entwerfen, der Millionen von Clients, die gleichzeitig mit dem Server über TCP verbunden sind, dienen muss.Wie behalten Sie eine Million gleichzeitige TCP-Verbindungen?

Der Datenverkehr zwischen dem Server und den Clients ist gering, so dass Bandbreitenprobleme ignoriert werden können.

Eine wichtige Voraussetzung ist, dass immer dann, wenn der Server Daten an einen beliebigen Client senden muss, die vorhandene TCP-Verbindung verwendet werden sollte, anstatt eine neue Verbindung zum Client zu öffnen (weil sich der Client hinter einer Firewall befindet).

Weiß jemand wie man das macht und welche Hardware/Software benötigt wird (zu den geringsten Kosten)?

+2

Muss es TCP sein? Wenn der Verkehr gering ist, können die Kosten für das Verfolgen aller Verbindungen unverhältnismäßig hoch sein. Und könnten Sie ein wenig darüber nachdenken, was der Server tun wird? Millionen aktiver Verbindungen, die nicht aktiv genutzt werden, erscheinen mir verdächtig. – VladV

Antwort

19

Welche Betriebssysteme berücksichtigen Sie dafür?

Wenn Sie ein Windows-Betriebssystem verwenden und etwas später als Vista verwenden, sollten Sie kein Problem mit vielen Tausenden von Verbindungen auf einem einzelnen Computer haben. Ich habe Tests (hier: http://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html) mit einer niedrigen Spezifikation Windows Server 2003-Maschine durchgeführt und leicht mehr als 70.000 aktive TCP-Verbindungen erreicht. Einige der Ressourcenbeschränkungen, die die Anzahl der möglichen Verbindungen beeinflussen, wurden unter Vista erheblich gelockert (siehe hier: http://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html) und Sie könnten Ihr Ziel wahrscheinlich mit einem kleinen Cluster von Maschinen erreichen. Ich weiß nicht, was Sie vor denen brauchen würden, um die Verbindungen zu routen.

Windows bietet eine Einrichtung namens I/O Completion Ports (siehe: http://msdn.microsoft.com/en-us/magazine/cc302334.aspx), mit der Sie viele tausend gleichzeitige Verbindungen mit sehr wenigen Threads bedienen können (Ich habe gestern Tests mit 5000 Verbindungen ausgeführt, die einen Link zu einem Server mit 2 sättigten Threads zur Verarbeitung der E/A ...). Daher ist die grundlegende Architektur sehr skalierbar.

Wenn Sie einige Tests ausführen möchten, dann habe ich einige frei verfügbaren Tools auf meinem Blog, die Ihnen erlauben einen einfachen Echo-Server mit vielen Tausenden von Verbindungen zu dreschen (1) und (2) und einige freie Code, die Sie nutzen könnten (3)

Der zweite Teil Ihrer Frage, aus Ihren Kommentaren, ist komplizierter. Wenn sich die IP-Adresse des Clients ständig ändert und nichts zwischen Ihnen und Ihnen liegt, die NAT für eine konsistente IP-Adresse bereitstellen, werden die Verbindungen ohne Zweifel beendet und müssen neu eingerichtet werden. Wenn die Clients feststellen, dass diese Verbindung abreißt, wenn sich ihre IP-Adresse ändert, können sie sich wieder mit dem Server verbinden. Wenn sie dies nicht können, würde ich vorschlagen, dass die Clients den Server ab und zu abfragen müssen, um den Verbindungsverlust zu erkennen erneut verbinden. Es gibt nichts, was der Server hier tun kann, da er die neue IP-Adresse nicht vorhersagen kann und er erkennt, dass die alte Verbindung beim Versuch, Daten zu senden, fehlgeschlagen ist.

Und denken Sie daran, Ihre Probleme beginnen gerade erst, wenn Sie Ihr System auf dieser Ebene zu skalieren bekommen ...

+1

Ihr EchoServerTest ist in Ordnung, aber wie können wir über 64k Verbindungen testen? Client hat 64 KB Portlimit – onmyway133

+1

Mehrere Clientcomputer. Sie müssen dies zur Zeit manuell tun, da ich keinen Netzwerk-Client-Test schreiben muss, der von einer einzigen Maschine mit Slaves auf anderen Maschinen ausgeführt werden kann (es steht auf meiner Liste der Dinge, die ich tun muss ...). –

+1

Unter Linux können Sie auch die Alias-IP-Adressen auf einem Client-Rechner verwenden; Mit jedem Alias-IP erhalten Sie zusätzliche 65.000 Clients. –

11

Dieses Problem hängt mit dem sogenannten C10K Problem zusammen. Die C10K-Seite listet eine große Anzahl an guten Ressourcen zum Beheben der Probleme auf, die auftreten, wenn Sie versuchen, mehreren tausend Clients die Verbindung mit demselben Server zu ermöglichen.

+0

danke für die Antwort. aber ich persönlich denke nicht, dass sie das gleiche Problem sind. Was ich wissen möchte ist, wie man 1M verbundene Clients dauerhaft verbunden hält, NICHT, wie man ihre Verbindungsanforderungen akzeptiert oder wie man ihre Verbindungsstatusänderung erkennt. danke trotzdem. – cow

+0

@cow: Es ist nicht besonders schwierig, die Clients verbunden zu halten - was lässt dich glauben, dass es da wäre? Es ist bei weitem nicht der schwierigste Teil des Problems. – caf

+0

Was ist, wenn sich die Clients in einem Netzwerk befinden, in dem ihre IPs häufig geändert werden? Zum Beispiel habe ich ein T-Mobile G1 Telefon. Ich habe festgestellt, dass sich die IP-Adresse meines Telefons häufig ändert.Selbst wenn das Telefon eine TCP-Verbindung zu einem Server außerhalb des T-Moble-Netzwerks hat, ist die Wahrscheinlichkeit, dass die IP-Adresse des Telefons geändert wird, groß, wenn keine Daten über die Verbindung fließen. Sobald IP geändert wird, ist jede TCP-Verbindung tatsächlich unterbrochen. Deshalb habe ich das Problem. – cow

-4

EDIT: Wie weiter unten in den Kommentaren erwähnt, meine ursprüngliche Behauptung, dass es eine Grenze von 64 KB auf die Anzahl der Ports ist falsch, aber es ist ein 32K Begrenzung für die Anzahl von Buchse Griffe basiert, so meine vorgeschlagenes Design ist gültig.

Bei einem typischen TCP/IP-Serverdesign ist die Anzahl der gleichzeitig verfügbaren offenen Verbindungen begrenzt. Der Server verfügt über einen Überwachungsport, und wenn ein Client eine Verbindung herstellt, nimmt der Server einen Annahmeaufruf vor und erstellt einen neuen Socket an einem zufälligen Port für den Rest der Verbindung.

Um mehr als 64K gleichzeitige Verbindungen zu handhaben, denke ich, dass Sie stattdessen UDP verwenden müssen. Sie benötigen nur einen Port für den Server, den Sie überwachen müssen, und Sie müssen die Verbindungen mithilfe einer 32-Bit-Client-ID in den Paketdaten verwalten, anstatt einen separaten Port für jeden Client zu verwenden. Die 32-Bit-Client-ID kann die IP-Adresse des Clients sein, und der Client kann auf einem bekannten UDP-Port auf Nachrichten warten, die vom Server zurückkommen. Dieser Port ist der einzige, der auf der Firewall geöffnet sein muss.

Bei diesem Ansatz besteht Ihre einzige Einschränkung darin, wie schnell UDP-Nachrichten verarbeitet und beantwortet werden können. Bei Millionen von Clients kann selbst spärlicher Datenverkehr zu großen Spitzen führen. Wenn Sie die Pakete nicht schnell genug lesen, füllt sich die Eingabewarteschlange und Sie werden Pakete löschen. Die C10K-Seite, auf die Greg verweist, wird Ihnen Strategien dafür geben.

+1

Mehrere Client-Verbindungen zu einem Server verwenden keine zusätzlichen * Server * -Ports. Es wird immer noch technische Einschränkungen geben, aber es ist nicht die Anzahl der Ports. Verbindungen werden auf der Serverseite mit dem eindeutigen 4-Tupel identifiziert (server_ip, server_port, client_ip, client_port). Vielleicht denken Sie an die * Socket-Handles *, bei denen ein Server-Socket anscheinend mehr Socket-Handles durch den 'accept()' -Aufruf erzeugt. –

+0

Hmm. Ja, ich denke du hast Recht. http://linux.die.net/man/2/accept sagt akzeptieren wird fehlschlagen, wenn Sie keine Dateideskriptoren, keine Ports. Ich habe einen Blick in den Quellcode des Linux-Kernels geworfen, und von dem, was ich sagen kann, wird die maximale Anzahl von Dateien als int weitergegeben. Das beschränkt Sie wahrscheinlich auf 32K-Dateideskriptoren, obwohl dies von Plattform zu Plattform variiert. Ich bin falsch in den Details, warum TCP begrenzt ist, aber ich denke, es ist immer noch begrenzt und UDP ist eine praktikable Alternative. – DougWebb

+0

danke für Kommentare von euch beiden. Ich sah die c10k Seite Wochen. Ich erinnere mich, dass es epoll() vorgeschlagen hat. Ich wünschte, ich könnte es mit UDP verwenden. wie auch immer, wie ich weiß, ist epoll irrelevant für einen UDP-Server, der nur einen Socket zu empfangen hat, bin ich richtig? Die Dringlichkeit, Pakete schnell genug zu lesen, ist gültig. Ich kann mir jedoch keinen besseren Weg vorstellen, schneller zu lesen, als einen dedizierten Thread zu verwenden, um Pakete vom UDP-Socket zu lesen und sie in eine Warteschlange für Worker-Threads zu setzen, um sie zu verbrauchen. Könnten Sie bessere Methoden empfehlen? Vielen Dank im Voraus. – cow

4

Ich bin auf die APE Project vor einer Weile gestoßen. Es scheint, als würde ein Traum wahr werden. Sie können bis zu 100.000 gleichzeitige Clients auf einem einzelnen Knoten unterstützen. Verteilen Sie sie auf 10 oder 20 Knoten, und Sie können Millionen bedienen. Perfekt für REST-Anwendungen. Vielleicht möchte ich nach einem freigegebenen Namespace suchen. Ein Nachteil ist, dass dies ein eigenständiger Server ist, wie in Ergänzung zu einem Webserver. Dieser Server ist natürlich Open Source, also sind alle Kosten auf Hardware/ISP bezogen.

+0

danke für die Information. aber meine App ist nicht webbasiert. Wie kann ich APE nutzen? – cow

+0

Sie können APE ohne Browser verwenden. Sie verwenden ein Standardprotokoll (und Sie können Ihr eigenes erstellen: http://www.ape-project.org/wiki/index.php/Protocol) Sie können Ihre eigene Bibliothek schreiben, um Verbindungen mit Ihrer Sprache Ihrer Wahl zu verwalten, indem Sie " APE Javascript Framework "als Referenz. – Vic

+0

danke nochmal. Ich werde in das Protokoll schauen, um zu sehen, ob es gut ist, mein eigenes binärkodiertes Protokoll durch APEs zu ersetzen. – cow

0

Sie nicht UDP verwenden können. Wenn der Client eine Anfrage sendet und Sie nicht sofort antworten, vergisst ein Router die umgekehrte Route in 30 Sekunden oder weniger, so dass Ihr Server niemals auf den Client antworten kann.

TCP ist die einzige Option, und es wird Ihnen Kopfschmerzen bereiten. Die meisten Router werden die Route vergessen und/oder die Verbindung nach ein paar Minuten abbrechen, so dass Ihr Client/Server-Code ziemlich oft "keep alives" senden muss.

Ich empfehle die Einrichtung eines "Sniffer", um zu sehen, wie die Telefongesellschaften in Kontakt bleiben mit Ihrem Smartphone für ihre "Push" -Technologie. Kopieren Sie, was auch immer sie tun, denn das Zeug funktioniert!

0

Wie von Greg erwähnt, ist das Problem, das Sie beschreiben, C10K (oder besser "C1M" in Ihrem Fall) Ich habe vor kurzem einen einfachen TCP-Echo-Server unter Linux, der sehr gut mit der Anzahl der Sitzungen skaliert (nur bis getestet) 200.000), indem die Warteschlange epoll verwendet wird. Auf BSD haben Sie etwas ähnliches namens kqueue. Sie können die code überprüfen, wenn Sie möchten. Hoffe das hilft und viel Glück!

Verwandte Themen