Использование ClassTypeInformation.from(..) внутри MappingMongoConverter приводит к значительному конфликту потоков

Я пишу приложение, которое хранит много объектов в MongoDB через Spring Data MongoTemplate, Во избежание синхронизации создаю отдельный MongoTemplate для каждой темы. Фактически, каждый поток получает свое собственное почти все, чтобы избежать синхронизации.

Приложение обрабатывает события, генерируемые при взаимодействии пользователей с веб-страницей. Таким образом, события от конкретного пользователя должны обрабатываться последовательно, в то время как события для нескольких пользователей могут обрабатываться параллельно. В настоящее время приложение состоит из N конвейеров и балансировщика нагрузки, который распределяет события в конвейер на основе хеша / мода userId. В конце конвейера данные записываются в MongoDB с использованием Spring Data MongoDB Template.

Этот единственный процесс способен обрабатывать 2500 событий в секунду. Тем не менее, я наблюдаю значительную (со скоростью 2500 событий в секунду любая блокировка становится довольно значительной) конфликт между потоками. Все в области ClassTypeInformation доступа к синхронизированному CACHE.

К несчастью, MongoTemplate использования ClassTypeInformation который хранит кэш в синхронизированной карте. Поэтому, как бы я ни старался, запись данных в MongoDB всегда приводит к конфликту между моими рабочими потоками.

Я думаю ClassTypeInformation должен быть преобразован в bean-компонент, чтобы его можно было предоставить по желанию пользователя. Если учесть это, удалит конфликт между несколькими потоками.

Кто-нибудь знает, почему это было реализовано в виде статики, в отличие от обычного Spring bean-компонента? Есть ли планы сделать это изменение?

1 ответ

Решение

Нет, планов нет. По нескольким причинам: ClassTypeInformation это объект значения, а не инъекционный. Экземпляры должны создаваться на лету очень часто. Просто не имеет смысла настраивать его экземпляр с помощью Spring, поскольку экземпляры обычно создаются, когда мы сталкиваемся с Class в некотором роде, необходимо проверить его и поддерживать и разрешать общую информацию. Использование статической фабрики гарантирует, что мы можем применять улучшения к созданию объекта без необходимости изменения всех клиентов.

Мы применили множество сравнительных тестов и настроек, чтобы убрать некоторые узкие места производительности в самых последних выпусках и ClassTypeInformation никогда даже близко не подходил к анализу профиля.

Вообще говоря, я бы начал, прежде чем копаться во внутренностях низкого уровня:

  • По какой причине вы думаете, что вам нужно начинать распараллеливание вставок? MongoTemplate.insertAll(…) в основном это самый быстрый способ вставить объекты в MongoDB, если вы хотите использовать наши средства отображения объектов на документы. Внедрение параллелизма может на самом деле замедлить процесс, так как необходимость синхронизации возникает в первую очередь.
  • Почему вы думаете, создавая отдельные MongoTemplate случаи улучшают вещи? MongoTemplate является потокобезопасным, поэтому может быть разделен между потоками.
  • Рассматривали ли вы подключить пользовательские преобразователи, которые вручную превращают объекты в DBObject? По умолчанию мы должны использовать отражение, чтобы преобразовать первое в последнее, и это, конечно, требует затрат.
  • Вам действительно нужно начинать с объектов в первую очередь? Иногда данные, считанные из входного источника, могут быть отображены в DBObjectнепосредственно, что позволяет полностью обойти отображение объекта на документ.

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

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

Другие вопросы по тегам