文章讨论了微服务架构下测试复杂性随服务数量指数增长的问题,指出集成点倍增、Mock维护困难和环境倍增是主要原因。提出了使用智能临时环境,创建隔离的类生产环境切片来解决这些问题,从而打破指数增长曲线。
译自:Why Scaling Makes Microservices Testing Exponentially Harder
作者:Arjun Iyer
我上周和一位工程副总裁聊天,他的一句话让我印象深刻:“当我们有五个微服务时,测试实际上比我们以前的单体应用更容易。但当服务达到 50 个时,它就成了我们最大的瓶颈。”
这并不罕见。大多数团队在使用 微服务 时都会经历一段蜜月期,测试感觉可控甚至优雅。然后,情况发生了变化。曾经的竞争优势变成了速度上的阻碍。问题是:为什么微服务测试的难度似乎呈指数级增长,而不是线性增长?
早期阶段的迷惑性
起初,微服务测试感觉像是一股清新的空气。你拥有清晰的服务边界和重点突出的测试套件,每个团队都可以独立行动。测试支付服务?启动该服务,模拟用户服务,就完成了。很简单。
这种早期的成功创造了一个合理的假设,即测试复杂性将与服务和开发人员的数量成比例地增长。毕竟,如果每个服务都可以独立测试,并且你的工程团队与你的服务一起增长,为什么测试工作不会线性增长呢?
这是一个合乎逻辑的假设。但它完全是错误的。
隐藏的指数力量
现实情况是,由于几个复合因素,微服务中的测试复杂性呈指数级增长,这些因素在刚开始时并不明显。
集成点快速倍增
如果有五个服务,你可能需要测试八到十个集成点。但集成点不会线性增长,而是根据系统的互连性增长。
来源:Signadot。
想想看:每个服务不仅仅调用一个其他服务。一个典型的微服务可能与四到六个其他服务集成——身份验证、日志记录、数据存储、通知服务,以及两到三个业务逻辑服务。随着架构的增长,服务之间的互连性越来越强,而不是越来越弱。订单服务不仅仅与库存对话,还会与支付处理、用户管理、运输、分析和审计日志交互。
结果呢?集成点的增长速度远快于服务的数量,从而创建了一个必须验证的依赖关系网。
每个新服务不仅仅增加它自己的测试需求。它可能会与多个现有服务交互,从而创建一个必须验证的依赖关系网。最初简单的点对点测试变成了一个复杂而庞大的验证挑战。
Mock 维护变得难以持续
在小规模上运行良好的 Mock 策略在大规模上会变成维护灾难。一个 API 更改可能需要更新不同代码库中的数十个 Mock,这些代码库由不同的团队拥有。
一位平台工程总监最近告诉我:“我们计算出,我们的团队花费 40% 的测试时间仅仅用于维护 Mock。”
环境倍增失控
如果有五个服务,每个团队维护三到四个测试环境感觉是合理的。扩展到 15 个团队的 50 个服务,突然间你需要 45-60 个环境。基础设施成本和运营复杂性变得惊人。
我们的一位客户每年花费 200 万美元仅仅用于预生产环境,然后才重新考虑其方法。运维团队花费更多的时间维护测试基础设施,而不是构建新功能。
放大 Staging 环境瓶颈
也许最具痛苦的扩展挑战是共享 Staging 环境中发生的事情。对于一些服务来说,Staging 环境工作得相当好。多个团队可以协调部署,当出现问题时,罪魁祸首通常很明显。
但是,当你添加服务和团队时,Staging 环境要么变成交通堵塞,要么变成自由区——两者都是灾难性的。
来源:Signadot。
选项 1:独占访问排队
一些组织实施严格的调度,团队获得独占的 Staging 环境访问权。我见过团队等待八个小时或更长时间才能轮到他们,并使用精细的协调系统(Slackbots、部署日历和其他机制)来管理队列。
这里的计算非常残酷。如果你有 20 个团队,每个团队每周需要两次 Staging 环境访问权限,并且每次测试会话需要两个小时,那么每周需要 80 个小时的 Staging 环境时间。但是你只有 40 个小时(一个环境,周一到周五)。按平均每小时 150 美元的完全加载工程成本计算,这些等待时间每周会转化为数千美元的生产力损失。我们合作的一个组织计算出,他们每年仅因工程师等待 Staging 环境访问权限而损失 40 万美元。
选项 2:共享访问混乱
更常见的是,团队在没有协调的情况下同时共享 Staging 环境。无需等待,但现在多个团队同时部署和测试。测试失败变得毫无意义——是你的代码还是其他人的部署破坏了流程?
这会产生一种反常的结果:开发人员不再信任测试结果,并开始忽略失败,假设它们与环境有关。团队在测试失败的情况下将代码推送到生产环境,从而导致生产事件。这个旨在在生产环境之前发现错误的本身,反而成为了虚假自信的来源。
当团队开始玩弄系统时
随着测试变得越来越痛苦,团队开始开发一些变通方法,这些方法使根本问题变得更糟:
- 批量更改: 团队不是测试单个功能,而是将多个更改批量在一起,以“优化”Staging 环境时间。当出现问题时,这会使调试难度呈指数级增长。
- 测试捷径: 团队跳过集成测试,并希望一切顺利,或者仅测试“happy path”以节省时间。质量不可避免地会受到影响。
- 环境囤积: 团队开始预留 Staging 环境的时间比实际需要的时间更长,从而造成人为的稀缺性。
- 并行开发停滞: 团队开始协调他们的开发周期以避免 Staging 环境冲突,从而破坏了微服务所承诺的独立性。
打破指数曲线
成功扩展微服务测试的团队已经找到了打破这种指数曲线的方法。他们已经不再尝试复制用于测试的生产环境,而是专注于创建类似生产环境的隔离切片。
他们不是为每个测试场景启动 50 个服务,而是只启动两个或三个正在修改的服务,并将测试流量路由到其他所有内容的类生产版本。这种智能临时环境方法限制了复杂性的增长,同时保持了高保真测试。
以下是它如何打破每个指数级扩展问题:
- 集成复杂性: 你无需测试 200 多个集成点,而是仅针对实际依赖项测试已修改服务的四到六个集成点。
- Mock 维护: 无需 Mock ——你的更改会针对实际的类生产服务进行测试,从而消除了维护开销。
- 环境倍增: 一个共享的基线环境通过请求级别的路由支持无限的隔离测试,从而大大降低了基础设施成本。
- Staging 环境瓶颈: 每个开发人员都可以立即获得自己的隔离测试环境,而无需排队,也不会受到其他团队更改的干扰。
一位客户完美地解释了这一点:“我们停止尝试为每个测试重新创建整个世界。相反,我们创建了一个小的更改气泡,并测试它如何与真实世界交互。”
前进的道路
随着你的扩展,微服务测试不必变得非常复杂。关键是尽早认识到传统的测试方法无法扩展到 10-15 个服务以上,并采用随着你的架构线性增长的测试。
在 Signadot,我们构建了一个平台,可以为这个问题启用 沙盒环境 ——允许团队针对类生产依赖项测试单个更改,而不会产生指数级的复杂性。如果你遇到了测试瓶颈,免费试用,看看线性扩展如何改变一切。

