服务总线消息版本控制的最佳做法

本文关键字:最佳 版本控制 总线 消息 服务 | 更新日期: 2023-09-27 18:32:16

我正在设置一个系统,我们将在其中在服务总线主题上的多个内部服务之间传输消息。消息将保存序列化的对象。模型对象被定义为相当复杂的类树。这意味着在代码中维护模型结构的重复版本是不切实际的。

我们希望模型结构发生变化,因此我将模型版本公开为中转消息的属性。

当我们需要升级模型版本时,处理转换的最佳方法是什么?

我认为我们真的不需要支持两个并行模型版本。但我担心我们不会在过渡期间丢失信息。我认为首先升级发送服务并让所有订阅者继续处理消息是一个很好的策略。处理完以前版本的所有消息后,就该升级订阅服务了。

使用侦听服务当前未处理的新版本跳过消息的最佳机制是什么?

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

  2. 我注意到代理消息有一个延迟方法。那有用吗?它看起来很有希望,直到我意识到消息将从实时队列"移动"到一个单独的状态,需要通过按键引用它们来拉取它们。不切实际。

  3. 是否可以通过修改传递时间来推迟消息?几分钟就好了。如果到那时同一服务仍在运行,则可以再次推迟。(一个工作代码示例将不胜感激!

  4. 是否需要根据模型版本创建单独的订阅?到目前为止,我们允许不同的消息类型在同一主题上传播,因此需要进行一些重新设计。

服务总线消息版本控制的最佳做法

根据经验:实时系统上的升级很困难。将系统停机风险降至最低的最简单选项是:

  • 将下一消息版本支持添加到当前代码库
  • 同时运行两个消息版本
  • 确保所有版本都受支持,并且系统运行没有问题
  • 删除以前的版本

我一直在寻找类似的东西,但尚未实现它,因此无法提供完整的指导,但要回答您在 #3 上的问题......我有一些消息,它有一个标志来重新排队消息以再次运行,例如,让一个进程每 5 分钟运行一次。

因此,在此过程中,我从代理消息中提取对象:

  var myObject = receivedMessage.GetBody<MyModel>();  
然后,

我完成该消息以将其从队列中删除,并基于该对象创建新的代理消息,然后您可以将 ScheduledEnqueueTimeUtc 字段设置为将来的内容。

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

因此,如果您一次只想处理一个模型版本,则可以为模型分配一个版本号,并在处理器中编码某些内容以查找某个型号。如果模型更高,则将其重新排队以备将来使用(直到更新代码)。如果它较低(错过的消息),那么也许有一些异常处理。

对消息使用自定义MessageProperty,比如Version

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

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

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

现在您可以选择:

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