Использование 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 доступа к данным, как правило, противоречит цели получения большей производительности. Вместо того, чтобы придерживаться удобства и пытаться распараллелить все, часто легче избавиться от некоторых удобных вещей, чтобы избежать дорогостоящих путей кода.
Если вы действительно обнаружите какие-либо проблемы с настройкой по умолчанию, мы будем рады получить отчет об ошибке с некоторыми доказательствами ваших выводов (исполняемый тестовый пример или тому подобное), чтобы посмотреть, что мы можем улучшить. Но я думаю, что полезно начать с простого и не пытаться быть слишком умным с самого начала.