Как настроить кластер mongodb для обработки 20K + одновременных

Мое приложение использует MongoDB как базу данных. Мы ожидаем одновременного подключения 20K + к кластеру mongodb. Как мне настроить сервер, если я хочу запустить mongodb на 20 серверах и очертить кластер 20 способами?

Вот что я сделал до сих пор: На каждом из моих 20 серверов у меня есть один монгос (маршрутизатор), работающий на порте 30000, а на 3 серверах я запускаю серверы конфигурации mongo на порту 20000. Затем на каждом сервере я запускаю 3 экземпляра mongod. Один из них является основным. Для слов у меня 20 монго, 3 mongo-config, 60 серверов mongod (20 первичных и 40 реплик).

Затем в моем приложении (которое также запускается на каждом сервере и подключается к localhost: 30000 mongos), я устанавливаю mongoOptions таким образом, что соединенияPerHost = 1000.

Через 10-15 минут после начала всех сервисов некоторые из них перестали быть ssh -способными. Эти серверы по-прежнему работают в режиме ping. Я подозреваю, что слишком много соединений, и это заставило сервер умереть.

Мой собственный анализ выглядит следующим образом: 1K соединений для каждого пула соединений для каждого первичного осколка, он будет иметь 1K * 20 (осколки) = 20K одновременных подключений. На нескольких серверах, вероятно, будет работать более одного первичного запуска, что удвоит или утроит количество подключений до 60K. Так или иначе, mongod не может обрабатывать эти многочисленные соединения, хотя я изменил свои системные настройки, чтобы каждый процесс мог открыть больше файлов.

Вот что показывает 'ulimit -a':

core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20
file size (blocks, -f) unlimited
pending signals (-i) 16382
max locked memory (kbytes, -l) 64000000
max memory size (kbytes, -m) unlimited
open files (-n) 320000
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) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

Кстати, я не указывал --maxConns, когда я запускал mongod/mongos, я также не менял MONGO.POOLSIZE.

Вопрос: если мои рассуждения верны, общее количество требований к одновременному соединению будет задано для каждого первичного элемента, что не кажется мне правильным, это почти означает, что кластер mongodb вообще не масштабируется. Кто-нибудь скажет мне, что я не прав, пожалуйста?

Ответ 1

Архитектура вашего кластера:

Запуск нескольких экземпляров mongod на том же сервере обычно не является хорошей идеей, есть ли у вас какая-то особая причина для этого? Первичный сервер каждого осколка будет оказывать сильное давление на ваш сервер, репликация также добавит давление io, поэтому их смешивание не будет действительно хорошим для производительности. ИМО, вам лучше иметь 6 осколков (1 мастер - 2 секунды) и дать каждому экземпляру собственный сервер. (Контекст и экземпляр arbiter не являются очень ресурсоемкими, поэтому его можно оставить на тех же серверах).

Ответ 2

Иногда лимиты не применяются к самому процессу. В качестве теста перейдите на один из серверов и получите pid для службы mongo, которую вы хотите проверить, выполнив

ps axu | grep mongodb

а затем do

cat /proc/{pid}/limit

Это скажет вам, что лимиты вступили в силу. Если лимит не действует, вам необходимо указать предел в файле запуска, а затем остановить - запустить службу mongo и снова проверить.

Правильный способ узнать, происходит ли это, - это заголовок журнала mongo на умирающем сервере и просмотр сообщений "слишком много файлов".

Мы устанавливаем ограничение на 20000 на сервер и делаем то же самое на всех экземплярах mongod и mongos, и это, похоже, работает.

Ответ 3

Мы используем 4-осколочный реплик на 4 машинах. У нас есть 2 первичных осколка на 2 хозяевах, 2 дубликата реплики на двух других коробках, арбитры и серверы конфигурации разбросаны).

Мы получаем сообщения:

./checkMongo.bash: fork: retry: Resource temporarily unavailable
./checkMongo.bash: fork: retry: Resource temporarily unavailable
./checkMongo.bash: fork: retry: Resource temporarily unavailable
Write failed: Broken pipe 

Проверка ulimit -a:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 773713
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 4096
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited   

Хорошо, поэтому мы, возможно, достигли предела процесса из-за сообщения fork. Здесь, как проверить, что:

$ ps axo pid,ppid,rss,vsz,nlwp,cmd | egrep mongo
27442     1 36572   59735772 275 /path/mongod --shardsvr --replSet shard-00 --dbpath /path/rs-00-p --port 30000 --logpath /path/rs-00-p.log --fork
27534     1 4100020 59587548 295 /path/mongod --shardsvr --replSet shard-02 --dbpath /path/rs-02-p --port 30200 --logpath /path/rs-02-p.log --fork
27769     1 57948   13242560 401 /path/mongod --configsvr --dbpath /path/configServer_1 --port 35000 --logpath /path/configServer_1.log --fork

Итак, вы можете видеть, что у mongod есть 275, 295 и 401 подпроцессы/потоки. хотя сейчас я не нахожусь на пределе, я, вероятно, был раньше. Итак, решение: измените систему ulimit для пользователя, с которым мы работаем с 1024 до 2048 (или даже без ограничений). Вы не можете изменить через

ulimit -u unlimited

если только вы не суо первым или чем-то; У меня нет приемов для этого.