具有多个具有内部调用的微服务的蓝绿色部署

Posted

技术标签:

【中文标题】具有多个具有内部调用的微服务的蓝绿色部署【英文标题】:Blue Green deployment with multiple Micro Services with internal calls 【发布时间】:2018-01-14 19:09:03 【问题描述】:

我有 8 个 Spring Boot 微服务,它们在内部相互调用。其他微服务的调用dns,定义在每个服务的application.properties文件中。

假设,微服务 A 由 A -> a.mydns.com 和 B-> b.mydns.com 等代表

所以基本上每个微服务都包含一个 ELB 和两个 HA 代理(分布式 在两个区域中)和 4 个应用服务器(分布在两个区域中)。

目前我正在创建新的绿色服务器(仅限应用服务器)并从 HA 代理级别切换实时流量。在这种情况下,当新版本的微服务在测试时,它也会暴露给现场客户。

理想情况下,方法应该是,为每个微服务创建整个服务器结构,包括 ELB 和 HA 代理,对吗?

但是我怎么会面临使用测试 dns 进行测试的挑战。我可以将 ELB 映射到测试 dns。 那么,在 application.properties 文件中硬编码的外部微服务 dns 呢?

在这种情况下我应该采取什么方法?

【问题讨论】:

如果你必须一次更换所有的微服务,那意味着你没有微服务。 您为什么要在生产环境中进行测试?你应该有单独的测试环境。 @JakubKania 我没有必要一次部署所有微服务。可能是 1,但部署的微服务对其他微服务有内部调用。还有一个测试环境来测试应用程序,但是一旦部署完成,还有一个 BVT 在生产环境中运行 为每个微服务使用单独的 ELB 是一种浪费。您应该使用应用程序负载均衡器 (ALB),一个 ALB 就足以满足所有微服务的需求。每个微服务都会通过 ALB 互相调用 【参考方案1】:

理想情况下,方法应该是为每个微服务创建整个服务器结构,包括 ELB 和 HA 代理,对吗?

这不一定是真的。部署(蓝绿色或金丝雀,无论您的部署策略是什么)应该是transparent 它的消费者(在您的情况下是其他 7 个微服务)。这意味着,与其他服务交互的服务 DNS 名称(或 IP)应该保持不变。恕我直言,在微服务部署的情况下,只要您遵守合同的一部分,您就不必考虑生态系统中的其他服务;毕竟这就是“微”服务的全部意义所在。正如其他 SOer 指出的那样,如果您不能在不更改其他服务的情况下部署您的一个微服务,那不是微服务,它只是一个通过 http 进行对话的单体。

我建议你阅读这篇文章 https://www.thoughtworks.com/insights/blog/implementing-blue-green-deployments-aws

我在这里引用相关部分

ELB 后面有多个 EC2 实例

如果您通过负载平衡器提供内容,那么同样 技术不起作用,因为您无法将弹性 IP 关联到 ELB。在这个场景中,当前的蓝色环境是一个 EC2 池 实例和负载均衡器会将请求路由到任何健康的 池中的实例。执行相同后面的蓝绿切换 您需要用一组新的负载均衡器替换整个池 包含新版本软件的 EC2 实例。有 有两种方法来做到这一点——自动化一系列 API 调用或使用 AutoScaling 组。

还有其他类似的创意方式

使用 Route53 进行 DNS 重定向

而不是将弹性 IP 地址或长 ELB 主机名暴露给您的 用户,您可以为所有面向公众的 URL 设置一个域名。 在 AWS 之外,您可以通过更改来执行蓝绿切换 DNS 中的 CNAME 记录。在 AWS 中,您可以使用 Route53 来实现相同的 结果。使用 Route53,您可以创建托管区域并定义资源 记录集告诉域名系统如何路由流量 那个域。

回答其他问题。

那么,硬编码的外部微服务 dns 怎么样? 在 application.properties 文件中?

