Как решить, какие исключения стоит повторить при чтении и записи в MongoDB (драйвер C #)?

Просматривая эту официальную документацию Кажется, что драйвер MongoDB C # выдает в основном три типа ошибок:

  • ошибки, возникающие, когда драйвер не может правильно выбрать или подключиться к серверу, чтобы отправить запрос. Эти ошибки приводят к TimeoutException
  • ошибки, возникающие, когда драйвер успешно выбрал сервер для выполнения запроса, но сервер отключается во время выполнения запроса. Эти ошибки проявляются как MongoConnectionException
  • ошибки, возникающие во время операций записи. Эти ошибки приводят к MongoWriteException или MongoBulkWriteException в зависимости от типа выполняемой операции записи.

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

Проблема не в реализации надежной политики повторных попыток (обычно я использую Polly .NET для этого), но вместо этого понимая, когда повторная попытка имеет смысл.

Я думаю, что повторная попытка при исключениях типа TimeoutException не имеет смысла, потому что сам драйвер ждет несколько секунд, прежде чем тайм-аут операции (по умолчанию 30 секунд, но вы можете изменить это с помощью параметров строки подключения). Идея состоит в том, что повторение операции после того, как вы подождали 30 секунд до истечения времени ожидания, вероятно, является пустой тратой времени. Например, если вы решите реализовать 3 повтора с интервалом ожидания в 1 секунду, то для сбоя операции потребуется до 93 секунд (30 + 30 + 30 + 1 + 1 + 1). Это огромное время.

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

Сложным моментом в выборе хорошей стратегии повтора для записи является случай, когда вы получаете исключение типа MongoWriteException или MongoBulkWriteException.

Что касается исключений типа MongoWriteException, вероятно, стоит повторить попытку всех исключений, имеющих ServerErrorCategory отличный от DuplicateKey. Как здесь вы можете обнаруживать повторяющиеся ключевые ошибки с помощью этого свойства объекта MongoWriteException.WriteError.

Повторная попытка повторяющихся ключевых ошибок, вероятно, не имеет смысла, потому что вы получите их снова (это не временная ошибка).

Я понятия не имею, как безопасно обрабатывать ошибки типа MongoBulkWriteException. В этом случае вы вставляете несколько документов в MongoDB, и вполне возможно, что только некоторые из них вышли из строя, в то время как другие были успешно записаны в MongoDB. Таким образом, повторная попытка одной и той же операции массовой вставки может привести к двойной записи одного и того же документа (массовая запись не идемпотентна по своей природе). Как я могу справиться с этим сценарием?

Есть ли у вас предложения ?

Знаете ли вы какой-либо рабочий пример или ссылку относительно повторных запросов в MongoDB для драйвера C #?


person Enrico Massone    schedule 30.08.2019    source источник
comment
Никто!!! Пункт 1: Просто увеличьте время ожидания соединения. 2) Если сервер выходит из строя в середине вставки, вы получите повторяющиеся записи в базе данных. 3) Опять же, если вы пишете более одной строки, вы получите дубликаты.   -  person jdweng    schedule 30.08.2019
comment
@jdweng Я не уверен, что никогда не повторять операцию - лучший выбор. Например, почему бы мне не повторить неудачную операцию чтения, если во время чтения возникает исключение MongoConnectionException? Опять же, почему бы мне не повторить операцию InsertOne, когда возникает исключение MongoWriteException из-за временной медлительности сервера во время операции записи?   -  person Enrico Massone    schedule 31.08.2019
comment
Настоящий вопрос заключается в том, хотите ли вы ПОВТОРИТЬ ПОВТОР, когда вы получаете ошибку и в конечном итоге получаете повторяющиеся записи в базе данных? Вы всегда должны сообщать об ошибках.   -  person jdweng    schedule 31.08.2019
comment
@jdweng вы предлагаете пропустить повторные попытки даже при чтении из mongodb (в этом случае нет возможности повредить данные вообще)?   -  person Enrico Massone    schedule 03.09.2019
comment
Почему чтение дает ошибки? Вы хотите исследовать ошибки перед повторной попыткой? Как вы думаете, действительно ли сработает повторная попытка? Мне не нравится повторять попытку, когда на уровне TCP уже есть метод повтора. Шансы на то, что повторная попытка сработает, очень мала.   -  person jdweng    schedule 03.09.2019
comment
@jdweng Я понимаю вашу точку зрения. Когда вы говорите, что на уровне TCP уже есть метод повтора, что вы конкретно имеете в виду? Вы имеете в виду тайм-аут MongoClient, когда он пытается найти сервер, способный обработать его запрос? Или, вместо этого, вы имеете в виду встроенный механизм повтора запроса, реализованный в драйвере MongoDB C # (я не знаю его внутреннего устройства, может быть, у вас лучше, чем у меня)   -  person Enrico Massone    schedule 03.09.2019
comment
HTTP использует TCP в качестве транспортного уровня. Если у вас есть MongoClient, это веб-приложение / http. Таким образом, для любых данных, передаваемых через Интернет, выполняется повторная попытка. Если вы превышаете время ожидания запроса MongoClient к базе данных, повторная попытка в большинстве случаев не удастся, и время ожидания следует увеличить.   -  person jdweng    schedule 03.09.2019
comment
@jdweng хорошо, спасибо за ваши комментарии, теперь я понял вашу точку зрения. Может быть, обычный ответ на мой вопрос будет полезен для обычных читателей.   -  person Enrico Massone    schedule 03.09.2019


