Vorwort Es besteht ein Missverständnis bezüglich der maximalen Anzahl gleichzeitiger Verbindungen eines TCP-Servers: „Da die Obergrenze der Portnummer 65535 ist, beträgt die maximale Anzahl gleichzeitiger Verbindungen, die ein TCP-Server theoretisch ausführen kann, ebenfalls 65535.“ Lassen Sie mich zunächst die Schlussfolgerung ziehen: Bei einem TCP-Serverprozess ist die Anzahl der Clients, mit denen er gleichzeitig eine Verbindung herstellen kann, nicht durch die verfügbaren Portnummern begrenzt. Die Anzahl gleichzeitiger Verbindungen wird durch die Anzahl der Dateien begrenzt, die in Linux geöffnet werden können. Diese Zahl ist konfigurierbar und kann sehr groß sein, sodass sie tatsächlich durch die Systemleistung begrenzt ist. Wenn Sie heutzutage Serverentwicklung ohne hohe Parallelität durchführen, wird es Ihnen peinlich sein, auszugehen. Um in Zukunft auf die Frage anderer, „Sie verbessern die Parallelität jeden Tag, was ist die höchste Parallelität, die Sie erreicht haben?“, richtig antworten zu können, habe ich beschlossen, selbst eine Demo zu schreiben, während ich am Neujahrstag zu Hause war und nichts tat. Dieser Test dient vor allem dazu herauszufinden, welche Parameterkonfigurationen unter Linux die maximale Anzahl an Verbindungen begrenzen und wie hoch die Obergrenze ist. 1. Lassen Sie mich zunächst über die Idee der Demo sprechen: Der Server wird mit epoll implementiert, das lediglich Verbindungen empfängt, und der Client verwendet die Goroutine von Go. Jede Goroutine stellt lediglich eine Verbindung her und tut dann nichts. Oben genannter Code: Server: /* * g++ -o test_epoll ./test_epoll.c */ #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/epoll.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> int SetReuseAddr(int fd) { IntOptVal = 1; socklen_t optlen = Größe von (optval); gibt setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen) zurück; } int main() { int fd = socket(AF_INET, SOCK_STREAM, 0); int iRet = SetReuseAddr(fd); wenn (iRet != 0) { printf("setsockopt für SO_REUSEADDR fehlgeschlagen, Fehler: %s\n", strerror(iRet)); iRet zurückgeben; } Struktur sockaddr_in Adresse; memset(&Adresse, 0, Größe von(Adresse)); Adresse.sin_family = AF_INET; Adresse.sin_port = htons(8080); addr.sin_addr.s_addr = INADDR_ANY; wenn (binden(fd, (Struktur sockaddr*)&addr, sizeof(addr)) == -1) { printf("Binden fehlgeschlagen, Fehler: %s\n", strerror(errno)); Fehlernummer zurückgeben; } wenn (hören(fd, 5) == -1) { printf("Abhören fehlgeschlagen, Fehler: %s\n", strerror(errno)); Fehlernummer zurückgeben; } printf("Abhören auf 8080...\n"); epoll_create(102400); Struktur epoll_event-Ereignis; Ereignis.Ereignisse = EPOLLIN; Ereignis.Daten.fd = fd; epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &Ereignis); Struktur epoll_event revents[102400]; int iOnline = 0; während (1) { In diesem Beispiel wird der epoll_wait-Befehl verwendet, um die Abfrage auszuführen. printf("epoll_wait return %d\n", Zahl); wenn (Zahl > 0) { für (int i = 0; i < num; i++) { wenn (revents[i].data.fd == fd) { int-Client; Struktur sockaddr_in cli_addr; socklen_t cli_addr_len = Größe von (cli_addr); Client = akzeptieren(fd, (Struktur sockaddr*)&cli_addr, &cli_addr_len); wenn (Client == -1) { printf("Akzeptieren fehlgeschlagen, Fehler: %s\n", strerror(errno)); wenn (errno == EMFILE) { printf("Pro-Prozess-Limit erreicht\n"); beenden(Fehlernummer); } wenn (errno == ENFILE) { printf("systemweites Limit erreicht\n"); beenden(Fehlernummer); } weitermachen; } iOnline++; printf("Empfange eine neue Verbindung von %s:%d\n", inet_ntoa(cli_addr.sin_addr), cli_addr.sin_port); Ereignis.Ereignisse = EPOLLIN; Ereignis.Daten.fd = Client; epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &Ereignis); } } } printf("Online-Nummer:%d\n", iOnline); } gebe 0 zurück; } Kunde: Paket Haupt importieren ( "netto" "fmt" "Zeit" "strconv" "Laufzeit" ) Funktion Connect(Host-String, Port-Int) { _, err := net.Dial("tcp", host+":"+strconv.Itoa(port)) wenn err != nil { fmt.Printf("Anruf bei %s:%d fehlgeschlagen\n", Host, Port) zurückkehren } für { Zeit.Schlaf(30 * 1000 * Zeit.Millisekunde) } } Funktion main() { Anzahl := 0 für { gehe zu Verbinden("192.168.63.128", 8080) zählen++; fmt.Printf("Goroutine-Nummer:%d\n", runtime.NumGoroutine()) Zeit.Schlaf(100 * Zeit.Millisekunde) } } 2. Beginnen Sie mit dem Testen Erste: Lassen Sie mich zunächst über das Ergebnis sprechen. Als die Anzahl der Verbindungen 1031 erreichte, schlug die Annahme fehl. Zu diesem Zeitpunkt wurde errno nicht beurteilt, sodass nur der Annahmefehler ausgedruckt wurde. Dann fällt mir als erstes das ulimit -n-Limit ein. Ich habe es überprüft und festgestellt, dass der Standardwert 1024 ist. Dann habe ich diesen Wert geändert und den folgenden Inhalt in /etc/security/limits.conf hinzugefügt: 1 * weiches Nofile 102400 2 * hartes Nofile 102400 Schließen Sie dann die aktuelle Xshell-Verbindung und stellen Sie die Verbindung erneut her, damit die Änderungen wirksam werden. Jetzt ist ulimit -n 102400. Mit diesen beiden Zeilen werden die weichen und harten Grenzen der Anzahl der Datei-Deskriptoren, die jeder Prozess öffnen kann, auf 102.400 angepasst. Hinweis: ulimit -n 102400 kann ebenfalls wirksam sein, aber diese Änderung ist vorübergehend. Machen Sie dann einen zweiten Test. Zweites Mal: Komisch, eigentlich beträgt die Anzahl der Verbindungen nur 2000+. Ich habe mich gefragt, warum die Standardanzahl der Verbindungen in Windows so hoch ist. Es stellte sich heraus, dass einige Verbindungen getrennt wurden, aber da ich nichts getan hatte, dachte ich, sie wären noch da. Es scheint, dass ich eine andere virtuelle Maschine installieren muss [Erha] Fortgesetzt werden. . . Installieren Sie die virtuelle Maschine. Zeit: 2017-12-31 00:09:00 Die virtuelle Maschine ist installiert, dann fahren Sie fort. Dieses Mal waren es tatsächlich mehr als 10.000. Die Zahl der Verbindungen steigt immer noch. Ich bin gespannt, ob sie irgendwann 100.000 erreichen kann. Ich freue mich darauf. Zeit: 31.12.2017 00:41:00, die endgültige Obergrenze bleibt bei 28232 hängen, Golang meldet weiterhin Wählfehler, da ich vergessen habe, die spezifische Fehlermeldung auszudrucken. Ich habe also keine Ahnung, warum die Wahl fehlgeschlagen ist, also kann ich es nur erneut ausführen T_T Zeit: 31.12.2017, 01:01:00 Uhr. Fehlermeldung „Wählfehler“ hinzugefügt, erneut ausgeführt, und bei 28232 ist immer noch ein Wählfehler aufgetreten, mit der Fehlermeldung: In der Standardbibliotheksdokumentation von Golang gibt es keine Erklärung für die Fehlermeldung. Aus der Fehlermeldung geht hervor, dass die Adresszuweisung fehlgeschlagen ist. Daher frage ich mich, ob der Portadressbereich begrenzt ist. Ich habe den Portadressbereich überprüft und festgestellt, dass dies die Einschränkung ist. Da die Portadresse 16 Bit beträgt, können maximal 64521 Verbindungen geöffnet werden, selbst wenn der Portadressbereich auf 1024-65535 geändert wird. Ich habe nur eine virtuelle Maschine als Client, daher ist es unmöglich, 100.000 Verbindungen zu erreichen. Durch diesen Test habe ich jedoch auch herausgefunden, welche Parameter die Obergrenze der Verbindungen begrenzen, was ich auch möchte. Abschließend möchte ich den großartigen Leuten im Linux-Kernel-Team dafür danken, dass sie einen so großartigen Mechanismus wie epoll eingeführt haben, der es uns so einfach macht, eine hohe Parallelität zu erreichen. Ich hoffe, ich kann eines Tages so großartig sein wie sie, haha. Zusammenfassen Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Wenn Sie Fragen haben, können Sie eine Nachricht hinterlassen. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM. Das könnte Sie auch interessieren:
|
>>: So exportieren Sie MySQL-Abfrageergebnisse in CSV
Das Image kann problemlos direkt in das öffentlic...
Ich hatte dieses Problem in letzter Zeit beim Desi...
In diesem Artikel wird der spezifische Code zum Z...
Herunterladen und installierenUmgebungsvariablen ...
In diesem Artikelbeispiel wird der spezifische Co...
Dieser Artikel beschreibt, wie MySQL 5.7 aus dem ...
Sie können häufig Artikel über das Zeichnen mit C...
Empfohlene Artikel: Klicken Sie auf die untere re...
Methode 1: Verwenden Sie den Befehl SET PASSWORD ...
Zabbix erkennt automatisch Regeln zur Überwachung...
Inhaltsverzeichnis Experimentelle Umgebung Instal...
Seien Sie vorsichtig, wenn Sie auf Ereignisse ach...
Projektanforderungen: Wenn Sie auf einen Produktb...
Umgebung: (Docker, K8s-Cluster), fahren Sie mit d...