Socket Accept – “Zu viele offene Dateien”

Lesezeit: 6 Minuten

Scotts Benutzeravatar
Scott

Ich arbeite an einem Schulprojekt, bei dem ich einen Multithread-Server schreiben musste, und jetzt vergleiche ich ihn mit Apache, indem ich einige Tests dagegen durchführe. Ich verwende Autobench, um dabei zu helfen, aber nachdem ich ein paar Tests durchgeführt habe oder wenn ich eine zu hohe Rate (etwa 600+) gebe, um die Verbindungen herzustellen, erhalte ich die Fehlermeldung „Zu viele offene Dateien“.

Nachdem ich mit der Bearbeitung der Anfrage fertig bin, mache ich immer a close() auf der Steckdose. Ich habe versucht, die zu verwenden shutdown() funktionieren auch, aber nichts scheint zu helfen. Irgendwie drum herum?

Es gibt mehrere Stellen, an denen Linux Beschränkungen für die Anzahl der Dateideskriptoren haben kann, die Sie öffnen dürfen.

Sie können Folgendes überprüfen:

cat /proc/sys/fs/file-max

Dadurch erhalten Sie die systemweiten Grenzen von Dateideskriptoren.

Auf der Shell-Ebene wird Ihnen dies Ihr persönliches Limit mitteilen:

ulimit -n

Dies kann in /etc/security/limits.conf geändert werden – es ist der nofile-Parameter.

Wenn Sie Ihre Sockets jedoch korrekt schließen, sollten Sie dies nicht erhalten, es sei denn, Sie öffnen viele gleichzeitige Verbindungen. Es hört sich so an, als ob etwas verhindert, dass Ihre Sockets ordnungsgemäß geschlossen werden. Ich würde überprüfen, ob sie ordnungsgemäß behandelt werden.

  • Benutzername Hard Nofile 20000

    – Linjunhalida

    21. Juli 2011 um 7:39 Uhr

Benutzeravatar von Nick
Nick

Ich hatte ein ähnliches Problem. Schnelle Lösung ist:

ulimit -n 4096

Erklärung ist wie folgt – jede Serververbindung ist ein Dateideskriptor. In CentOS, Redhat und Fedora, wahrscheinlich anderen, ist das Dateibenutzerlimit 1024 – keine Ahnung warum. Es ist leicht zu sehen, wenn Sie Folgendes eingeben: ulimit -n

Beachten Sie, dass dies nicht viel mit Systemmax-Dateien (/proc/sys/fs/file-max) zu tun hat.

In meinem Fall war es ein Problem mit Redis, also habe ich Folgendes getan:

ulimit -n 4096
redis-server -c xxxx

In Ihrem Fall müssen Sie anstelle von Redis Ihren Server starten.

  • Und die Antwort auf ein Speicherleck ist … Mehr Speicher kaufen? Keine Behebung des Dateilecks.

    – Raffael Baptista

    21. Mai 2013 um 15:56 Uhr

  • Anscheinend verstehen Sie das Problem nicht (oder platzieren Sie den Kommentar unter falsche Antwort?). Es hat mit dem Dateideskriptorlimit zu tun und nichts mit Speicher oder Speicherleck.

    – Nick

    21. Mai 2013 um 17:48 Uhr

  • Das Dateilimit ist 1024, da Sie sonst auf eine stoßen grundlegendes Problem mit select().

    – flauschige

    8. August 2014 um 18:40 Uhr

  • @RafaelBaptista In manchen Fällen wird tatsächlich eine große Anzahl gleichzeitiger Verbindungen benötigt, wie zum Beispiel ein Hochleistungs-Chat-Server. Dabei muss es sich nicht um undichte FDs handeln.

    – Antwan van Houdt

    3. Juni 2016 um 10:43 Uhr

  • @RafaelBaptista: Wenn Sie einen Server haben, der mehr als 512 parallele Verbindungen verarbeiten kann, benötigen Sie VIEL MEHR offene Dateien. Moderne Server können mehrere Millionen parallele Verbindungen verarbeiten, sodass ein Limit von nur 1024 wirklich keinen Sinn macht. Es könnte für gelegentliche Benutzer als Standardlimit in Ordnung sein, aber nicht für Serversoftware, die parallele Clientverbindungen verarbeitet.

    – Mikko Rantalainen

    7. April 2020 um 7:06 Uhr


TCP hat eine Funktion namens “TIME_WAIT”, die sicherstellt, dass Verbindungen sauber geschlossen werden. Es erfordert, dass ein Ende der Verbindung noch eine Weile zuhört, nachdem der Socket geschlossen wurde.

Bei einem Hochleistungsserver ist es wichtig, dass die Clients in TIME_WAIT gehen, nicht der Server. Clients können es sich leisten, einen Port offen zu haben, während einem ausgelasteten Server schnell die Ports ausgehen oder zu viele offene FDs haben.

Um dies zu erreichen, sollte der Server die Verbindung nie zuerst schließen – er sollte immer warten, bis der Client sie schließt.

  • Nein. TCP TIME_WAIT hält Sockets auf Betriebssystemebene offen und veranlasst schließlich den Server, eingehende Verbindungen abzulehnen. Wenn Sie das Dateihandle schließen, wird es geschlossen. stackoverflow.com/questions/1803566/…

    – Raffael Baptista

    21. Mai 2013 um 15:57 Uhr

  • Es ist wahr, dass das Dateihandle sofort geschlossen wird und ich mich falsch ausgedrückt habe. Aber mein Hauptargument bleibt bestehen, denn obwohl der FD freigegeben wird, bleibt der TCP-Port während TIME_WAIT zugewiesen, und einem ausgelasteten Server können die TCP-Ports ausgehen oder zu viel Kernel-Speicher für die Verfolgung dieser Ports verwendet werden.

    – Ed4

    8. April 2015 um 17:10 Uhr

