ServiceBus消息版本控制的最佳实践

5

我正在建立一个系统,在该系统中,我们将在ServiceBus主题之间传输多个内部服务之间的消息。这些消息将包含序列化对象。模型对象被定义为相当复杂的类树。这意味着在代码中维护模型结构的重复版本不是实际可行的。

我们预计模型结构会发生变化,因此我已经将模型版本作为一个属性暴露在代理消息上。

在需要升级模型版本时,最佳的处理方式是什么?

我认为我们不需要支持两个并行的模型版本。但我担心在过渡期间不会丢失消息。我假设最好的策略是先升级发送服务,并让所有订阅者继续处理消息。当所有旧版本的消息都被处理完毕后,就可以升级订阅服务了。

跳过具有当前监听服务无法处理的新版本的消息的最佳机制是什么?

  1. 我知道我可以回到老学派,通过使用json或xml模式来定义并行的模型版本,从而使监听服务能够处理并行版本。但这很麻烦,所以我真的想避免这种情况。

  2. 我注意到BrokeredMessage有一个Defer方法。这会有用吗?它看起来很有前途,直到我意识到消息将从活动队列移动到一个单独的状态,在那里需要通过引用它们的键来拉取它们。这不是实际可行的。

  3. 通过修改传送时间来推迟消息是否可能?几分钟是可以接受的。如果同一服务仍然运行,它可以再次被推迟。(如果您能提供一个有效的代码示例,那会很棒!)

  4. 我需要基于模型版本创建单独的订阅吗?到目前为止,我们允许不同类型的消息在同一个主题上流转,因此这需要进行一些重新设计。

3个回答

2

一般来说,在运行中的系统上进行升级是很困难的。最简单的选项是尽量减少系统停机的风险:

  • 将下一个消息版本支持添加到当前代码库
  • 同时运行两个消息版本
  • 确保所有版本都得到支持,系统运行正常
  • 删除先前的版本

1
我一直在研究类似的东西,但还没有实施,因此无法提供完整的指导。但是回答你关于#3的问题...我有一些消息,其中有一个标志可以重新排队消息以再次运行,例如每5分钟运行一次进程。
因此,在进程中,我从BrokeredMessage中提取对象:
  var myObject = receivedMessage.GetBody<MyModel>();  

然后,我会完成该消息以将其从队列中删除,并基于该对象创建一个新的BrokeredMessage,然后您可以将ScheduledEnqueueTimeUtc字段设置为未来某个时间。

 BrokeredMessage brokeredMsg = new BrokeredMessage(myObject);
 brokeredMsg.ScheduledEnqueueTimeUtc = DateTime.UtcNow.AddMinutes(5);
 Client.Send(brokeredMsg);

如果您只想一次处理一个模型版本,您可以为您的模型分配一个版本号,并编写一些代码来查找特定的模型编号以供您的处理器使用。如果模型更高,则重新排队以在将来的某个时间进行处理(直到您更新了代码)。如果较低(错过的消息),则可能需要进行一些异常处理。

1

使用自定义的MessageProperty在消息上,例如Version

在SB主题下 - 创建新的订阅,仅接受具有新版本的消息(使用规则),并修改现有订阅以不接受新版本消息。

然后可以升级发件人 - 新消息将仅存储在新的“临时”订阅中。

之后,升级侦听器,更改订阅上的规则(从“主”订阅中删除版本规则,在临时订阅上禁用接收)。

现在你可以选择:

  • 使用任何工具从临时订阅中读取消息并将它们写回到主题中 - 它们将到达升级后的侦听器。
  • 暂时启动一个额外的侦听器,读取临时订阅中的所有消息并处理它们
  • 其他特定于您的架构的方法

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接