.net core 当实体状态更改时向主题发送消息的模式
我们正在使用Azure服务总线在应用程序中的某个实体更改为某个状态时通知订阅者。现在,我们在调用dbContext.saveChangesSync()之后立即执行此操作:.net core 当实体状态更改时向主题发送消息的模式,.net-core,entity-framework-core,azureservicebus,azure-servicebus-topics,.net Core,Entity Framework Core,Azureservicebus,Azure Servicebus Topics,我们正在使用Azure服务总线在应用程序中的某个实体更改为某个状态时通知订阅者。现在,我们在调用dbContext.saveChangesSync()之后立即执行此操作: dbContext.saveChangesSync() topicClient.SendAsync(someMessage) 我遇到的问题是:假设dbContext.savechangessync()运行正常,但无论出于何种原因,对topicClient.SendAsync()的调用都会引发异常。现在,此主题的订阅者将不会知道
dbContext.saveChangesSync()
topicClient.SendAsync(someMessage)
提前感谢您。您可以实现名为或的模式。还有其他已知的同义词,如
重试队列
我们的想法是尝试一个操作,如果没有成功,将一些元信息放入队列中,稍后重试该操作。在您的情况下,在调用了dbContext.savechangesync()
之后,您可以将所有必要的信息放入持久的队列中,并拥有一个处理程序来处理该队列,在某种ProcessMessage()
中,您可以处理
topicClient.SendAsync(someMessage)
例如,如果对服务总线的调用未成功,则可以将队列项返回队列中,以便稍后进行处理
当然,您可以将所提到的队列专用于topicClient.SendAsync(someMessage)
的失败调用,这可以显著减少其大小。操作顺序无关紧要,因为您可以放置任何元信息,这使得调用topicClient.SendAsync(someMessage)成为可能
首先,然后尝试更新数据库。这不是您面临的问题的直接答案,但我将分享我们如何在一个应用程序中解决类似问题,我们必须将数据写入Azure表存储中的单独表中。因为我们将数据写入单独的表,所以无法使用Azure表存储中可用的实体批处理事务功能
我们解决这个问题的方法是实现类似于最终一致性模式的东西
我们所做的不是直接在表中保存数据(这意味着发出多个网络请求,其中任何一个都可能失败),而是将需要保存的数据发送到队列(我们使用存储队列)。如果我们能够将数据保存在队列中,这意味着数据最终将可用
然后我们编写了一个Azure队列触发函数。在该函数中,我们将数据保存在需要保存的表中。一旦所有操作成功,函数运行时将自动删除消息。如果任何操作失败,消息将再次发送到队列并再次退出队列
现在需要了解的一件重要事情是,这些save方法必须是幂等的。假设我们正在写入3个表,第一个表的写入操作成功,但第二个表的写入操作失败。下次调用该函数时,它将再次尝试写入第一个表,代码应该能够优雅地处理它。正如您所概述的,操作顺序无关紧要,因为数据库和消息传递服务这两个服务之间没有重叠的事务。如果您正在使用的数据存储支持事务(例如Azure SQL server),则无需使用两阶段提交,您就可以离开,并研究如何实现事务
NServiceBus将该模式作为一个组件提供。您可以下载发件箱,该发件箱显示了如何将其与RabbitMQ一起使用。运输工具可更换为,以满足您的要求
披露:我为NServiceBus做出了贡献。非常感谢。我会调查的。非常感谢。我将对此进行检查。正如您所建议的,我最终使用了事务发件箱模式,以及IHostedService实现来监视发件箱表。谢谢你的建议,很抱歉我花了这么长时间才回复。很高兴听到这正是你想要的。很高兴听到你的确认,谢谢。