Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net core 当实体状态更改时向主题发送消息的模式_.net Core_Entity Framework Core_Azureservicebus_Azure Servicebus Topics - Fatal编程技术网

.net core 当实体状态更改时向主题发送消息的模式

.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()的调用都会引发异常。现在,此主题的订阅者将不会知道

我们正在使用Azure服务总线在应用程序中的某个实体更改为某个状态时通知订阅者。现在,我们在调用dbContext.saveChangesSync()之后立即执行此操作:

  • dbContext.saveChangesSync()

  • topicClient.SendAsync(someMessage)

  • 我遇到的问题是:假设dbContext.savechangessync()运行正常,但无论出于何种原因,对topicClient.SendAsync()的调用都会引发异常。现在,此主题的订阅者将不会知道实体状态的更改

    我尝试过使用TransactionScope,但没有成功,因为据我所知,Azure没有使用DTC

    (我可以切换上述两个步骤的顺序,但如果消息发送正常,并且保存失败,则消息包含虚假数据。)

    有人对如何处理这个问题有什么建议吗?它看起来应该很普通,但我在网上找不到任何东西。如果有人能给我指出正确的方向,我将不胜感激


    提前感谢您。

    您可以实现名为或的模式。还有其他已知的同义词,如
    重试队列

    我们的想法是尝试一个操作,如果没有成功,将一些元信息放入队列中,稍后重试该操作。在您的情况下,在调用了
    dbContext.savechangesync()
    之后,您可以将所有必要的信息放入
    持久的
    队列中,并拥有一个处理程序来处理该队列,在某种
    ProcessMessage()
    中,您可以处理
    topicClient.SendAsync(someMessage)

    例如,如果对服务总线的调用未成功,则可以将队列项返回队列中,以便稍后进行处理


    当然,您可以将所提到的队列专用于
    topicClient.SendAsync(someMessage)
    的失败调用,这可以显著减少其大小。操作顺序无关紧要,因为您可以放置任何元信息,这使得调用
    topicClient.SendAsync(someMessage)成为可能
    首先,然后尝试更新数据库。

    这不是您面临的问题的直接答案,但我将分享我们如何在一个应用程序中解决类似问题,我们必须将数据写入Azure表存储中的单独表中。因为我们将数据写入单独的表,所以无法使用Azure表存储中可用的实体批处理事务功能

    我们解决这个问题的方法是实现类似于
    最终一致性模式的东西

    我们所做的不是直接在表中保存数据(这意味着发出多个网络请求,其中任何一个都可能失败),而是将需要保存的数据发送到队列(我们使用存储队列)。如果我们能够将数据保存在队列中,这意味着数据最终将可用

    然后我们编写了一个Azure队列触发函数。在该函数中,我们将数据保存在需要保存的表中。一旦所有操作成功,函数运行时将自动删除消息。如果任何操作失败,消息将再次发送到队列并再次退出队列


    现在需要了解的一件重要事情是,这些save方法必须是幂等的。假设我们正在写入3个表,第一个表的写入操作成功,但第二个表的写入操作失败。下次调用该函数时,它将再次尝试写入第一个表,代码应该能够优雅地处理它。

    正如您所概述的,操作顺序无关紧要,因为数据库和消息传递服务这两个服务之间没有重叠的事务。如果您正在使用的数据存储支持事务(例如Azure SQL server),则无需使用两阶段提交,您就可以离开,并研究如何实现事务

    NServiceBus将该模式作为一个组件提供。您可以下载发件箱,该发件箱显示了如何将其与RabbitMQ一起使用。运输工具可更换为,以满足您的要求


    披露:我为NServiceBus做出了贡献。

    非常感谢。我会调查的。非常感谢。我将对此进行检查。正如您所建议的,我最终使用了事务发件箱模式,以及IHostedService实现来监视发件箱表。谢谢你的建议,很抱歉我花了这么长时间才回复。很高兴听到这正是你想要的。很高兴听到你的确认,谢谢。