Linux 최대 스레드 수

Linux 최대 스레드 수

내 서버는 Amazon Ec2 Linux에서 실행되고 있습니다. 내부에 mongodb 서버가 있습니다. mongodb 서버가 높은 부하로 실행되고 있는데 불행하게도 문제가 발생했습니다./

우리 모두 mongodb가 각 클라이언트 연결에 대해 새 스레드를 생성한다는 것을 알고 있듯이 이전에는 잘 작동했습니다. 어떤 이유로 MongoDB는 권한이 없는 사용자(mongod 사용자로 실행 중)로서 호스트 시스템에 975개 이상의 연결을 생성할 수 없습니다. 하지만 루트 사용자로 실행하면 최대 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);
}

그리고 상황을 다시 반복하면 루트 사용자로서 약 32,000개의 스레드를 생성할 수 있고 권한이 없는 사용자(mongod 또는 ec2-user)로서 약 1000개를 생성할 수 있습니다.

루트 사용자에 대한 ulimit는 다음과 같습니다.

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

이것은 mongod 사용자의 ulimit입니다.

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가 비활성화되었습니다. 이 이상한 문제를 해결하는 방법을 잘 모르겠습니다... 혹시 아시는 분 계시나요?

답변1

당신의 문제는 max user processes한계입니다.

~에서getrlimit(2)매뉴얼 페이지:

RLIMIT_NPROC 호출 프로세스의 실제 사용자 ID에 대해 생성할 수 있는 최대 프로세스 수(더 정확하게는 Linux에서는 스레드)입니다. 이 제한에 도달하면 fork(2)오류와 함께 실패합니다 EAGAIN.

다음에도 적용됩니다.pthread_create(3):

EAGAIN다른 스레드를 생성하기에는 리소스가 부족하거나 스레드 수에 대한 시스템 제한이 발생했습니다. 후자의 상황은 두 가지 방법으로 발생할 수 있습니다. RLIMIT_NPROC즉, setrlimit(2)실제 사용자 ID로 프로세스 수를 제한하는 소프트 리소스 제한에 도달하거나 /proc/sys/kernel/threads-max스레드 수에 대한 커널 시스템 전체 제한에 도달합니다.

사용자 제한을 늘리면 다른 리소스 제한에 도달할 때까지 더 많은 스레드를 생성할 수 있어야 합니다.
또는 단순한 리소스 고갈 - 1Mb 스택 및 20,000개 스레드의 경우 많은 RAM이 필요합니다.
당신은 또한 볼 수 있습니다NPTL은 최대 스레드 수를 65528로 제한합니까?: /proc/sys/vm/max_map_count언젠가는 문제가 될 수도 있습니다.

측면 보기: .Look -pthread대신 사용해야 합니다 .-lpthreadgcc - 컴파일 시 -pthread 플래그의 의미.

답변2

Mongo 클라이언트(java)에 중단된 연결 문제가 있을 때(아마도 AWS 네트워크 중단으로 인해) 이 문제가 발생했습니다. TCP_KEEPALIVE가 7200(2시간)으로 설정되면 연결 풀의 연결은 이 2시간 내에 설정되고 975개의 연결에 도달하면 mongod가 종료됩니다.

Mongo 프로덕션 매니페스트에서는 연결 유지 시간(5분)을 훨씬 짧게 권장하며, 이 설정은 연결 제한을 방지하는 데도 도움이 됩니다.

관련 정보