2

背景

假设您有一个 (SOAP) Web 服务,BookService用于管理图书馆中的书籍。在信息模型中假设Book实体具有以下属性:

  • id
  • author
  • publisher
  • title
  • shelfId

为了操作数据,定义了四个 Web 服务操作:

  • AddBook
  • GetBook
  • UpdateBook
  • DeleteBook

为每个操作定义请求和响应消息。但是,更新消息 XML 模式的设计更为复杂。我们希望达到以下品质:

  • R1:重置/删除属性的先前值的可能性。例如,说您不再将书保留在图书馆中,因此想重置/清空/删除该shelfId特定书的属性的属性值。
  • R2:避免网络服务中的喋喋不休。请参阅反模式 Chatty Services
  • R3:为未来对并发控制和乐观锁定的需求做准备。我们可能希望最小化(或消除)根据旧信息进行更新的风险。

设计方案

我看到了三个市长备选方案,其中一个有几个子选项来设计更新消息:

  1. 发送整个业务文件。被遗漏的元素(minOccurs="0"在模式中)或元素明确设置为空,即<shelfId xsi:nil="true"/>,将被解释为删除先前的值。
  2. 突出显示更改或仅发送差异。
    1. 发送整个业务文档,但使用特定于此目的的属性标记修改的元素。示例:<author dirty="true">Hemingway<author/>。然后,服务的提供者只更新那些标记为脏的元素并忽略其他元素。
    2. 在消息模式中,将除标识符之外的所有元素设置id为具有minOccurs="0"。消费者发送那些要修改的元素。遗漏的元素不能在语义上被解释为删除。为了删除一个值,NULL必须使用显式 XML 值。示例:<shelfId xsi:nil="true"/>
    3. 发送整个业务文件,同时提交之前阅读文件的副本。然后,提供者可以比较两个文档并更新新文档和先前文档不同的那些属性。
  3. 定义多个操作。不是只使用一个操作,而是UpdateBook根据您认为必须更新的元素定义多个操作,例如UpdateBookAuthorUpdateBookPublisher等等。这些中的每一个都将只有强制元素,并且要删除元素,请使用 XML 的显式 NULL,例如<shelfId xsi:nil="true"/>.

讨论

替代 3的优点是易于理解,但缺点是消费者需要调用多个操作,以防Book要更新实体中的多个字段。这使得服务“健谈”(参见上面的 R3),从而导致性能下降。

Alt 2Alt 1更复杂,但Alt 2有一些与乐观并发控制相关的优点:

  • 对于每个字段的时间戳/版本的乐观锁定存储在数据库中的情况(例如authorVersion)=> Alt 2提供了一种让多个用户同时修改相同部分的不同部分的方法,例如authorpublisherBook同时发生故障的风险较小。
  • 对于在数据库中存储一个完整的单个时间戳/版本的乐观锁定的情况=> Alt 2相对于Alt 1Book没有真正的优势。即使更新只修改了一个字段,请求的版本号太旧也会导致错误。
  • 对于不使用并发控制或乐观/悲观锁定的情况 =>替代2比替代1提供的覆盖旧数据的风险更小,但其他不一致的更改可能会带来问题。

还有另一种情况,其中Alt 2(和Alt 3 )比Alt 1具有优势。消费者可能不会存储有关Book实体的所有数据。例如,如果机器人在更新书架信息时不需要跟踪(缓存)关于作者的信息,而只需要跟踪书架,则可以更有效地对从书架上挑选书籍的机器人进行编程。

替代2.3中的方法的一个优点是,消费者提交以前版本的完整副本而不是版本号或时间戳,即版本号或时间戳不需要数据库中的专用列。

总而言之,我会说Alt 2.2在大多数情况下看起来是最有吸引力的。这里的挑战在于反序列化 XML 的框架必须能够区分遗漏元素和显式设置为 NULL 的元素,例如<shelfId xsi:nil="true"/>. 在此处查看有关此主题的帖子。

问题

您会选择哪种选择?您是否看到其他更好的选择?你怎么看讨论?

4

1 回答 1

1

正如您已经讨论过的,替代 2.2 似乎相当可行。然而,minoccurs=0 和 nil 之间的区别经常被框架忽略,并且对于许多用户来说也很难理解(可能是这个接口)。因此,我会选择一种变体,在一个更改消息中,当您希望它们被取消时,您明确地标记每个属性。

etag 可能是用于乐观锁定的一种标准。我认为您已经广泛讨论了锁定机制的含义。它应该按照您描述的方式工作。

Alt 1 在消息设计和使用/实现方面都简单得多,如果流量不是问题并且对整个对象进行乐观锁定就足够了(恕我直言,这通常是这种情况),那也可以很好地工作。

您还应该考虑到,对于某些业务流程,不同属性的更改是相互依赖的,因此对属性进行单独的版本控制是没有意义的,因为即使只有另一个属性已过时,一个属性的更改也可能是错误的变化的时间。

如果是这种情况,这是替代 1 的另一个原因。

于 2014-07-11T13:01:05.497 回答