Задача
В настоящее время наш веб-сайт настроен таким образом, что при выполнении действия, требующего отправки электронного письма, наш веб-сайт вызывает сервер SMTP, чтобы попытаться отправить электронное письмо. Проблема заключается в том, что SMTP-сервер отключается по какой-либо причине. Мы не храним никаких исходящих сообщений, поэтому, если отправляемое письмо не удается, оно теряется навсегда (на самом деле это не так просто, как его можно легко восстановить, но у нас нет механизма, позволяющего нам знать, что это не удалось, кроме Azure Application Insights
). Хотя у нас также есть веб-сайт, отправляющий разработчикам электронное письмо при возникновении исключений по понятным причинам, мы не будем получать эти электронные письма.
Цель
Нашей целью является прекращение отправки нашего веб-сайта электронной почты непосредственно на сервер ретрансляции электронной почты. Вместо этого, внедрите решение, которое будет отправлять электронные письма и иметь возможность восстановления в случае возникновения проблемы.
- Не разрешать веб-сайту отправлять электронные письма
- Возможность восстановления после временных или побочных проблем / исключений
- Зарегистрируйте как можно больше действий, связанных с электронной почтой (попытки отправки / неудачи / и т.д.)
- Возможность восстановления журналов активности от потенциальных временных или побочных проблем / исключений
- Возможность повторно инициировать отправку электронного письма при необходимости (необязательно)
Решение
Я прочитал статью из 3 частей , которая звучит так, как будто это решит эту проблему, и сейчас я ее разрабатываю.
Я строю процесс, используя Microsoft.Azure.ServiceBus Topics
и Subscriptions
для управления отправкой электронной почты с нашего веб-сайта. Я прошел через множество сэмплов и смог успешно SendAsync()
a Message
, ReceiveAsync()
a Message
и CompleteAsync()
или AbandonAsync()
соответственно.
Примечание: Сейчас я изучаю, как работать с RetryPolicy , чтобы посмотреть, поможет ли это отложить повторную попытку на более длительный период, хотя я я не уверен, смогу ли я / должен использовать это для этого.
Хотя большая часть процесса уже построена, поэтому я могу понять базовую инфраструктуру, но я все еще на стадии планирования, чтобы убедиться, что мы планируем должным образом.
В настоящее время мы пытаемся определить лучший или наиболее подходящий рабочий процесс для этого процесса. Мы полагали, что понадобятся два Topics
: один для отправляемых писем EmailTopic , а другой для журналов для записи LogTopic .
Причина LogTopic
состоит в том, чтобы обрабатывать любые временные проблемы при попытке сохранить активность журнала в базе данных. Например: Я успешно получаю электронное письмо для отправки. Затем я пытаюсь отправить электронное письмо и зарегистрировать эту попытку. Письмо успешно отправлено. Затем я пытаюсь зарегистрировать это действие, но база данных просто отключилась, и я не смог бы зарегистрировать это действие. Второй Topic
должен смягчить это, но что произойдет, если это пойдет на убыль?
Вот наш текущий рабочий процесс:
- Веб-сайт вставляет данные в базу данных, которая определяет отправляемое электронное письмо (в настоящее время у нас будет поле для
Body
, которое будет само содержимым электронной почты, другая таблица для хранения Email Templates
, которая будет содержать содержимое вокруг поля Body
, а также из, в, CC, BCC и вложения файлов)
- Сайт отправляет небольшой
Message
на EmailTopic
с MessageId
вставленной записи
- A
Stateless Service Fabric Service
прослушивает сообщения
- Получите
Message
, получите все данные из базы данных для записи
- Создайте
SMTPClient
и попытайтесь отправить электронное письмо на SMTP-сервер
- Отправьте
Message
на LogTopic
с MessageId
, текущей датой, текущей DeliveryCount
и предпринятыми действиями (попытка отправить электронное письмо)
- В случае успеха
CompleteAsync()
Message
и отправить Message
на LogTopic
с MessageId
, текущей датой, текущей DeliveryCount
и предпринятыми действиями: «электронная почта отправлена» - В случае неудачи
AbandonAsync()
Message
и отправить Message
на LogTopic
с MessageId
, текущей датой, текущей DeliveryCount
и предпринятыми действиями: «электронная почта не отправлена» (после Сообщение 10 попыток будет автоматически помещено в DeadLetterQueue
В этом рабочем процессе LogTopic
будет содержать все предпринятые действия и будет сохранен в базе данных, когда сообщение (я) получено (получено). Очевидно, что если сообщения по какой-либо причине были оставлены и отправлены DeadLetterQueue
, у нас будет процесс, который попытается вставить их позже.
Вопросы
- Мы думали о том, чтобы просто хранить журналы в базе данных в рамках рабочего процесса, но вопрос "а что, если БД выйдет из строя за это время?" (следовательно, когда Azure Central US вышел из строя на прошлой неделе), мы решили использовать это 2
Topic
. Очевидно, что если Service Bus
не работает, мы не можем отправить это сообщение, и я не знаю, как его восстановить, за исключением регистрации ETW и проверки их другим способом. Должен ли я сначала попытаться сохранить БД, а если это не удастся, отправить Message
на Topic
?
- Слишком много вещей происходит в этом сервисе, и я должен разделить некоторые операции вокруг?
- Есть ли недостатки или недостающие элементы в самом рабочем процессе, которые мы не учитываем?
- Должны ли мы использовать 1
Topic
и добавить Label
к сообщению, чтобы мы знали, что это журнал и электронное письмо для отправки? Может быть, вы используете фильтры (не знаете, как это правильно сделать, или пока это подходит для этого рабочего процесса)?
- Мы задаем слишком много вопросов в этом 1 SO сообщении и должны разделить каждый вопрос на части?