Linux max threads dihitung

8

server saya sudah berjalan dengan Amazon Ec2 linux. Saya memiliki server mongodb di dalamnya. Server mongodb telah berjalan di bawah beban berat, dan, sayangnya, saya mengalami masalah dengan itu: /

Seperti diketahui, mongodb membuat utas baru untuk setiap koneksi klien, dan ini berfungsi dengan baik sebelumnya. Saya tidak tahu mengapa, tetapi MongoDB tidak dapat membuat lebih dari 975 koneksi pada host sebagai pengguna yang tidak memiliki hak istimewa (ini berjalan di bawah pengguna mongod). Tetapi ketika saya menjalankannya sebagai pengguna root, ia dapat menangani hingga 20.000 koneksi (batas internal mongodb). Tapi, penyelidikan lebih lanjut menunjukkan, masalah itu bukan server MongoDB, tetapi linux itu sendiri.

Saya telah menemukan program sederhana, yang memeriksa nomor koneksi maks:

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

Dan sutuation diulangi lagi, sebagai pengguna root saya dapat membuat sekitar 32k utas, sebagai pengguna non-privilege (mongod atau ec2-user) sekitar 1000.

Ini adalah ulimit untuk pengguna 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

Ini adalah ulimit untuk pengguna 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

Kernel max utas:

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

SELinux dinonaktifkan. Tidak tahu bagaimana mengatasi masalah aneh ini ... Mungkin, ada yang tahu?

Sergei Lomakov
sumber

Jawaban:

12

Masalah Anda adalah max user processesbatasnya.

Dari getrlimit(2)halaman manual:

RLIMIT_NPROC Jumlah maksimum proses (atau, lebih tepatnya di Linux, utas) yang dapat dibuat untuk ID pengguna sebenarnya dari proses panggilan. Setelah menemui batas ini, fork(2)gagal dengan kesalahan EAGAIN.

Sama untuk pthread_create(3):

EAGAINSumber daya yang tidak mencukupi untuk membuat utas lain, atau batasan yang diberlakukan sistem pada jumlah utas ditemui. Kasus terakhir dapat terjadi dalam dua cara: RLIMIT_NPROCbatas sumber daya lunak (ditetapkan melalui setrlimit(2)), yang membatasi jumlah proses untuk ID pengguna nyata, tercapai; atau batas seluruh sistem kernel pada jumlah utas,, /proc/sys/kernel/threads-maxtercapai.

Tingkatkan batas itu untuk pengguna Anda, dan itu harus dapat membuat lebih banyak utas, hingga mencapai batas sumber daya lainnya.
Atau kelelahan sumber daya biasa - untuk tumpukan 1Mb dan utas 20k, Anda akan membutuhkan banyak RAM.
Lihat juga NPTL membatasi utas maksimal di 65528? : /proc/sys/vm/max_map_countbisa menjadi masalah di beberapa titik.

Poin samping: Anda harus menggunakan -pthreadsebagai gantinya -lpthread. Lihat gcc - signifikansi flag -pthread saat kompilasi .

Tikar
sumber
0

Kami mengalami masalah ini ketika masalah koneksi dari klien mongo (java) terganggu (sepertinya oleh jaringan AWS). Dengan TCP_KEEPALIVE diatur ke 7200 (2 jam), koneksi dalam kumpulan koneksi bertambah dalam jendela 2 jam ini, dan mongod mati ketika mencapai 975 koneksi.

Daftar periksa produksi mongo menyarankan agar Anda tetap memiliki waktu yang jauh lebih rendah (5 menit); pengaturan yang akan membantu Anda menghindari batas koneksi juga.

Brett
sumber