Максимальное количество потоков в Linux

8

мой сервер работает с Amazon Ec2 linux. У меня есть сервер mongodb внутри. Сервер mongodb работал под большой нагрузкой, и, к сожалению, у меня возникла проблема с ним: /

Как известно, mongodb создает новый поток для каждого клиентского соединения, и раньше это работало нормально. Я не знаю почему, но MongoDB не может создать более 975 соединений на хосте как непривилегированный пользователь (он работает под пользователем mongod). Но когда я запускаю его как пользователь root, он может обрабатывать до 20000 подключений (внутреннее ограничение mongodb). Но дальнейшие исследования показывают, что проблема не в сервере MongoDB, а в самом Linux.

Я нашел простую программу, которая проверяет максимальное количество соединений:

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

И повторяемость повторяется снова, как пользователь root, я могу создать около 32 тыс. Потоков, а непривилегированный пользователь (mongod или ec2-user) - около 1000.

Это ограничение для пользователя 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

Это ulimit для пользователя 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

Ядро макс темы:

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

SELinux отключен. Не знаю, как решить эту странную проблему ... Возможно, кто-то делает?

Сергей Ломаков
источник

Ответы:

12

Ваша проблема - это max user processesпредел.

Со getrlimit(2)страницы руководства :

RLIMIT_NPROC Максимальное количество процессов (или, точнее, в Linux, потоков), которое может быть создано для реального идентификатора пользователя вызывающего процесса. При fork(2)достижении этого предела происходит сбой с ошибкой EAGAIN.

То же самое для pthread_create(3):

EAGAINНедостаточно ресурсов для создания другого потока или системное ограничение на количество потоков. Последний случай может происходить двумя способами: достигнут RLIMIT_NPROCпредел мягкого ресурса (установленный через setrlimit(2)), который ограничивает количество процессов для реального идентификатора пользователя; или /proc/sys/kernel/threads-maxбыл достигнут общесистемный лимит ядра на количество потоков .

Увеличьте этот лимит для своего пользователя, и он сможет создавать больше потоков, пока он не достигнет других лимитов ресурсов.
Или просто исчерпание ресурсов - для стека 1 МБ и потоков 20 КБ вам потребуется много оперативной памяти.
Смотрите также NPTL caps максимальные темы на 65528? : /proc/sys/vm/max_map_countможет стать проблемой в какой-то момент.

Побочный момент: вы должны использовать -pthreadвместо -lpthread. Смотрите gcc - значение флага -pthread при компиляции .

Мат
источник
0

Мы столкнулись с этой проблемой, когда проблемы с соединением от клиента mongo (java) прерываются (кажется, сетью AWS). Если для TCP_KEEPALIVE установлено значение 7200 (2 часа), соединения в пулах подключений будут создаваться в течение этого 2-часового окна, и mongod умирает, когда он достигает 975 соединений.

Контрольный список для производства монго предполагает, что keepalive гораздо меньше (5 минут); настройка, которая также поможет вам избежать ограничения соединения.

Brett
источник