Nombre max de threads Linux

8

mon serveur fonctionne avec Amazon Ec2 linux. J'ai un serveur mongodb à l'intérieur. Le serveur mongodb fonctionne sous une charge importante et, malheureusement, je suis tombé sur un problème avec lui: /

Comme on le sait, le mongodb crée un nouveau thread pour chaque connexion client, et cela fonctionnait bien avant. Je ne sais pas pourquoi, mais MongoDB ne peut pas créer plus de 975 connexions sur l'hôte en tant qu'utilisateur non privilégié (il fonctionne sous un utilisateur mongod). Mais lorsque je l'exécute en tant qu'utilisateur root, il peut gérer jusqu'à 20000 connexions (limite interne mongodb). Mais, de nouvelles investigations montrent que ce problème n'est pas le serveur MongoDB, mais un Linux lui-même.

J'ai trouvé un programme simple, qui vérifie le nombre maximum de connexions:

/* compile with:   gcc -lpthread -o thread-limit thread-limit.c */
/* originally from: http://www.volano.com/linuxnotes.html */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

#define MAX_THREADS 100000
#define PTHREAD_STACK_MIN 1*1024*1024*1024
int i;

void run(void) {
  sleep(60 * 60);
}

int main(int argc, char *argv[]) {
  int rc = 0;
  pthread_t thread[MAX_THREADS];
  pthread_attr_t thread_attr;

  pthread_attr_init(&thread_attr);
  pthread_attr_setstacksize(&thread_attr, PTHREAD_STACK_MIN);

  printf("Creating threads ...\n");
  for (i = 0; i < MAX_THREADS && rc == 0; i++) {
    rc = pthread_create(&(thread[i]), &thread_attr, (void *) &run, NULL);
    if (rc == 0) {
      pthread_detach(thread[i]);
      if ((i + 1) % 100 == 0)
    printf("%i threads so far ...\n", i + 1);
    }
    else
    {
      printf("Failed with return code %i creating thread %i (%s).\n",
         rc, i + 1, strerror(rc));

      // can we allocate memory?
      char *block = NULL;
      block = malloc(65545);
      if(block == NULL)
        printf("Malloc failed too :( \n");
      else
        printf("Malloc worked, hmmm\n");
    }
  }
sleep(60*60); // ctrl+c to exit; makes it easier to see mem use
  exit(0);
}

Et la sutuation est répétée à nouveau, en tant qu'utilisateur root, je peux créer environ 32k threads, en tant qu'utilisateur non privilégié (mongod ou ec2-user) autour de 1000.

Ceci est un ulimit pour l'utilisateur root:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 59470
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 60000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Ceci est un ulimit pour l'utilisateur mongod:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 59470
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 60000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 1024
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Nombre maximal de threads du noyau:

bash-4.1$ cat /proc/sys/kernel/threads-max 
118940

SELinux est désactivé. Je ne sais pas comment résoudre cet étrange problème ... Peut-être que quelqu'un le fait?

Sergei Lomakov
la source

Réponses:

12

Votre problème est la max user processeslimite.

Depuis la getrlimit(2)page de manuel:

RLIMIT_NPROC Le nombre maximal de processus (ou, plus précisément sous Linux, de threads) pouvant être créés pour l'ID utilisateur réel du processus appelant. En rencontrant cette limite, fork(2)échoue avec l'erreur EAGAIN.

Pareil pour pthread_create(3):

EAGAINRessources insuffisantes pour créer un autre thread, ou une limite imposée par le système sur le nombre de threads a été rencontrée. Ce dernier cas peut se produire de deux manières: la RLIMIT_NPROClimite de ressources logicielles (définie via setrlimit(2)), qui limite le nombre de processus pour un ID utilisateur réel, a été atteinte; ou la limite à l'échelle du système du noyau sur le nombre de threads /proc/sys/kernel/threads-max, a été atteinte.

Augmentez cette limite pour votre utilisateur et il devrait pouvoir créer plus de threads jusqu'à ce qu'il atteigne d'autres limites de ressources.
Ou épuisement des ressources - pour une pile de 1 Mo et des threads de 20 Ko, vous aurez besoin de beaucoup de RAM.
Voir aussi NPTL plafonne les filetages maximum à 65528? : /proc/sys/vm/max_map_countpourrait devenir un problème à un moment donné.

Point de côté: vous devez utiliser à la -pthreadplace de -lpthread. Voir gcc - signification du drapeau -pthread lors de la compilation .

Tapis
la source
0

Nous avons rencontré ce problème lorsque les problèmes de connexion du client mongo (java) sont interrompus (il semble que le réseau AWS). Avec TCP_KEEPALIVE défini sur 7200 (2 heures), les connexions dans les pools de connexions s'accumulent dans cette fenêtre de 2 heures et mongod meurt lorsqu'il atteint 975 connexions.

La liste de contrôle de la production de mongo suggère des durées de vie beaucoup plus courtes (5 minutes); paramètre qui devrait également vous aider à éviter la limite de connexion.

Brett
la source