私のサーバーはAmazon Ec2 Linuxで実行されています。内部にmongodbサーバーがあります。 mongodbサーバーが高負荷で実行されていますが、残念ながら問題が発生しました。
私たちは皆、mongodbが各クライアント接続に対して新しいスレッドを生成することを知っているように、以前はうまくいきました。何らかの理由で、MongoDBは無許可ユーザー(mongodユーザーとして実行されています)として、ホストシステムに975を超える接続を作成できません。ただし、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,000個のスレッドを作成し、権限のないユーザー(mongodまたはec2-user)として約1000個を作成できます。
rootユーザーの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
別のスレッドを作成するには、リソースが不足しているか、スレッド数にシステム制限がありました。後者の状況は2つの方法で発生する可能性があります。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分)をはるかに短く推奨し、この設定は接続の制限を防ぐのにも役立ちます。