Microsoft Azure Service Bus主题保存到数据库的工作流程

问题描述 投票:0回答:1

问题

目前,我们的网站已设置好,以便在采取需要发送电子邮件的操作时,我们的网站将拨打SMTP服务器以尝试发送电子邮件。问题在于SMTP服务器由于某种原因而关闭。我们不会以任何方式存储任何外发电子邮件,因此如果要发送的电子邮件失败,它将永远丢失(不是因为它可以很容易地重新生成,但我们没有机制让我们知道它失败了,除了Azure Application Insights)。虽然我们也有网站在发生异常时向开发者发送电子邮件,但由于显而易见的原因,我们不会收到这些电子邮件。

目标

我们的目标是停止让我们的网站直接向电子邮件中继服务器发送电子邮件。相反,实施一个可以发送电子邮件的解决方案,并且能够在出现问题时进行恢复。

  1. 阻止网站发送电子邮件
  2. 能够从瞬态或侧面问题/异常中恢复
  3. 记录有关电子邮件的尽可能多的活动(发送尝试/失败/等)
  4. 能够从潜在的瞬态或侧面问题/异常中恢复活动日志
  5. 能够在必要时重新触发要发送的电子邮件(可选)

我读了一个3-part article,听起来它会解决这个问题,我正在开发它。

我正在使用Microsoft.Azure.ServiceBus TopicsSubscriptions构建一个流程来管理从我们网站发送电子邮件。我已经经历了很多样本​​,并且已经成功地将SendAsync() MessageReceiveAsync()Message以及CompleteAsync()AbandonAsync()成功地进行了对比。

旁注:我现在正在探索如何使用RetryPolicy来看看这是否会帮助我将重试延迟到更长的时间,尽管我不确定我是否可以/应该使用它。

虽然到目前为止已经构建了大部分流程,因此我可以理解底层基础架构,但我仍然处于规划阶段,以确保我们进行适当的规划。

我们目前正在尝试找出此流程的最佳或最合适的工作流程。我们认为需要两个Topics:一个用于发送EmailTopic的电子邮件,另一个用于记录LogTopic的日志。

LogTopic的原因是在尝试将日志活动保存到数据库时处理任何瞬态问题。例如:我成功检索了要发送的电子邮件。然后我尝试发送电子邮件并记录此尝试。电子邮件已成功发送。然后我尝试记录此活动,但数据库刚刚关闭,我将无法记录此活动。第二个Topic应该可以减轻这一点,但是如果下降会发生什么?

这是我们当前的工作流程:

  1. 网站将数据插入到定义要发送的电子邮件的数据库中(目前,我们将为Body提供一个字段,该字段将是电子邮件内容本身,另一个用于保存Email Templates的表,其中包含Body字段周围的内容,与from,to,CC,BCC和文件附件)
  2. 网站发送一个小MessageEmailTopic与插入记录的MessageId
  3. 一个Stateless Service Fabric Service听取消息
  4. 收到Message,从数据库中获取所有详细信息以备记录
  5. 构建SMTPClient并尝试将电子邮件发送到SMTP服务器
  6. 发送MessageLogTopicMessageId,当前日期,当前DeliveryCount,并采取行动(尝试发送电子邮件) 如果成功,CompleteAsync() Message并发送MessageLogTopicMessageId,当前日期,当前DeliveryCount,并采取行动:“发送电子邮件” 如果不成功,AbandonAsync() Message并发送MessageLogTopicMessageId,当前日期,当前DeliveryCount,并采取行动:“电子邮件未能发送”(10次尝试后消息将自动放入DeadLetterQueue

在此工作流程中,LogTopic将包含所有已采取的操作,并将在收到消息时存储在数据库中。显然,如果消息因任何原因被放弃并发送了DeadLetterQueue,我们将有一个过程尝试稍后插入它们。

问题

  1. 我们考虑过只在工作流程中将日志存储到数据库,但问题是“如果数据库在此期间出现故障会怎么样?” (因此当Azure Central美国上周停工时)出现了,所以我们决定使用这个第二个Topic。显然,如果Service Bus关闭,我们无法发送此消息,我不知道如何从中恢复,除了登录ETW并以其他方式检查它们。我应该首先尝试数据库保存吗?如果失败,请将Message发送到Topic
  2. 这项服务中是否有太多事情发生,我应该分开一些操作吗?
  3. 我们没有考虑到工作流程本身是否存在缺陷或缺失项目?
  4. 我们应该使用1 Topic并在邮件中添加Label,以便我们知道它是一个日志与电子邮件发送?也许使用过滤器(不知道如何正确地做到这一点或者它是否适合这个工作流程)?
  5. 我们在这篇SO帖子中提出了太多问题,应该将每个问题分开吗?
c# azure azure-service-fabric azureservicebus
1个回答
2
投票

我认为可以通过跟踪和解决故障的方式改进工作流程。我正在提供解决方案来实现这一目标。

Service Bus Topics支持单个发件人的多个订阅者。这可以通过订阅帮助实现。

您可以在主题下创建两个订阅,而不是将消息发送到两个主题。请参阅here,使用规则将邮件过滤到订阅中。

您可以为订阅创建不同的规则。将消息发送到主题后,将根据每个订阅的规则验证消息的自定义属性。根据验证结果,消息将进入具有所需规则条件的订阅。

假设创建的订阅是电子邮件和日志。无状态服务结构服务应该从这些订阅中侦听消息。

网站应使用电子邮件订阅的自定义属性将消息发送到主题。

每当无状态服务结构服务收到消息时,它应该启动一个线程来发送邮件。

成功发送电子邮件后,应使用Log Subscription的自定义属性将Success消息发送到Topic。如果发送邮件失败,电子邮件订阅中的邮件应该是无效的,并且应该使用适当的日志订阅自定义属性向主题发送失败消息。

无状态服务结构服务也会监听来自日志订阅的消息,它将创建一个线程,以便在消息到达时写入数据库。如果写入数据库失败,则Log Subscription中的消息应该是死信。

您可以监控两个订阅的死信消息的数量,以确保没有失败。如果计数大于0,则应该在将死信消息重新提交到主题时进行手动干预。市场上可能有工具来监控和重新提交死信消息,或者您也可以开发自定义应用程序来执行此操作。

我想这个工作流程应该按预期工作。安装完成后,唯一需要注意的是订阅中的死信消息。

© www.soinside.com 2019 - 2024. All rights reserved.