如果你这样做,我建议你阅读12factor app;特别是config 部分。如果您还没有这样做的话,您也应该看看服务发现选项。

我有一种感觉,你在这里看到的是不那么微服务的意大利面。如果它是一个新建项目并且如果您的时间线预算允许,我建议您考虑将您的应用程序及其基础设施(一个词:Dockerizing)进行容器化,并使用任何容器编排技术,如 kubernetes、Docker swarm 或 AWS ECS (最简单的,前提是你已经在 AWS 上),我知道这超出了这个问题的范围,只是一个建议。

【讨论】:

【参考方案2】:

我建议将您的微服务 docker 化(使用 spring-boot 很容易),然后将 ECS(弹性容器服务)和 ELB(弹性负载均衡器)与应用程序负载均衡器一起使用。 (可以是内部的,也可以是面向互联网的)。

然后,当您部署新版本时,ECS 和 ELB 会利用您的微服务 /health 端点。

然后您可以在 spring-boot 中实现更复杂的HealthIndicator,以确定应用程序是否健康(并因此准备好接收传入请求)。只有当新应用程序健康时,它才会投入使用,而旧应用程序才会进入睡眠状态。

然后在test environment 上测试您的所有业务逻辑,并且由于 Docker,您在所有环境中运行完全相同的映像,在部署到生产环境时您不需要运行(任何)测试。 (因为它已经过测试,如果它启动了,你就可以开始了)。

【讨论】:

【参考方案3】:

通常对于 B/G 测试,您不会为新功能使用不同的 dns,而是定义规则,例如每 100 个用户发送到新功能,或者只有来自某个区域或办公室的 ip 可以访问新功能等。

假设您使用的是 AWS,您应该能够在 ELB 前面为基于上下文的路由创建一个 ALB,您应该能够在其中定义路由到 B 或 G 的规则。在这种情况下,您必须独立运行的独立环境(尽管可能使用相同的数据库)。

对于更复杂的规则,您可以在您的 Spring Boot 应用程序中使用诸如leanplum 或omniture 之类的工具。使用这种方法,您将拥有一个托管新旧功能的单一环境,稍后您将删除过时的代码。

【讨论】:

【参考方案4】:

我个人会走一条更简单的路线,使用测试 DNS 条目进行绿色部署,然后在您完全验证绿色部署良好后将其换成实时 DNS 条目。

那么我的意思是:

您声明您的实时部署具有以下 DNS 条目:

a.mydns.com b.mydns.com

我建议您创建一个模式,让每个微服务部署也获得一个测试 dns 条目:

test.a.mydns.com test.b.mydns.com

在部署微服务的“绿色”版本时,您会部署所有内容(包括 ELB)并将 ELB 的 CNAME 映射到 Route 53 中的测试 DNS 条目。这意味着您已经准备好使用绿色版本,但未被您的实时应用程序使用。绿色版本有它自己的 DNS 条目,因此您可以针对 test.a.mydns.com 域运行完整的测试套件。

如果(且仅当)测试套件通过,您将 CNAME 条目交换为 a.mydns.com 成为作为绿色部署的一部分创建的 ELB。这意味着一旦 DNS 传播,您现有的微服务就会开始与您的绿色部署对话。如果出现问题,只需将 DNS 更新反向到旧的 CNAME 条目即可完全回滚。

这里需要一点协调,但是您应该能够使用 Jenkins 和 AWS CLI 之类的工具来自动化整个事情。

【讨论】:

以上是关于具有多个具有内部调用的微服务的蓝绿色部署的主要内容,如果未能解决你的问题,请参考以下文章

具有共享数据库的微服务?使用多个 ORM? [关闭]

设计高可用的微服务架构

具有自己数据库的微服务的聚集,排序,过滤和分页

Spring Cloud 应用程序中具有 Forbidden 状态的微服务请求响应

单独的微服务只是为了微服务编排?

如何构建基于 DDD 领域驱动的微服务?