Cuenta máxima de hilos de Linux

8

mi servidor se ha estado ejecutando con Amazon Ec2 Linux. Tengo un servidor mongodb dentro. El servidor mongodb se ha estado ejecutando con mucha carga y, por desgracia, me he encontrado con un problema: /

Como se sabe, el mongodb crea un nuevo hilo para cada conexión de cliente, y esto funcionó bien antes. No sé por qué, pero MongoDB no puede crear más de 975 conexiones en el host como usuario no privilegiado (se ejecuta bajo un usuario mongod). Pero cuando lo estoy ejecutando como usuario root, puede manejar hasta 20000 conexiones (límite interno mongodb). Pero, investigaciones posteriores muestran que ese problema no es el servidor MongoDB, sino un linux en sí mismo.

He encontrado un programa simple, que verifica el número máximo de conexiones:

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

Y la sutura se repite nuevamente, como usuario root puedo crear alrededor de 32k hilos, como usuario no privilegiado (mongod o ec2-user) alrededor de 1000.

Este es un ulimit para el usuario 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

Este es un ulimit para el usuario 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

Hilos máximos del núcleo:

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

SELinux está deshabilitado. No sé cómo resolver este extraño problema ... ¿Posiblemente alguien lo haga?

Sergei Lomakov
fuente

Respuestas:

12

Tu problema es el max user processeslímite.

Desde la getrlimit(2)página del manual:

RLIMIT_NPROC El número máximo de procesos (o, más precisamente en Linux, subprocesos) que se pueden crear para la ID de usuario real del proceso de llamada. Al encontrar este límite, fork(2)falla con el error EAGAIN.

Lo mismo para pthread_create(3):

EAGAINSe encontraron recursos insuficientes para crear otro subproceso o un límite impuesto por el sistema en el número de subprocesos. El último caso puede ocurrir de dos maneras: se alcanzó el RLIMIT_NPROClímite de recursos flexibles (establecido a través de setrlimit(2)), que limita el número de procesos para una ID de usuario real; o /proc/sys/kernel/threads-maxse alcanzó el límite de todo el sistema del núcleo en el número de subprocesos .

Aumente ese límite para su usuario, y debería poder crear más hilos, hasta que alcance otros límites de recursos.
O simplemente agotamiento de recursos: para una pila de 1Mb y subprocesos de 20k, necesitará mucha RAM.
Ver también NPTL caps roscas máximas en 65528? : /proc/sys/vm/max_map_countpodría convertirse en un problema en algún momento.

Punto lateral: debe usar en -pthreadlugar de -lpthread. Ver gcc - significado del indicador -pthread al compilar .

Estera
fuente
0

Nos encontramos con este problema cuando los problemas de conexión del cliente mongo (java) se interrumpen (parece ser por la red de AWS). Con TCP_KEEPALIVE establecido en 7200 (2 horas), las conexiones en los grupos de conexiones se acumulan dentro de esta ventana de 2 horas, y mongod muere cuando alcanza las 975 conexiones.

La lista de control de producción de mongo sugiere keepalives de un tiempo mucho más bajo (5 minutos); configuración que debería ayudarlo a evitar el límite de conexión también.

Brett
fuente