HelloFresh 迁移至新的 API 网关,实现微服务架构

阅读数:1529 2017 年 4 月 12 日

话题:DevOps架构

HelloFresh最近以零停机的方式将应用迁移到了一个新的 API 网关,其技术总监Ítalo Lelis de Vietro在一篇文章中分享了他们所面临的挑战以及迁移的过程。

在这次迁移之前,HelloFresh 已有的 API 是单体架构的。为了迁移至微服务架构并让微服务的创建更加简单,同时还要与他们的基础设施进行集成,他们构建了一个新的 API 网关,这个网关会涵盖已有的和新的服务。他们的基础设施已经有了一些组件,包括服务发现、基于 Ansible 的自动化以及广泛存在的日志和监控,这些组件都会让微服务更加易于实现。为了解决零停机以及向后兼容的难题,团队编写了一个代理脚本将旧服务转换为新的模式。迁移过程的第一次尝试失败了,然而第二次尝试按照预期得到了成功。

HelloFresh 已有的基础设施使用Consul来实现服务发现,并使用 HAProxy 实现客户端的负载均衡。这两个因素促使他们转向了微服务。团队还有一个约定,那就是所有的新服务必须要从Ansible自动化开始着手。这种自动化几乎涵盖了整个技术栈,包括网络、DNS、CI 以及机器的供应。在分布式系统多个服务存在交互的场景下,可见性(Visibility)是至关重要的,HelloFresh 存在着广泛的日志和监控功能。Statsd 和 Grafana 用于实现监控和仪表盘, ELK则被用来详细分析服务的行为,它们组成了这方面的技术栈。

除了新的网关,新的认证服务也已经进行了规划,它将会代替旧 API 中的认证模块。这需要旧应用进行重构。

团队预迁移的挑战在于要向后兼容移动应用,确保所有的服务通过新的网关调用,所有的调用能够安全传输,已有的 API 规则在新的 API 网关中能够继续得到遵循。不能对用户强制要求移动应用的更新,因此 API 要保持向后的兼容性。正在使用的 API 同时包含公开的和私有的端点,所有的这些端点必须要使用新的网关进行注册。微服务和网关之间的服务调用传输必须是安全的。API 按照 OpenAPI 格式进行文档化,这是用于描述 REST API 的一个标准。这样的话,团队就能够使用 Go 来编写导入脚本,它会在旧 API 和新 API 间进行转换,并保持像配额(quotas)、CORS 设置以及限速这样的规则。

迁移的第一次尝试包括将旧的 API 替换为新的,首先在 staging 环境,然后是在生产环境,每一步都有相关的测试用例。这次尝试最终失败了,因为认证数据库由于大量的请求出现负荷超载了。团队低估了负载,数据库开始拒绝连接。另外,在导入脚本方面有一些 CORS 错误配置。监控系统能够捕获到问题,迁移过程被回滚了。

第二次部署尝试基于第一次所学习到的经验教训。团队规划了一个蓝绿(blue-green)部署,预先准备了一个使用新网关的生产环境副本。这种设置使得新旧环境的切换变得更加容易,所需要的是配置的变更。机器的容量进行了重新的规划,这基于正在运行的应用的指标以及第一次部署的负载指标所确定的。他们使用了一个开源的负载测试工具Gatling来运行性能测试。认证服务中一些已知的 issue 也进行了修正。

迁移之后,基础设施如下图所示:

图片来源:http://highscalability.com/blog/2017/2/20/scaling-hellofresh-api-gateway.html

API 网关是 HelloFresh 基础设施的前沿。团队为什么要构建自己的网关,而不是采用已有的解决方案呢?de Vietro 在评论区是这样回应的:

我们曾经尝试 Amazon API 网关和 Tyk,但是我们有自己的认证提供商(provider),将它与 AWS 网关集成的效果并不理想。我们必须要处理 lambdas(AWS 的云服务——译注)来添加自定义的认证提供商。将相关指标数据集成到 grafana 也会更加复杂一些,另外一点就是我们会锁定到相同的供应商上面。Tyk 并没有在自定义认证提供商方面给出什么方案(至少当时如此),我们必须要使用他们的内置策略、用户管理以及 ACL,这并不是我们想要的结果。我觉得现在的产品已经有了很大的不同,但这就是当时的原因所在。另外,借助我们自己的网关,可以版本化 git 上的路由配置文件,为其保留变更日志对我们来说至关重要。

这个 API 网关已经在 Github 上开源了

查看英文原文HelloFresh's Migration to a New API Gateway to Enable Microservices