2015-03-17 1 views
1

Я делаю некоторые проверки GridFS MongoDB как двоичного хранилища, и во время моих тестов я встречал, в редких случаях, исключение, которое бросает драйвер (в моем случае, Java), когда я проверяю, что сохраненный файл действительно хранится должным образом. Эта валидация - это то, где Java-драйвер сравнивает свой вычисленный MD5 с содержимым, который он только что хранил, с MD5, указанным командой filemd5 от MongoDB.Что вызывает несоответствие хеша MongoDB/GridFS MD5?

Это исключение документированы, и я могу работать, чтобы справиться с этим правильно, но:

мой вопрос почему это происходит (очевидно, имеется бинарная несоответствие, но есть что-то, что заставляет это происходить чаще) ?

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

+0

Можете ли вы предоставить конкретный случай? Предпочтительно то, что можно воспроизвести. Наряду с версией вашего драйвера и версией сервера для справки. –

+0

Вы подтвердили, что файлы действительно отличаются в этом случае? Если да, то какая разница? – Philipp

+0

К сожалению, это произошло во время автоматической сборки. Я на самом деле еще не видел его при запуске локально. Я добавлю дополнительную информацию, если смогу воспроизвести ее. – RutledgePaulV

ответ

2

Наконец-то было время, чтобы правильно изучить это, вот что я обнаружил!

По умолчанию драйвер 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); 
+0

Какую версию драйвера Java вы используете? По умолчанию WriteConcern был ACKNOWLEDGED, поскольку 2.11.0, iirc. – jyemin

+0

Я не думаю, что беспокойство подтверждается до 3.x +. – RutledgePaulV

+0

Но я бежал 2.13 Я считаю, – RutledgePaulV