Как настроить Java-драйвер MongoDB MongoOptions для производственного использования?

100

Я искал в Интернете лучшие практики по настройке MongoOptions для Java-драйвера MongoDB, и я не придумал ничего, кроме API. Этот поиск начался после того, как я столкнулся с ошибкой «com.mongodb.DBPortPool $ SemaphoresOut: Out of semaphores to get db connection» и, увеличив количество соединений / множитель, я смог решить эту проблему. Я ищу ссылки или ваши лучшие практики по настройке этих параметров для производства.

Параметры для драйвера 2.4 включают: http://api.mongodb.org/java/2.4/com/mongodb/MongoOptions.html

  • autoConnectRetry
  • ConnectionsPerHost
  • connectTimeout
  • maxWaitTime
  • socketTimeout
  • ThreadsAllowedToBlockForConnectionMultiplier

У новых драйверов больше возможностей, и мне было бы интересно узнать о них.

Дэн Политес
источник

Ответы:

160

Обновлено до 2.9:

  • autoConnectRetry просто означает, что драйвер автоматически попытается повторно подключиться к серверу (-ам) после неожиданного отключения. В производственных средах обычно требуется значение true.

  • connectionsPerHost - это количество физических подключений, которые один экземпляр Mongo (это синглтон, поэтому у вас обычно есть одно для каждого приложения) может установить с процессом mongod / mongos. Во время написания java-драйвер в конечном итоге установит это количество подключений, даже если фактическая пропускная способность запросов низкая (вы увидите, что статистика «conn» в монгостате возрастает, пока не достигнет этого числа для каждого сервера приложений).

    В большинстве случаев нет необходимости устанавливать это значение выше 100, но этот параметр является одним из тех, что «протестируйте и посмотрите». Обратите внимание, что вам нужно убедиться, что вы установили достаточно низкий уровень, чтобы общее количество подключений к вашему серверу не превышало

    db.serverStatus().connections.available

    Сейчас в производстве у нас это 40.

  • connectTimeout . Как видно из названия, драйвер будет ждать в миллисекундах, прежде чем попытка подключения будет прервана. Установите для тайм-аута какое-то большое значение (15–30 секунд), если нет реалистичной ожидаемой вероятности, что это будет мешать успешным попыткам подключения. Обычно, если попытка подключения занимает больше пары секунд, ваша сетевая инфраструктура не способна обеспечить высокую пропускную способность.

  • maxWaitTime . Количество мсек, в течение которого поток будет ждать, пока соединение станет доступным в пуле соединений, и вызовет исключение, если это не произойдет вовремя. Оставить по умолчанию.

  • socketTimeout . Стандартное значение тайм-аута сокета. Установите 60 секунд (60000).

  • threadAllowedToBlockForConnectionMultiplier . Множитель для connectionsPerHost, который обозначает количество потоков, которым разрешено ждать, пока соединения станут доступными, если пул в настоящее время исчерпан. Это параметр, который вызовет исключение «com.mongodb.DBPortPool $ SemaphoresOut: Out of semaphores to get db connection». Это исключение будет сгенерировано, когда эта очередь потока превысит значение threadAllowedToBlockForConnectionMultiplier. Например, если connectionsPerHost равно 10, а это значение равно 5, до 50 потоков могут заблокироваться до того, как будет сгенерировано вышеупомянутое исключение.

    Если вы ожидаете больших пиков пропускной способности, которые могут вызвать большие очереди, временно увеличьте это значение. Именно по этой причине у нас сейчас 15:00. Если нагрузка на ваш запрос постоянно опережает сервер, вам следует соответствующим образом улучшить ситуацию с оборудованием / масштабированием.

  • readPreference . (ОБНОВЛЕНО, 2.8+) Используется для определения предпочтения чтения по умолчанию и заменяет "slaveOk". Настройте ReadPreference с помощью одного из методов фабрики классов. Полное описание наиболее распространенных настроек можно найти в конце этого поста.

  • ш . (ОБНОВЛЕНО, 2.6+) Это значение определяет «безопасность» записи. Когда это значение равно -1, запись не будет сообщать об ошибках независимо от ошибок сети или базы данных. WriteConcern.NONE - подходящий предопределенный WriteConcern для этого. Если w равно 0, то сетевые ошибки приведут к сбою записи, а ошибки mongo - нет. Это обычно называется записью «запустил и забыл» и должен использоваться, когда производительность важнее согласованности и долговечности. Для этого режима используйте WriteConcern.NORMAL.

    Если вы установите w равным 1 или выше, запись будет считаться безопасной. Безопасная запись выполняет запись и сопровождается запросом к серверу, чтобы убедиться, что запись прошла успешно, или получить значение ошибки, если это не так (другими словами, он отправляет команду getLastError () после того, как вы пишете). Обратите внимание, что пока эта команда getLastError () не будет завершена, соединение зарезервировано. В результате этого и дополнительной команды пропускная способность будет значительно ниже, чем при записи с w <= 0. При значении aw ровно 1 MongoDB гарантирует, что запись будет успешной (или подтвержденной ошибкой) в экземпляре, в который вы отправили запись.

    В случае наборов реплик вы можете использовать более высокие значения для w, которые сообщают MongoDB отправлять запись по крайней мере "w" членам набора реплик перед возвратом (или, точнее, дождитесь репликации вашей записи для "w" участников ). Вы также можете установить w в строку «большинство», которая сообщает MongoDB выполнять запись в большинство членов набора реплик (WriteConcern.MAJORITY). Обычно вам следует установить это значение в 1, если вам не нужна чистая производительность (-1 или 0) или реплицированная запись (> 1). Значения выше 1 существенно влияют на пропускную способность записи.

  • fsync . Параметр долговечности, который заставляет mongo сбрасывать данные на диск после каждой записи, если он включен. У меня никогда не было проблем с долговечностью, связанных с невыполненной записью, поэтому у нас это значение false (по умолчанию) в продакшене.

  • j * (НОВИНКА 2.7+) *. Логическое значение, которое при значении true заставляет MongoDB ждать успешного коммита группы журналирования перед возвратом. Если у вас включено ведение журнала, вы можете включить его для дополнительной надежности. Обратитесь к http://www.mongodb.org/display/DOCS/Journaling, чтобы узнать, что дает вам ведение журнала (и, следовательно, почему вы можете захотеть включить этот флаг).

