Question Socket accept - "Trop de fichiers ouverts"


Je travaille sur un projet d'école où je devais écrire un serveur multi-thread, et maintenant je le compare à Apache en effectuant des tests. J'utilise l'autobench pour aider avec cela, mais après quelques tests, ou si je lui donne un taux trop élevé (environ 600+) pour établir les connexions, j'obtiens une erreur "Trop de fichiers ouverts".

Après avoir fini de traiter la demande, je fais toujours un close() sur la prise J'ai essayé d'utiliser le shutdown() fonction aussi, mais rien ne semble aider. Un moyen de contourner cela?


46
2018-05-19 01:15


origine


Réponses:


Il y a plusieurs endroits où Linux peut avoir des limites sur le nombre de descripteurs de fichiers que vous êtes autorisé à ouvrir.

Vous pouvez vérifier les éléments suivants:

cat /proc/sys/fs/file-max

Cela vous donnera les limites du système pour les descripteurs de fichiers.

Au niveau du shell, cela vous indiquera votre limite personnelle:

ulimit -n

Cela peut être changé dans /etc/security/limits.conf - c'est le paramètre nofile.

Cependant, si vous fermez correctement vos prises, vous ne devriez pas recevoir ceci à moins que vous ouvriez beaucoup de connexions simultanées. Il semble que quelque chose empêche vos prises de se fermer correctement. Je vérifierais qu'ils sont traités correctement.


49
2018-05-19 01:20



J'ai eu un problème similaire. La solution rapide est la suivante:

ulimit -n 4096

l'explication est la suivante - chaque connexion au serveur est un descripteur de fichier. Dans CentOS, Redhat et Fedora, probablement d'autres, la limite de l'utilisateur du fichier est de 1024 - aucune idée de la raison. Il peut être facilement vu lorsque vous tapez: ulimit -n

Notez que cela n'a pas beaucoup de rapport avec les fichiers système max (/ proc / sys / fs / file-max).

Dans mon cas, c'était un problème avec Redis, alors j'ai fait:

ulimit -n 4096
redis-server -c xxxx

dans votre cas, au lieu de redis, vous devez démarrer votre serveur.


19
2017-12-20 22:59



TCP a une fonctionnalité appelée "TIME_WAIT" qui garantit que les connexions sont correctement fermées. Il faut qu'une extrémité de la connexion reste à l'écoute pendant un certain temps après la fermeture du socket.

Dans un serveur haute performance, il est important que ce soit les clients qui entrent dans TIME_WAIT, pas le serveur. Les clients peuvent se permettre d'ouvrir un port, tandis qu'un serveur occupé peut rapidement manquer de ports ou avoir trop de FD ouverts.

Pour ce faire, le serveur ne doit jamais fermer la connexion en premier - il doit toujours attendre que le client le ferme.


12
2018-06-03 14:17



Utilisation lsof -u `whoami` | wc -l pour trouver combien de fichiers ouverts l'utilisateur a


7
2018-06-01 18:04



Cela signifie que le nombre maximum de fichiers ouverts simultanément.

Résolu:

À la fin du fichier /etc/security/limits.conf vous devez ajouter les lignes suivantes:

* soft nofile 16384
* hard nofile 16384

Dans la console actuelle de root (sudo ne fonctionne pas) à faire:

ulimit -n 16384

Bien que ce soit facultatif, s'il est possible de redémarrer le serveur.

Dans /etc/nginx/nginx.conf fichier pour enregistrer la nouvelle valeur worker_connections égal à 16384 diviser par valeur worker_processes.

Sinon fait ulimit -n 16384, besoin de redémarrer, alors le problème va reculer.

PS:

Si après la réparation est visible dans les journaux error accept() failed (24: Too many open files):

Dans la configuration nginx, propevia (par exemple):

worker_processes 2;

worker_rlimit_nofile 16384;

events {
  worker_connections 8192;
}

6
2017-09-21 15:38



J'ai eu ce problème également. Vous avez une fuite de handle de fichier. Vous pouvez déboguer ceci en imprimant une liste de tous les descripteurs de fichiers ouverts (sur les systèmes POSIX):

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 << ") ";
   }
}

En vidant tous les fichiers ouverts, vous découvrirez rapidement où se trouve la fuite de votre gestionnaire de fichiers.

Si votre serveur génère des sous-processus. Par exemple. s'il s'agit d'un serveur de type 'fork' ou si vous générez d'autres processus (par exemple via cgi), vous devez vous assurer de créer vos descripteurs de fichiers avec "cloexec", à la fois pour les fichiers réels et les sockets.

Sans cloexec, chaque fois que vous faites un fork ou un spawn, tous les descripteurs de fichiers ouverts sont clonés dans le processus fils.

Il est également très facile de ne pas fermer les sockets réseau - par ex. il suffit de les abandonner lorsque le correspondant distant se déconnecte. Cela va fuir les poignées comme un fou.


5
2018-05-21 15:42



cela peut prendre un peu de temps avant qu'une prise fermée soit vraiment libérée

lsof pour lister les fichiers ouverts

cat /proc/sys/fs/file-max pour voir s'il y a une limite du système


4
2018-05-19 01:20



Lorsque votre programme a plus de descripteurs ouverts que les fichiers ouverts ulimit (ulimit -a va le lister), le noyau refuse d'ouvrir d'autres descripteurs de fichiers. Assurez-vous de ne pas avoir de fuite de descripteur de fichier - par exemple, en l'exécutant pendant un moment, puis en vous arrêtant et en vérifiant si des fds supplémentaires sont encore ouverts - et si le problème persiste, modifiez le nofile ulimit utilisateur dans /etc/security/limits.conf


1
2018-05-19 01:21