功能标志和预览环境是管理微服务发布和测试的流行方法。了解特定情况下的优缺点。
译自 Microservices Testing: Feature Flags vs. Preview Environments,作者 Arjun Iyer。
微服务架构 改变了现代应用程序的构建方式,使快速的功能开发和可扩展性成为可能。但是,它们也带来了独特的测试挑战。确保新功能在多个微服务中按预期工作,而不会造成意外故障,需要强大的测试策略。在微服务中管理功能发布和测试的两种流行方法是 特性开关 和 预览环境。
每种方法都有其优势和局限性,我将通过一个虚构的微服务应用程序来探讨,该应用程序正在实现新的购物车行为,并与订单服务、支付服务和愿望清单服务交互。
电子商务服务架构示例。(来自“用于微服务及其云和边缘系统硬件软件影响的开源基准套件,” ASPLOS ’19:第 24 届编程语言和操作系统架构支持国际会议论文集。)
在传统的单体应用程序中,测试新功能通常涉及验证整个应用程序。在微服务中,每个服务都是独立开发、部署和测试的,因此更难预测一个服务中的更改可能会如何影响其他服务。例如,对身份验证服务的微小更改可能会意外地破坏支付处理器,如果它们的交互没有经过彻底测试。
为了确保尽早发现此类问题,并在它们影响用户之前解决,测试策略 必须不断发展。这就是特性开关和预览环境发挥作用的地方。
特性开关提供了一种动态的方式来管理功能发布,通过将部署与发布分离。基本思想很简单:新代码部署到生产环境,但只有在特性开关打开后才会激活。这允许逐步发布、目标测试以及在出现问题时轻松回滚。
例如,在我们的微服务应用程序中,我们可以为新的购物车功能实现一个特性开关,如下所示:
if (isFeatureEnabled('newCartFeature')) {
return newCartFunctionality();
} else {
return oldCartFunctionality();
}
使用此开关,我们可以为一小部分用户启用该功能,同时在真实环境中测试它与订单、支付和愿望清单服务的交互。
- 在生产环境中进行实时测试:您可以在生产环境中测试功能,消除测试环境和生产环境之间的差异。例如,监控新功能如何处理真实流量。
- 受控发布和快速回滚:您可以逐步发布功能,限制影响。如果出现问题,您可以立即禁用它,最大程度地降低风险。
- 将部署与发布分离:您可以将代码部署与向用户发布代码分开,非常适合将发布与特定事件或里程碑对齐。
- 复杂性:过度使用会增加复杂性,增加要测试的配置数量,使系统更难管理。
- 没有隔离:开关在生产环境中运行,因此服务之间的交互可能会导致意外问题,例如支付处理器中的错误。
- 技术债务:未删除的开关会使代码库混乱,使维护更加困难。正如一位 Reddit 用户指出,“特性开关就像癌症,除非快速移除。”
**特性开关不应用于每次更改。**它们最适合用户界面功能、A/B 测试或需要实时回滚的情况。但是,对于更深层的集成或基础设施更改,仅仅依靠特性开关可能很危险,因为这些类型的更改通常需要在到达生产环境之前在隔离的环境中进行全面测试。这就是预览环境大放异彩的地方。
预览环境是一种临时、隔离的环境,可以按需启动,用于隔离测试功能。它可以克隆整个应用程序,也可以选择性地仅部署正在修改的服务。隔离是通过复制基础设施或通过动态路由特定请求到正在测试的服务来实现的。
在我们的微服务应用程序中,预览环境可以让我们在部署到生产环境之前测试新的购物车与其他服务的集成。我们可以运行完整的集成测试,模拟现实世界中的用户场景,尽早发现错误并进行迭代,而不会影响实时系统。
- 隔离:与功能标志不同,预览环境隔离了新功能,降低了它影响其他服务的风险。例如,在购物车服务中发现的任何错误都不会影响其他团队测试应用程序的其他部分。
- 早期错误检测:通过在与生产环境非常相似的环境中进行测试,您可以尽早发现错误,降低部署后引入问题的风险。这在复杂的微服务架构中尤其重要,因为服务交互可能难以预测。
- 合并前的信心:预览环境允许在合并前进行全面测试,确保功能在到达生产环境之前已在所有服务中得到充分测试。
- 资源使用:克隆整个基础设施资源密集,特别是对于大型应用程序。较新的方法专注于隔离修改后的服务,从而降低开销。
- 开发人员体验:设置时间各不相同。完整的基础设施克隆速度较慢,而特定服务的动态路由速度更快,负担更轻。
- 流量模拟:预览环境有助于早期测试,但可能无法完全模拟真实流量。动态路由可以使用高保真预生产设置更好地模拟生产条件。
这些考虑因素中的每一个都取决于实现方法——是在预生产环境中隔离完整的基础设施,还是仅隔离正在更改的服务。
虽然功能标志和预览环境都提供了独特的优势,但现实情况是,两者本身都不完美。测试微服务的最佳方法通常是将两者结合起来。
以下是一种实用方法:
- 使用预览环境进行合并前测试:启动一个预览环境来全面测试新的推荐算法与其他服务的集成。这确保您在代码合并到主分支并部署到生产环境之前发现任何错误。
- 使用功能标志进行部署后测试:一旦功能在预览环境中通过集成测试,就将其部署到生产环境中,并在功能标志的控制下。逐步将其推广到一小部分用户,监控其在现实世界条件下的行为,并在出现任何问题时回滚。
这种混合方法使您可以利用两种方法的优势:预览环境的早期错误检测和隔离,以及功能标志的灵活性和实时测试。
有效的微服务测试需要平衡速度和可靠性。功能标志支持在生产环境中进行实时测试,但通常缺乏对复杂集成问题的隔离。预览环境为合并前测试提供隔离,但可能资源密集,并且可能无法完全复制生产流量。
最佳方法?将两者结合起来。 使用预览环境尽早发现错误,然后使用功能标志进行部署以控制生产环境中的发布。这确保了速度而不牺牲质量。