Benutzeravatar von Edson Medina
Edson Medina

Verwenden lsof -u `whoami` | wc -l um herauszufinden, wie viele offene Dateien der Benutzer hat

shilovks Benutzeravatar
Schilowk

Dies bedeutet die maximale Anzahl gleichzeitig geöffneter Dateien.

Gelöst:

Am Ende der Datei /etc/security/limits.conf Sie müssen die folgenden Zeilen hinzufügen:

* soft nofile 16384
* hard nofile 16384

In der aktuellen Konsole von root (sudo funktioniert nicht) zu tun:

ulimit -n 16384

Obwohl dies optional ist, wenn es möglich ist, den Server neu zu starten.

Im /etc/nginx/nginx.conf Datei, um den neuen Wert zu registrieren worker_connections gleicht 16384 durch Wert dividieren worker_processes.

Wenn nicht ulimit -n 16384muss neu gestartet werden, dann wird das Problem zurückgehen.

PS:

Wenn nach der Reparatur in den Protokollen sichtbar ist error accept() failed (24: Too many open files):

In der Nginx-Konfiguration Propevia (zum Beispiel):

worker_processes 2;

worker_rlimit_nofile 16384;

events {
  worker_connections 8192;
}

Benutzeravatar von Rafael Baptista
Raffael Baptista

Ich hatte dieses Problem auch. Sie haben ein Dateihandle-Leck. Sie können dies debuggen, indem Sie eine Liste aller offenen Dateihandles ausdrucken (auf POSIX-Systemen):

void showFDInfo()
{
   s32 numHandles = getdtablesize();

   for ( s32 i = 0; i < numHandles; i++ )
   {
      s32 fd_flags = fcntl( i, F_GETFD ); 
      if ( fd_flags == -1 ) continue;


      showFDInfo( i );
   }
}

void showFDInfo( s32 fd )
{
   char buf[256];

   s32 fd_flags = fcntl( fd, F_GETFD ); 
   if ( fd_flags == -1 ) return;

   s32 fl_flags = fcntl( fd, F_GETFL ); 
   if ( fl_flags == -1 ) return;

   char path[256];
   sprintf( path, "/proc/self/fd/%d", fd );

   memset( &buf[0], 0, 256 );
   ssize_t s = readlink( path, &buf[0], 256 );
   if ( s == -1 )
   {
        cerr << " (" << path << "): " << "not available";
        return;
   }
   cerr << fd << " (" << buf << "): ";

   if ( fd_flags & FD_CLOEXEC )  cerr << "cloexec ";

   // file status
   if ( fl_flags & O_APPEND   )  cerr << "append ";
   if ( fl_flags & O_NONBLOCK )  cerr << "nonblock ";

   // acc mode
   if ( fl_flags & O_RDONLY   )  cerr << "read-only ";
   if ( fl_flags & O_RDWR     )  cerr << "read-write ";
   if ( fl_flags & O_WRONLY   )  cerr << "write-only ";

   if ( fl_flags & O_DSYNC    )  cerr << "dsync ";
   if ( fl_flags & O_RSYNC    )  cerr << "rsync ";
   if ( fl_flags & O_SYNC     )  cerr << "sync ";

   struct flock fl;
   fl.l_type = F_WRLCK;
   fl.l_whence = 0;
   fl.l_start = 0;
   fl.l_len = 0;
   fcntl( fd, F_GETLK, &fl );
   if ( fl.l_type != F_UNLCK )
   {
      if ( fl.l_type == F_WRLCK )
         cerr << "write-locked";
      else
         cerr << "read-locked";
      cerr << "(pid:" << fl.l_pid << ") ";
   }
}

Indem Sie alle geöffneten Dateien ausgeben, werden Sie schnell herausfinden, wo sich Ihr Datei-Handle-Leck befindet.

Wenn Ihr Server Unterprozesse erzeugt. Wenn dies zB ein ‘Fork’-Server ist oder wenn Sie andere Prozesse spawnen (zB über cgi), müssen Sie sicherstellen, dass Sie Ihre Dateihandles mit “cloexec” erstellen – sowohl für echte Dateien als auch für Sockets.

Ohne cloexec werden jedes Mal, wenn Sie forken oder spawnen, alle offenen Datei-Handles im untergeordneten Prozess geklont.

Es ist auch sehr einfach, Netzwerk-Sockets nicht zu schließen – z. B. wenn sie einfach aufgegeben werden, wenn die Gegenstelle die Verbindung trennt. Dadurch werden Griffe wie verrückt auslaufen.

Benutzeravatar von letanthang
letanthang

Zeigen Sie unter MacOS die Grenzen an:

launchctl limit maxfiles

Ergebnis wie: maxfiles 256 1000

Wenn die Zahlen (Soft Limit & Hard Limit) zu niedrig sind, müssen Sie nach oben setzen:

sudo launchctl limit maxfiles 65536 200000

1419650cookie-checkSocket Accept – “Zu viele offene Dateien”

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy