问题
目前,我们的网站已设置好,以便在采取需要发送电子邮件的操作时,我们的网站将拨打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和文件附件)Message
到EmailTopic
与插入记录的MessageId
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
,我们将有一个过程尝试稍后插入它们。
问题
Topic
。显然,如果Service Bus
关闭,我们无法发送此消息,我不知道如何从中恢复,除了登录ETW并以其他方式检查它们。我应该首先尝试数据库保存吗?如果失败,请将Message
发送到Topic
?Topic
并在邮件中添加Label
,以便我们知道它是一个日志与电子邮件发送?也许使用过滤器(不知道如何正确地做到这一点或者它是否适合这个工作流程)?我认为可以通过跟踪和解决故障的方式改进工作流程。我正在提供解决方案来实现这一目标。
Service Bus Topics支持单个发件人的多个订阅者。这可以通过订阅帮助实现。
您可以在主题下创建两个订阅,而不是将消息发送到两个主题。请参阅here,使用规则将邮件过滤到订阅中。
您可以为订阅创建不同的规则。将消息发送到主题后,将根据每个订阅的规则验证消息的自定义属性。根据验证结果,消息将进入具有所需规则条件的订阅。
假设创建的订阅是电子邮件和日志。无状态服务结构服务应该从这些订阅中侦听消息。
网站应使用电子邮件订阅的自定义属性将消息发送到主题。
每当无状态服务结构服务收到消息时,它应该启动一个线程来发送邮件。
成功发送电子邮件后,应使用Log Subscription的自定义属性将Success消息发送到Topic。如果发送邮件失败,电子邮件订阅中的邮件应该是无效的,并且应该使用适当的日志订阅自定义属性向主题发送失败消息。
无状态服务结构服务也会监听来自日志订阅的消息,它将创建一个线程,以便在消息到达时写入数据库。如果写入数据库失败,则Log Subscription中的消息应该是死信。
您可以监控两个订阅的死信消息的数量,以确保没有失败。如果计数大于0,则应该在将死信消息重新提交到主题时进行手动干预。市场上可能有工具来监控和重新提交死信消息,或者您也可以开发自定义应用程序来执行此操作。
我想这个工作流程应该按预期工作。安装完成后,唯一需要注意的是订阅中的死信消息。