Наконец-то было время, чтобы правильно изучить это, вот что я обнаружил!
По умолчанию драйвер mongo java устанавливает так называемую проблему NONE/UNACKNOWLEDGED для записи всех и всех записей в mongodb. Это означает, что писать в mongodb очень асинхронный процесс. Водитель говорит: «Эй, сохраните все это, когда у вас есть шанс», и монго хранит его в конце концов, однако ответ немедленно возвращается в приложение и, следовательно, продолжается с потоком.
Объект Mongo's GridFSFile драйвера java имеет метод, называемый validate
, который можно вызвать после сохранения файла. Этот метод использует MD5, который был рассчитан в памяти драйвером java, когда поток был разделен на куски и отправлен в mongodb, а затем сравнивает его с результатами команды mmo filemd5. Когда mongo выдается запрос filemd5, он принимает предоставленный идентификатор и вычисляет MD5 на основе содержимого различных кусков двоичного массива, которые существуют со ссылками на предоставленный id (которые вместе представляют собой единый объект, который хранился в GridFS).
Что касается того, что вызывает у меня, чтобы увидеть частые несоответствия между вычисленным MD5 водителя и MD5 вернулся из Монго, в основном с по умолчанию для записи концерна NONE он возвращался управлением приложением и запустившей команды validate
/filemd5
сразу после , который mongo затем обрабатывает текущее состояние его содержимого. Возможно (и, по-видимому, так было), что MongoDB вычислял MD5 для идентификатора, прежде чем все было записано в память, и поэтому оно иногда возвращало плохой MD5.
Кроме того, это согласуется с тем, что было замечено в деталях отладки. После возникновения исключения я добавил регистрацию для запроса файла, который был сохранен и прочитал его содержимое, и в этот момент он всегда имел правильное содержимое и правильный MD5 ,
Решение заключается в том, что взаимодействие с драйверами mongo с GridFS должно использовать проблему записи, по меньшей мере, ACKNOWLEDGED, что означает, что данные, которые были записаны, по крайней мере сохраняются в памяти монго перед возвратом в приложение. Я установил это вручную для своих тестов и включил его для коллекций GridFS при запуске приложения, так как он еще не отображается как параметр конфигурации в весенних данных. Также стоит отметить, что новый java-драйвер mongo-3.x имеет проблему записи по умолчанию ACKNOWLEDGED, поэтому, как только я использую это, я теоретически смогу удалить дополнительную загрузку.
Что касается того, почему это никогда не было видно на местном уровне, вполне вероятно, что моя машина обладает доступной памятью и вычислительной мощностью, которую mongo требует для хранения содержимого достаточно быстро, чтобы к моменту, когда был вызван validate
, все было уже там, и поэтому MD5 вернулся правильно.Агент сборки, выполняющий множество параллельных тестов, находится под значительно более тяжелой нагрузкой и потенциально более ограниченными ресурсами, и поэтому mongodb не всегда заканчивал сохранение содержимого до того, как была выполнена команда filemd5.
Что касается проверки того, что это действительно исправлено, я ранее видел, что из-за этой проблемы не удалось выполнить 3-4 теста (из примерно 2000), и я теперь провел более 15 полных наборов тестов на сборке агентов и не видел его один раз.
Фактический код, я использую, чтобы исправить это:
private static final String GRID_FS_FILES_COLLECTION_NAME = "fs.files";
private static final String GRID_FS_CHUNKS_COLLECTION_NAME = "fs.chunks";
@Autowired
protected MongoOperations mongoOperations;
mongoOperations.getCollection(GRID_FS_FILES_COLLECTION_NAME).setWriteConcern(WriteConcern.ACKNOWLEDGED);
mongoOperations.getCollection(GRID_FS_CHUNKS_COLLECTION_NAME).setWriteConcern(WriteConcern.ACKNOWLEDGED);
Можете ли вы предоставить конкретный случай? Предпочтительно то, что можно воспроизвести. Наряду с версией вашего драйвера и версией сервера для справки. –
Вы подтвердили, что файлы действительно отличаются в этом случае? Если да, то какая разница? – Philipp
К сожалению, это произошло во время автоматической сборки. Я на самом деле еще не видел его при запуске локально. Я добавлю дополнительную информацию, если смогу воспроизвести ее. – RutledgePaulV