So testen Sie die maximale Anzahl von TCP-Verbindungen in Linux

So testen Sie die maximale Anzahl von TCP-Verbindungen in Linux

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:
  • Lösung für das Timeout-Problem der TCP-Verbindung unter Linux
  • 2 Befehle zum Überprüfen der TCP-Verbindung unter Linux
  • So verhindern Sie TCP-Flood-Angriffe in Linux

<<:  MySQL-Installations- und Konfigurationsmethoden und Vorsichtsmaßnahmen unter der Windows-Plattform

>>:  So exportieren Sie MySQL-Abfrageergebnisse in CSV

Artikel empfehlen

Beispiel zum Hochladen eines Docker-Images in ein privates Repository

Das Image kann problemlos direkt in das öffentlic...

...

Canvas zeichnet Rubbellos-Effekt

In diesem Artikel wird der spezifische Code zum Z...

So installieren Sie Graphviz und beginnen mit dem Tutorial unter Windows

Herunterladen und installierenUmgebungsvariablen ...

Vue realisiert die Funktion zum Hochladen von Fotos auf den PC

In diesem Artikelbeispiel wird der spezifische Co...

So installieren Sie MySQL 5.7 aus dem Quellcode in einer CentOS 7-Umgebung

Dieser Artikel beschreibt, wie MySQL 5.7 aus dem ...

Implementierung von Single-Div-Zeichentechniken in CSS

Sie können häufig Artikel über das Zeichnen mit C...

Mehrere Methoden zum Ändern des MySQL-Root-Passworts (empfohlen)

Methode 1: Verwenden Sie den Befehl SET PASSWORD ...

Zabbix überwacht den Prozess der Linux-Systemdienste

Zabbix erkennt automatisch Regeln zur Überwachung...

So installieren und implementieren Sie Zabbix 5.0 für Nginx

Inhaltsverzeichnis Experimentelle Umgebung Instal...

Implementierung der K8S-Bereitstellung eines Docker-Containers

Umgebung: (Docker, K8s-Cluster), fahren Sie mit d...