写点什么

Marcin Grzejszczak 访谈:Spring Cloud Contract

  • 2017-04-27
  • 本文字数:3435 字

    阅读完需:约 11 分钟

Marcin Grzejszczak 是 Pivotal 的一名软件工程师。目前,他在从事 Spring Cloud Contract 的开发,这是一个消费者驱动的、面向 Java 的契约框架。为了了解该框架的一些好处,特别是消费者驱动契约对微服务测试的帮助,InfoQ 对 Marcin 进行了采访。

要点:

  • 对于架构来说,消费者驱动契约和测试驱动开发类似;
  • Spring Cloud Contract 与 Spring 生态系统集成得很好;
  • 当使用消费者驱动契约时,端到端测试变得多余;
  • 在 Spring Cloud Contract 中,Spring Rest Docs 可以代替 Groovy DSL;
  • 将来,Spring Cloud Contract 将为非 Java 用户提供改进的工具。

InfoQ:您能简要介绍一下消费者驱动契约模式以及它解决的是微服务开发中的哪类问题吗?

Marcin Grzejszczak:消费者驱动契约是一个流程,旨在帮助客户测试他们的软件,创建更好的架构设计。在架构层面,我们可以称之为测试驱动开发。现如今,软件需要能够非常快速地响应客户需求、法律法规变化及业务需求,等等。另一方面,我们 IT 行业希望尽可能快地交付可靠的软件,经过测试,不含任何 Bug。这就是为什么我们创建了部署管道——自动化发布和测试过程。至于微服务,由于架构风格本身的性质,问题被放大了。我们不可能在不影响测试流程的情况下将单体应用拆分成微服务。

单体结构中包含的复杂性被推至架构层面。消费者驱动契约试图在团队之间定义一些明确的沟通界限。CDC 的总体流程是,消费者定义他们期望 API/ 消息是什么样子。这种期望就称为契约。从这些契约可以生成存根,稍后,消费者团队可以在构建过程中重复使用它们。在生产者一端也需要验证契约。那就导致,不管是测试生产者一端,还是测试消费者一端,都需要引入一种快速失败方法。对于快速失败,我们指的是软件构建失败以及通过产品调试发现问题(例如,我们在 REST/AMQP 消息中犯了一个错误)。

消费者驱动契约将 API 设计转移给了使用它的人。典型地,服务器端的团队只需要宣布 API 会是个什么样子。通常,消费者的数量导致那是唯一可能的方式。但情况并不总是如此。我见过,有的公司没有公开暴露他们的 API,团队也不希望在 API 应该是个什么样子这个问题上进行协作。CDC 就是设法将那种方法变成一种由消费者驱动 API 变化的方法。细想一下,这很有道理。不是服务器端消费 API,是消费者消费 API,那就是为什么创建的 API 应该尽可能地适应消费者。

InfoQ:你们创建 Spring Cloud Contract 的动机是什么?你们为什么用它代替其他可选的消费者驱动的契约框架?

Grzejszczak:和来自 Devskiller 公司的 Jakub Kubrynski 一起,我们对 CDC 框架进行了分析。我们得出的结论是,它们的学习曲线很高,而且非常啰嗦。这就是为什么在 2014 年 12 月诞生了 Spring Cloud Contract 的前身 Accurest。我们已经决定引入静态类型 Groovy DSL 来定义契约。这里要说到 Spring Cloud Contract 和其他 CDC 框架的主要区别了。Spring Cloud Contract 不仅可以从契约生成存根,还可以生成测试。那意味着开发人员只需要定义契约,而其他的东西都会为生产者自动生成。这曾是我们希望做出的一个非常重要的决策,因为 CDC 的本质就是,假定生成的存根是可信的。如果有人在契约中定义了一个可以通过GET方法访问的端点/foo,那么在生产者一端,我们就可以通过向/foo端点发送GET请求来生成一个测试。如果没有这样的端点,那么测试就会中断,存根也不会生成。

