【发布时间】:2019-02-12 22:31:49
【问题描述】:
问题
目前,我们的网站已设置为当采取需要发送电子邮件的操作时,我们的网站将调用 SMTP 服务器以尝试发送电子邮件。问题出在 SMTP 服务器出于某种原因出现故障时。我们不会以任何方式存储任何外发电子邮件,因此如果要发送的电子邮件失败,它会永远丢失(不是真的,因为它可以很容易地重新生成,但我们没有机制让我们知道它失败了,除了Azure Application Insights)。虽然我们也让网站在发生异常时向开发人员发送电子邮件,但出于显而易见的原因,我们不会收到这些电子邮件。
目标
我们的目标是停止让我们的网站直接向电子邮件中继服务器发送电子邮件。相反,实施一个可以发送电子邮件并在出现问题时能够恢复的解决方案。
- 阻止网站发送电子邮件
- 能够从暂时或附带问题/异常中恢复
- 尽可能多地记录有关电子邮件的活动(发送尝试/失败/等)
- 能够从潜在的暂时性或附带问题/异常中恢复活动日志
- 如有必要,可以重新触发要发送的电子邮件(可选)
解决方案
我读过3-part article,听起来它可以解决这个问题,我目前正在开发它。
我正在使用 Microsoft.Azure.ServiceBus Topics 和 Subscriptions 构建一个流程来管理从我们的网站发送电子邮件。我经历了很多样本,并且已经成功地能够正确地SendAsync()Message、ReceiveAsync()Message、CompleteAsync() 或AbandonAsync()。
旁注:我现在正在探索如何使用RetryPolicy,看看这是否有助于我将重试推迟到更长的时间,尽管我不是确定我是否可以/应该使用它。
虽然到目前为止大部分流程都已构建,因此我可以了解底层基础架构,但我仍处于规划阶段,以确保我们进行适当的规划。
我们目前正在尝试为该流程找出最佳或最合适的工作流程。我们认为需要两个Topics:一个用于发送电子邮件EmailTopic,另一个用于记录LogTopic的日志。
LogTopic 的原因是为了在尝试将日志活动保存到数据库时处理任何暂时性问题。 例如: 我成功检索到要发送的电子邮件。然后我尝试发送电子邮件并记录此尝试。电子邮件已成功发送。然后我尝试记录此活动,但数据库刚刚关闭,我将无法记录此活动。第二个Topic 应该可以缓解这种情况,但如果这种情况下降会怎样?
这是我们当前的工作流程:
- 网站将数据插入到定义要发送的电子邮件的数据库中(目前,我们将有一个字段用于
Body,这将是电子邮件内容本身,另一个用于保存Email Templates的表将包含Body字段周围的内容,以及 from、to、CC、BCC 和文件附件) - 网站向
EmailTopic发送一个小Message,并带有插入记录的MessageId -
Stateless Service Fabric Service监听消息 - 接收
Message,从数据库中获取所有详细信息进行记录 - 构建
SMTPClient并尝试将电子邮件发送到 SMTP 服务器 - 向
LogTopic发送Message,并附上MessageId、当前日期、当前DeliveryCount和采取的措施(尝试发送电子邮件)- 如果成功,
CompleteAsync()Message并发送Message到LogTopic,MessageId、当前日期、当前DeliveryCount和采取的措施:“已发送电子邮件” - 如果不成功,
AbandonAsync()Message并发送一个Message到LogTopic,MessageId、当前日期、当前DeliveryCount和采取的措施:“电子邮件发送失败”(之后10 次尝试消息将自动放入DeadLetterQueue
- 如果成功,
在此工作流程中,LogTopic 将包含所有已采取的操作,并在收到消息时存储在数据库中。显然,如果消息因任何原因被放弃并发送DeadLetterQueue,我们将有一个过程在稍后尝试插入它们。
问题
- 我们曾考虑在工作流中仅将日志存储到数据库中,但问题是“如果数据库同时出现故障怎么办?” (因此上周 Azure Central US 出现故障时)出现了,所以我们决定使用第二个
Topic。显然,如果Service Bus已关闭,我们将无法发送此消息,我不知道如何从中恢复,除了记录 ETW 并以其他方式检查它们。我是否应该先尝试进行数据库保存,如果失败,请将Message发送到Topic? - 此服务中发生的事情太多,我是否应该拆分一些操作?
- 工作流程本身是否存在我们没有考虑到的缺陷或缺失项?
- 我们是否应该使用 1
Topic并在消息中添加Label,以便我们知道要发送的是日志还是电子邮件?也许使用过滤器(不确定如何正确执行此操作或是否适合此工作流程)? - 我们是否在这 1 个 SO 帖子中提出了太多问题,是否应该将每个问题分开?
【问题讨论】:
标签: c# azure azure-service-fabric azureservicebus