Web services 您的Web服务版本控制最佳实践是什么?
我们有两个独立的产品需要通过web服务相互通信。 支持API版本化的最佳实践是什么 我从2004年开始就声称没有实际的标准,只有最佳实践。有更好的解决办法吗?如何解决WS版本控制问题 问题描述 系统A 客户 服务 可转让对象 版本1 版本2 请求对象 版本1 版本2 系统B 客户 服务 可转让对象 版本1 版本2 请求对象 版本1 版本2 失败场景 如果第1版的系统a客户端调用第2版的系统B服务,它可能会在以下方面失败:Web services 您的Web服务版本控制最佳实践是什么?,web-services,architecture,versioning,Web Services,Architecture,Versioning,我们有两个独立的产品需要通过web服务相互通信。 支持API版本化的最佳实践是什么 我从2004年开始就声称没有实际的标准,只有最佳实践。有更好的解决办法吗?如何解决WS版本控制问题 问题描述 系统A 客户 服务 可转让对象 版本1 版本2 请求对象 版本1 版本2 系统B 客户 服务 可转让对象 版本1 版本2 请求对象 版本1 版本2 失败场景 如果第1版的系统a客户端调用第2版的系统B服务,它可能会在以下方面失败: SystemBObject(getYear(),getMonth(),g
(SystemBObject
,getYear()
,getMonth()
)上缺少方法getDay()
- 未知类型
BDate
上的未知类型SomethingFromBRequest
(客户端使用B版本1无法识别的较新B请求对象)BDate
- 如果系统A客户端足够聪明,可以使用请求对象的版本1,则它可能会在
对象(SystemBObject
)上缺少方法时失败getDate()
- 在
上键入不匹配或溢出(返回systemaoobject
,但应为Long
)Integer
- 在
上键入missmatch或overflow(请求SystemARequest
而不是Long
)Integer
- 如果请求以某种方式通过,则强制转换问题(存根是
,但服务返回一个长的
,在所有WS实现中都不一定兼容)整数
systemaoobject1
,SystemBRequest2
等,但缺少用于匹配源/目标版本的API我更喜欢Salesforce.com的版本控制方法。每个版本的Web服务都会获得一个不同的URL,格式如下:
http://api.salesforce.com/{version}/{serviceName}
因此,您的Web服务URL如下所示:
http://api.salesforce.com/14/Lead
http://api.salesforce.com/15/Lead
等等
使用此方法,您可以获得以下好处:
解决方案是避免对类型进行不兼容的更改 以SystemBobObject为例。您描述了这种类型的“版本1”和“版本2”,但它们根本不是同一类型。对此类型的兼容更改只涉及添加属性,而不涉及更改任何现有属性的类型。您假设的“版本更新”违反了这两个约束 通过遵循这一原则,您可以避免您描述的所有问题 因此,如果这是版本1中的类型定义
class SystemBObject{ // version 1
String key;
Integer year;
Integer month;
Integer day;
... // getters and setters etc;
}
那么,这不能是v2中的类型定义:
// version 2 - NO NO NO
class SystemBObject{
String key;
BDate date;
... // getters and setters etc;
}
…因为它删除了现有字段。如果这是您需要进行的更改,那么它不是一个新的“版本”,而是一个新的类型,并且应该以代码和序列化格式这样命名
另一个示例:如果这是您现有的v1类型:
class SomethingFromARequest {
Integer requestedId;
... // getters and setters etc;
}
。。。那么这不是该类型的有效“v2”:
class SomethingFromARequest {
Long requestedId;
... // getters and setters etc;
}
…因为您已更改现有属性的类型
这些约束在本文中以一种主要与技术无关的方式进行了更详细的解释
除了避免不兼容的根源之外,您可以并且应该在类型中包含一个版本号。这可以是一个简单的序列号。如果您习惯于记录或审核消息,并且带宽和存储空间不是问题,那么您可能希望使用UUID扩展简单整数,以标识类型的每个唯一版本的实例
此外,通过使用lax处理,并将“额外”数据映射到“额外”字段中,您可以在数据传输对象中设计前向兼容性。如果XML是您的序列化格式,那么当v1服务接收到v2请求()时,您可以使用xsd:xmlAny或xsd:any和processContents=“lax”捕获任何无法识别的模式元素。如果您的序列化格式是JSON,具有更开放的内容模型,那么这是免费的 我知道这已经晚了,但我一直在深入研究这个问题。我真的认为最好的答案是另一个难题:服务中介。微软的托管服务引擎就是一个例子——我相信其他引擎也存在。基本上,通过更改web服务的XML名称空间(如链接文章所述,包括版本号或日期),您允许中介将各种客户端调用路由到适当的服务器实现。MSE的另一个(当然,也是非常酷的)特性是能够执行基于策略的转换。您可以定义将v1请求转换为v2请求和v2响应的XSLT转换
class SystemBClient{
SystemAServiceStub systemA;
public void consumeFromA(){
SystemAObject aObject = systemA.getSomethingFromA(new SomethingFromARequest(1));
aObject.getDescription() // fail point
// do something with it...
}
}
class SystemBService{
public SystemBObject getSomethingFromB(SomethingFromBRequest req){
return new SystemBObjectFactory.getObject(req);
}
}
class SystemBObject{
String key;
Integer year;
Integer month;
Integer day;
... // getters and setters etc;
}
class SystemBObject{
String key;
BDate date;
... // getters and setters etc;
}
class BDate{
Integer year;
Integer month;
Integer day;
... // getters and setters etc;
}
class SomethingFromBRequest {
String key;
... // getters and setters etc;
}
class SomethingFromBRequest {
String key;
BDate afterDate;
BDate beforeDate;
... // getters and setters etc;
}
http://api.salesforce.com/{version}/{serviceName}
http://api.salesforce.com/14/Lead
http://api.salesforce.com/15/Lead
class SystemBObject{ // version 1
String key;
Integer year;
Integer month;
Integer day;
... // getters and setters etc;
}
// version 2 - NO NO NO
class SystemBObject{
String key;
BDate date;
... // getters and setters etc;
}
class SomethingFromARequest {
Integer requestedId;
... // getters and setters etc;
}
class SomethingFromARequest {
Long requestedId;
... // getters and setters etc;
}