显而易见,Spring Cloud Contract 与 Spring 环境集成得很好。我们已经支持使用 Spring Integration Spring Cloud Stream Spring AMQP Apache Camel 进行消息传递。但是,是一个叫做 Stub Runner 的组件让 Spring Cloud Contract 成为一个有吸引力的选项。我已经提到过,存根是从契约生成的。在默认情况下,我们希望用户以 JAR 文件的形式将生产者存根和契约发布到 Maven 库。假如存根的组 ID 为“org.springframework”,工件 ID 为“spring-boot-application”。为了运行存根,消费者需要像下面这样给测试加上注解:@AutoConfigureStubRunner (ids={'org.springframework:spring-boot-application:+'}

实际情况是,框架会自动下载包含存根的“org.springframework:spring-boot-application” JAR 文件的最新版本,然后启动一个内存内 HTTP 服务器,并在一个随机端口上提供存根。也就是说,只需一条注解,你就可以为构建生成整个环境的存根!此外,真正有趣的是,Spring Cloud Contract 可以完全消除服务发现工具。那意味着,存根注册在一个服务注册中心的内存版本中。那样,你可以像使用服务发现那样,向一个真正的 HTTP 服务器发送一个真正的 HTTP 请求。

如果你想要在测试环境中对打包好的应用程序执行一些冒烟测试,Spring Cloud Contract 的 Stub Runner 也非常方便。下载好的存根可以注册到真正的服务发现工具中(例如 Eureka ),在契约中定义的真正的消息可以发送给真正的队列(例如 RabbitMQ )。那样,你的应用程序甚至都不知道它在同存根交互。

InfoQ:消费者驱动契约模式,如果有的话,对端到端测试有什么影响吗?

Grzejszczak:这是一个很好的问题。就像我提到的那样,使用微服务增加了测试和部署应用程序的复杂度。尤其是,部署和端到端测试的组合很有趣。假如我们的系统由 50 个微服务组成,让我们提几个问题:

  1. 对于每个构建的微服务,每个团队都应该有它的部署环境吗?
  2. 谁来承担那 50 个环境的费用?
  3. 如果我们决定,不是每个微服务一个环境,那我们该如何处理部署队列?如果端到端测试需要运行很长时间,我们就不得不在轮到我们之前等待很长时间……
  4. 那些环境应该包含其他 49 个微服务的生产版本还是开发版本?
  5. 或者,生产版本和开发版本都应该测试?谁来配置那些环境,谁又负责维护那些环境?
  6. 有时候,企业无法在测试环境中使用生产数据——他们会对数据进行模糊处理,并满足完整性需求。

此外,还有一点需要考虑,就是端到端测试相当脆弱。有许多和代码 Bug 无关的原因可以导致它们失败。我不是说端到端测试没有带来任何价值——恰恰相反。当复杂度达到一定程度时,必须计算成本和收益。消费者驱动契约可以解决问题。如果消息违反了契约,那么执行契约测试可以提早终止构建。换句话说,如果你的消息中有错误,那么最好在构建的第一分钟就失败,而不是在 2 个小时的端到端测试的最后一分钟。

这可能会引起争议,但在我个人而言,我认为,只要设置恰当,端到端测试就是多余的,完全可以省略。这需要满足三个条件:(1)进行契约测试;(2)监控关键性能指标并报警;(3)可以进行回滚测试,并构建到部署管道中。作为这种部署管道的例子,你可以检出 Spring Cloud Pipelines 项目。

InfoQ:给我介绍下新的 Spring Rest Docs 集成吧,它是否可以改变传统的消费者驱动契约工作流?

Grzejszczak:那不新了,不过,它确实获得了更多的关注。有些用户不喜欢编写 Groovy DSL,不希望生成测试。他们希望完全属于自己的测试流程。还有一些其他的用户已经在使用 Spring Rest Docs 测试他们的代码。Dave Syer 就是其中的一位用户,向 Spring Rest Docs 添加 Spring Cloud Contract 集成就是他的主意。多亏了这个,你才能编写测试来测试你的 Web 应用程序以及自动生成存根。使用 Spring Cloud Contract 的最新版本,你还可以从 Spring Rest Docs 生成 Groovy DSL 契约。

至于工作流,我可以想象得到,消费者和开发者结对满足消费者需要的测试和存根。那样,流程得以保留。另一方面,有些事情告诉我,Spring Rest Docs 方法将更多地应用在“生产者契约”方法中。生产者定义契约是什么样子也是如此。在 Spring,我们喜欢用自己的产品来进行开发,Spring Initilizr(start.spring.io 背后的代码)已经使用了 Spring Cloud Contract,而且,Spring Initilizr 存根发布到了 Spring 的 Maven 库。

InfoQ:最后一个问题,在你们的路线图上,有什么有趣的东西可以介绍一下吗?

Grzejszczak:我们刚刚发布了 Spring Cloud Contract 的最新版本“1.1.0.RELEASE”,带来了一些有趣的特性,其中包括完全模块化(现在,你可以自定义 Spring Cloud Contract 的部件,比如,生成 PHP 测试),所以,在接下来的几个周里,我们最可能做的是修复 Bug,让 API 更稳定。就长远规划而言,我们在考虑简化非 Java 用户的工作。不过显然,对我们而言,最重要的是用户的反馈,我们会调整规划满足他们的需求。

如果你想进一步了解这个项目,可以查看项目主页。如果你有什么问题,可以通过 Gitter 或者 Twitter( @mgrzejszczak )联系我。

查看英文原文 Q&A with Marcin Grzejszczak on Spring Cloud Contract

2017-04-27 19:003679
用户头像

发布了 1008 篇内容, 共 448.6 次阅读, 收获喜欢 346 次。

关注

评论

发布
暂无评论
发现更多内容

软件测试/测试开发 | 一文搞定 Appium 环境配置

测试人

软件测试 自动化测试 测试开发 appium app自动化测试

啥玩意儿?一个计时模块要做2天?

为自己带盐

dotnetcore

房价危机:疫情后时代席卷全球的新变局|数据报告

前嗅大数据

数据分析 数据采集 爬虫案例 爬虫工具 房价

高性能网络SIG月度动态:virtio新设备进入virtio规范、smc新特性IPC性能比tcp提升88% | 龙蜥SIG

OpenAnolis小助手

操作系统 高性能网络 龙蜥社区 sig virtio

pip安装'torch'出现PackageNotFoundError报错解决办法

Python

TiDB 底层存储结构 LSM 树原理介绍

C++后台开发

数据结构 后端开发 LSM树 TiDB

软件测试/测试开发丨如何从 0 开始学 Python 自动化测试开发(一)

测试人

Python 软件测试 自动化测试 测试开发

Python中LSTM回归神经网络的时间序列预测

Python

PyTorch中 torch.nn与torch.nn.functional的区别

Python PyTorch

Python对txt进行读写操作

Python

软件测试/测试开发丨从 0 开始学 Python 自动化测试开发(二):环境搭建

测试人

Python 软件测试 自动化测试 测试开发

小令观点 | 个人信息泄露——当代数字身份之殇

令牌云数字身份

数字身份 信息泄露 身份

Python将二维数组输出为图片

Python

新一代云原生日志架构 - Loggie的设计与实践

网易数帆

开源 云原生 日志 Loggie 企业号 1 月 PK 榜

极光笔记 | 如何为 iOS 16 创建一个实时活动

极光GPTBots-极光推送

ios 开发者 运营 API

基于 APISIX 的服务网格方案 Amesh 积极开发中!

API7.ai 技术团队

Service Mesh Service Mesh 服务网格 服务网格 APISIX

平安健康 Dubbo 3 升级、迁移和验证之路

阿里巴巴中间件

阿里云 云原生 dubbo

pip安装更换镜像

Python.

未来软件开发主流模式——低代码开发

力软低代码开发平台

这可能是Feign调用可重试的最佳方案了

JAVA旭阳

Java spring

Python将图片输出为二维数组并保存到txt中

Python

PyTorch的简单实现

Python PyTorch

为什么 APISIX Ingress 是比 Ingress NGINX 更好的选择?

API7.ai 技术团队

APISIX Ingress Controller Kubernetes Serverless NGINX Ingress Controller

PyTorch中 nn.Conv2d与nn.ConvTranspose2d函数的用法

Python PyTorch

尚硅谷Filebeat视频教程发布

小谷哥

RPN:Region Proposal Networks (区域候选网络)

图像处理

如何通过Java应用程序添加或删除 PDF 中的附件

在下毛毛雨

PDF Java’ 添加注释

I see you!「2022 龙蜥社区优秀贡献者」正式启动

OpenAnolis小助手

开源 龙蜥社区 2022 奖项 优秀贡献者

无需服务器开发,实现设备状态缓存方案——实践类

阿里云AIoT

sql 缓存 运维 物联网 存储

Marcin Grzejszczak访谈:Spring Cloud Contract_Java_Andrew Morgan_InfoQ精选文章