Ответы (1)


Повторить

Начнем с основ Retry.

Бывают ситуации, когда запрошенная операция зависит от ресурса, который может быть недоступен в определенный момент времени. Другими словами, может возникнуть временная проблема, которая рано или поздно исчезнет. Проблемы такого рода могут вызывать временные сбои. С помощью повторных попыток вы можете решить эти проблемы, попытавшись повторить ту же операцию в определенный момент в будущем. Чтобы использовать этот механизм, необходимо соответствие следующей группе критериев:

  • Возможное наблюдаемое воздействие приемлемо.
  • Операцию можно повторить без необратимых побочных эффектов.
  • Введенная сложность ничтожна по сравнению с обещанной надежностью.

Давайте рассмотрим их по очереди:

  • Слово «сбой» указывает на то, что эффект также наблюдается и для запрашивающей стороны, например, через более высокую задержку / снижение пропускной способности и т. Д. Если «штраф» (задержка или снижение производительности) неприемлем, то повторная попытка для вас не вариант.
  • Это требование также известно как идемпотентная операция. Если я вызову действие с одним и тем же вводом несколько раз, оно даст точно такой же результат. Другими словами, операция действует так, как будто она зависит только от своего параметра, и ничто другое не влияет на результат (как состояние других объектов).
  • Это условие, хотя и является одним из самых важных, о нем почти всегда забывают. Как всегда, есть компромиссы (если я введу Z, это увеличит X, но может уменьшить Y), и мы должны полностью осознавать их. Если только это не преподнесет нам несколько нежелательных сюрпризов в наименьшее ожидаемое время.

Исключение Mongo

Продолжим с исключениями, которые может выдавать клиент MongoDb C #.

Я не использовал MongoDb последние пару лет, поэтому эти знания, возможно, устарели. Но надеюсь, с тех пор суть не изменилась.

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

  • MongoConnectionException with a SocketException as Inner
    • When:
      • There is server selection problem
      • Время соединения истекло
      • Выбранный сервер недоступен
    • Retry:
      • If the problem is due to network issue then it might be useful to retry
      • Если основная причина - неправильная конфигурация, повторная попытка не поможет.
    • Log:
  • MongoWriteException or MongoWriteConcernException
person Peter Csala    schedule 25.02.2021