ReadPreference Класс ReadPreference позволяет вам настроить, на какие экземпляры mongod направляются запросы, если вы работаете с наборами реплик. Доступны следующие варианты:

  • ReadPreference.primary () : все операции чтения передаются только основному члену набора реплик . Используйте это, если вам требуется, чтобы все запросы возвращали согласованные (самые последние записанные) данные. Это значение по умолчанию.

  • ReadPreference.primaryPreferred () : все операции чтения передаются первичному элементу набора реплик, если это возможно, но могут запрашивать вторичные члены, если первичный узел недоступен. Таким образом, если первичный становится недоступным, чтения в конечном итоге становятся согласованными, но только если первичный недоступен.

  • ReadPreference.secondary () : все операции чтения переходят к вторичным членам набора репликаций, а первичный член используется только для записи. Используйте это, только если вы можете жить с последовательными чтениями. Для увеличения производительности чтения можно использовать дополнительные элементы репозитория, хотя есть ограничения на количество (голосующих) членов, которые может иметь репсет.

  • ReadPreference.secondaryPreferred () : все операции чтения переходят к вторичным членам набора репликаций, если любой из них доступен. Основной член используется исключительно для записи, если все второстепенные элементы не становятся недоступными. За исключением отката к основному члену для чтения, это то же самое, что и ReadPreference.secondary ().

  • ReadPreference.nearest () : чтение идет к ближайшему члену набора реплик, доступному клиенту базы данных. Используйте только в том случае, если в конечном итоге приемлемы последовательные чтения. Ближайший член - это член с наименьшей задержкой между клиентом и различными членами набора репозиториев. Поскольку у занятых участников в конечном итоге будут более высокие задержки, это также должно автоматически балансировать нагрузку на чтение, хотя, по моему опыту, вторичный (предпочтительный), кажется, делает это лучше, если задержки участников относительно постоянны.

Примечание. Все вышеперечисленное имеют версии одного и того же метода с поддержкой тегов, которые вместо этого возвращают экземпляры TaggableReadPreference. Полное описание тегов набора реплик можно найти здесь: Теги набора реплик

Ремон ван Влит
источник
6
Не опасно ли оставлять socketTimeout и connectTimeout по умолчанию (бесконечным)? Если соединение по какой-то причине зависает, ваше приложение (или, по крайней мере, этот поток) застрянет навсегда. Разве они не должны быть установлены как очень высокие (примерно 30 секунд для подключения, 2 минуты для сокета)?
Идрис Мохтарзада
Идрис, очень верно. В своем сообщении я ошибочно предположил, что MongoOptions имеет наши значения по умолчанию. В нашем слое Mongo ORM они равны 15 секундам и 1 минуте соответственно, и при написании я предположил, что это значения по умолчанию. Бесконечные тайм-ауты - определенно плохая идея. Спасибо за внимание, я исправил это в посте
Ремон ван Влит
опция "slaveOk" теперь устарела, если вы хотите, чтобы ее эквивалент был истинным, выполните: mongoOptions.readPreference = ReadPreference.secondaryPreferred ();
Gubatron
Хороший ответ, но ваше определение threadAllowedToBlockForConnectionMultiplier неверно (множитель ключевого слова). В соответствии с документами: «множитель для connectionsPerHost для # потоков, которые могут блокироваться, если для connectionsPerHost установлено значение 10, а для threadAllowedToBlockForConnectionMultiplier - 5, тогда 50 потоков могут заблокировать больше, и будет выдано исключение»
Тайлер Зейл,
3
Кажется, довольно популярный ответ. Если кто-то заинтересован в том, чтобы я обновил это, чтобы отразить изменения в последней версии драйвера, дайте мне знать
Ремон ван Влит,