Numero massimo di thread di Linux


8

il mio server ha funzionato con Amazon Ec2 linux. Ho un server mongodb dentro. Il server mongodb è stato eseguito con un carico pesante e, purtroppo, ho riscontrato un problema con esso: /

Come noto, il mongodb crea un nuovo thread per ogni connessione client, e questo ha funzionato bene prima. Non so perché, ma MongoDB non può creare più di 975 connessioni sull'host come utente non privilegiato (funziona sotto un utente mongod). Ma quando lo eseguo come utente root, può gestire fino a 20000 connessioni (limite interno mongodb). Ma, ulteriori ricerche mostrano che quel problema non è il server MongoDB, ma un Linux stesso.

Ho trovato un semplice programma che controlla il numero massimo di connessioni:

/* 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);
}

E la sutuazione viene ripetuta di nuovo, come utente root posso creare circa 32k thread, come utente non privilegiato (mongod o ec2-user) circa 1000.

Questo è un ulimit per l'utente 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

Questo è un ulimit per l'utente 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

Discussioni max del kernel:

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

SELinux è disabilitato. Non so come risolvere questo strano problema ... Forse qualcuno lo fa?

Risposte:


12

Il tuo problema è il max user processeslimite.

Dalla getrlimit(2)pagina man:

RLIMIT_NPROC Il numero massimo di processi (o, più precisamente su Linux, thread) che possono essere creati per l'ID utente reale del processo di chiamata. Quando si incontra questo limite, fork(2)non riesce con l'errore EAGAIN.

Lo stesso per pthread_create(3):

EAGAINRisorse insufficienti per creare un altro thread o è stato riscontrato un limite imposto dal sistema sul numero di thread. Quest'ultimo caso può verificarsi in due modi: è stato raggiunto il RLIMIT_NPROClimite delle risorse software (impostato tramite setrlimit(2)), che limita il numero di processi per un ID utente reale; oppure è /proc/sys/kernel/threads-maxstato raggiunto il limite a livello di sistema del kernel sul numero di thread .

Aumenta quel limite per il tuo utente e dovrebbe essere in grado di creare più thread, fino a raggiungere altri limiti di risorse.
O semplice esaurimento delle risorse: per stack da 1Mb e thread da 20k, avrai bisogno di molta RAM.
Vedi anche NPTL tappi filettature massime a 65528? : /proc/sys/vm/max_map_countpotrebbe diventare un problema ad un certo punto.

Punto laterale: dovresti usare -pthreadinvece di -lpthread. Vedi gcc - significato del flag -pthread durante la compilazione .


0

Abbiamo riscontrato questo problema quando i problemi di connessione dal client mongo (java) vengono interrotti (sembra dalla rete AWS). Con TCP_KEEPALIVE impostato su 7200 (2 ore), le connessioni nei pool di connessione si accumulano in questa finestra di 2 ore e mongod muore quando raggiunge 975 connessioni.

L'elenco di controllo della produzione di mongo suggerisce un periodo di tempo molto più basso (5 minuti); impostazione che dovrebbe aiutarti a evitare anche il limite di connessione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.