我们有很多不同的微服务,除其他外,我们还测试了这些不同微服务的REST API。这些自动化的REST API测试未包含在微服务项目/存储库中。相反,我们有一个testautomation项目,其中包含所有不同的测试,例如API测试和end2end测试,因为我们希望将所有内容作为黑盒进行测试。
现在的问题是,可以在测试环境中测试不同微服务版本的无限组合(示例:今天针对具有1.0版的Microservice A和具有2.0版的Microservice B执行测试是不同的,因为它们执行相同明天针对版本1.1的Microservice A和版本2.1的Microservice B进行测试。因此,我们将需要某种形式的版本控制或标记我们的testautomation项目或已执行的测试,以便能够识别不同微服务版本的哪些组合有效以及哪些组合无效/无效,因为例如一些测试将失败。
是否有任何建议或经验来实施和集成这种版本控制/标记机制?
答案 0 :(得分:1)
对我来说,实际问题已经根植于您的实际设计中。您声明您维护了一些基于REST体系结构的微服务,尽管在这种环境中,您不需要像这样开始对任何端点进行版本控制。菲尔丁本人通过简单地回答:Don't回答了REST环境中的API应该如何版本化。
那为什么呢? REST具有的少数约束之一是HATEOAS(或我经常说的讨厌的Us),它代表应用程序状态的超文本作为引擎。该首字母缩写词基本上仅描述了Web中使用的交互模型,该模型对接收的内容没有任何假定,只会向用户呈现所接收的内容,包括服务器返回的任何URI。浏览器将在调用由用户调用的URI为目标的端点时触发状态更改。这可能是链接,图像或表单按钮(或其他)。这里的核心思想是,API或服务器将为客户端提供采取进一步操作并将结果仅呈现给用户所需的所有信息。
浏览首选制造商或供应商的网页时,您可能会发现您很可能会收到一个包含图像,链接和其他内容的HTML页面。浏览器本身并不知道该站点上提供的产品,尽管它知道如何呈现HTML仍能够将结果呈现给用户。如果您访问其他页面,则无论该页面提供的内容如何,您的浏览器仍将能够呈现HTML。但是,如果这些页面之一以某种方式发生了变化,除非服务器使用您的浏览器尚不知道的媒体类型进行响应,否则浏览器仍将能够向您呈现结果,尽管这在网络上不太可能
大多数自称为“ REST” API返回的是某些特定于特定API的任意内容,即使其中大多数都使用application/json
作为表示格式。一个对内置API有一定了解的量身定制的客户端通常正在与此类API进行交互,但是这种API不太可能与那里的任何其他API进行交互。如果API级别上的某些内容发生更改,则在不进行任何其他更新的情况下破坏该客户端的可能性很高。对于像SOAP,RMI和CORBA之类的RPC这样的系统,这非常常见。
此类客户端通常假设某些端点(例如/api/users/12345
)以最可能的JSON表示形式返回有关特定用户的数据。稍后将有效内容编组到基础编程语言的对象上,可能会忽略任何未知字段,并使响应中不可用的指定字段无效。尽管这里的根本问题是客户认为certain endpoints have a certain types。 “智能”开发人员现在将向端点引入版本控制,以便对于包含旧字段的JSON表示,上述URI将更改为/api/v1/users/12345
,而/api/v2/users/12345
将返回新字段。但是,这两个版本仍然描述相同的用户。对于同一用户而言,拥有两个不同的URI本身已经是一个糟糕的设计,尽管通常不会单独提供端点的版本控制。通常,整个API本身都会进行版本控制,因此,如果遇到重大更改,您将不得不引入一个全新的API版本,要么复制其他未修改的资源,要么在内部内部重用相同的模型,从而再次暴露于多个URI下。
客户端和服务器应该协商内容,而不是假设端点以预定义的表示格式返回某种类型。此处的HTTP特别支持content type negotiation,其中客户端将其功能通知服务器,并且服务器应以客户端理解的表示格式进行响应。可能是类似application/vnd.acmee-users+json
或application/vcard+xml
之类的东西。理解application/vnd.acmee-users.v2+json
的客户端,即可能由服务器提供新的表示形式,而较旧的客户端仍会通知服务器他们仅了解application/vnd.acmee-users+json
并由这种表示形式提供服务。服务器如何在内部处理更改对客户而言并不重要。它只是对它可以处理的表示形式感兴趣。
尽管某些架构师也不是版本控制更改版本的首选方式,因为您从根本上仍然使用一点不同的语法或稍微不同的语义来描述同一件事。 HTML,即仍然附带application/html
(很少附带text/html
),但不附带application/html_5
等。它的显式设计旨在保持向后兼容。生成HTML 5输出的服务器仍将在仅支持HTML 4.01或2的浏览器上呈现。也许并非所有元素的呈现方式都与与HTML 5兼容的浏览器相同,但是客户端不会停止工作。
IETF HTTP工作组的联合主席Mark Nottingham表示,版本控制的基本原则是不破坏现有客户。因此,据他
这意味着API版本绝对不能以任何方式与软件版本绑定。这样做会不必要地限制(并经常破坏)您的客户,并且通常会使人不高兴。 (Source)
Nottingham甚至声明,User-Agent
或Server
标头中使用的product-token应该优先于任何URI或媒体类型版本控制,以产生特定于某些软件版本的响应。但是,由于存在大量的客户端软件,因此我不是这种方法的最大支持者,因为这将要求服务器对HTTP客户端的功能及其使用的版本有一定的了解。但是,对于仅具有有限数量的客户端的API,可能大多数客户端都与API /服务器处于相同的控制之下,但这可能是一种可行的方法。
您可能会自己看到,在REST体系结构中,真正不需要对端点本身进行版本控制,因为客户端仅会处理API /服务器提供的服务。产品令牌方法是否比基于媒体类型的方法更好?但是,后一种应该基于向IANA注册的标准化媒体类型。在最佳情况下,媒体类型本身的设计方式是向后兼容的,例如HTML,这可以避免一遍又一遍地为相同的内容引入新的媒体类型。
如菲尔·斯特金(Phil Sturgeon)在他的blog posts
中提到的那样如果人们打算使用RESTish外观将API设计为RPC,那么他们应该致力于成为RPC API并为特定客户端构建端点,就像他们已经在做的那样。
老实说。隐藏错误的意图,RPC批次,文档本身,甚至可以使用gRPC。