내 서버는 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
대신 사용해야 합니다 .-lpthread
gcc - 컴파일 시 -pthread 플래그의 의미.
답변2
Mongo 클라이언트(java)에 중단된 연결 문제가 있을 때(아마도 AWS 네트워크 중단으로 인해) 이 문제가 발생했습니다. TCP_KEEPALIVE가 7200(2시간)으로 설정되면 연결 풀의 연결은 이 2시간 내에 설정되고 975개의 연결에 도달하면 mongod가 종료됩니다.
Mongo 프로덕션 매니페스트에서는 연결 유지 시간(5분)을 훨씬 짧게 권장하며, 이 설정은 연결 제한을 방지하는 데도 도움이 됩니다.