使用API​​网关帮助单体到微服务的平滑过渡

本文从网关角度讨论了从单体迁移到微服务的三种方式,主要方向是确保新老系统平滑过渡,这些模式和最佳实践值得一读:

在我的咨询工作中,我遇到了很多工程团队,他们正在从单体应用迁移到基于微服务的应用程序,虽然我明白迁移模式几乎成了陈词滥调,但是迁移的细节方面往往都会被遗忘。我现在热衷于讨论其中一个主题 - 边缘网关或API网关的角色。

迁移到微服务
一般情况下,在迁移开始时,下面这些明显的主题会得到了很多关注:
1. 通过领域驱动设计进行领域域建模,引入“ 有界的上下文 ”;
2. 创建了持续交付管道;
3. 自动化基础设施配置;
4. 增强的监控和记录
5. 引入新技术Docker,Kubernetes,或服务网格或。

但是如何协调系统的演变和现有用户流量的迁移?虽然你希望重构现有的应用程序架构并可能引入一些新技术,但你不希望破坏最终用户的正常使用。

每个(用户)旅程都从边缘开始
在转向基于微服务的应用程序时,我显然不是第一个谈论有效边缘解决方案需求的人。事实上,Phil Calcado提出了扩展Martin Fowler最初的微服务先决条件,并发表文章:  "Calcado的微服务先决条件" , 他的第五个先决条件是“ 轻松进入边缘 ”,Phil根据他的经验谈到,许多组织首次尝试在他们的单体上部署新的微服务,只需将服务直接暴露给互联网,这对于单个(简单)服务会很奏效,但是该方法不能扩展,并且还强制调用客户端在授权或数据聚合方面的特殊处理。

一个方案是可以将现有的单体应用用作网关,如果你有复杂且高度耦合的授权和身份验证代码,那么在将安全组件重构为新模块或服务之前,这可能是唯一可行的解​​决方案。

这种方法有明显的缺点,就是要求必须使用任何新的路由信息​​(可能涉及完全重新部署)来“更新”单体,以及所有流量必须通过单体。如果要将微服务部署到单独的新结构或平台(例如Kubernetes),后一个问题解决起来可能会特别昂贵,因为现在任何进入应用程序的请求必须在它接触新平台之前首先通过旧单体平台进行路由。

可以使用边缘网关或反向代理(例如,NGINX或HAProxy),因为他们可以提供许多优势,提供的功能通常包括到多个后端组件的透明路由、标头重写、TLS终止等,以及横切关注点。

无论最终如何提供请求。在这种情况下要问的问题是,是否要继续使用此网关进行微服务实现?如果这样做,是否应该以相同的方式使用它?

从VM到容器(通过编排)
正如我在本文的介绍中提到的,许多工程团队也决定在更改应用程序架构同时迁移到新的基础架构。这样做的好处和挑战在很大程度上依赖于上下文,但我看到许多团队从虚拟机(IaaS)直接迁移到容器和Kubernetes。

假设你决定将闪亮的新微服务打包到容器中并将其部署到Kubernetes中,那么在处理边缘流量方面面临哪些挑战?本质上有三种选择,其中一种你已经读过:

1. 使用现有的单体应用程序充当边缘网关,将流量路由到单体服务或新的微服务。这里可以实现任何类型的路由逻辑(因为所有请求都通过单体传输)并且可以在进程中调用验证和授权。

2. 在现有基础架构中部署和运行边缘网关,基于URI和Http Header标头将流量路由到单体服务或新服务。验证和授权通常通过调用单体或重构的安全服务来完成。

3. 在新的Kubernetes基础架构中部署和运行边缘网关,基于URI和Http标头将流量路由到单体服务或新服务。验证和授权通常通过调用可在Kubernetes中运行的已经重构的安全服务来完成。

这三种情况比较如下:
1. 学习曲线是依次从低到高
2. 配置难度是依次从高到低
3. 自我服务能力是从低到高
4. 扩展性,前面两种都很低,最后一种高扩展性。

一旦你选择了如何实现边缘网关,应该做出的下一个决定是如何改进系统,从广义上讲,你可以尝试按原样“strangle扼杀”单体,或者你把“单体”放在盒子,然后逐渐移开。

扼杀单体
Martin Fowler撰写了一篇关于Strangler(扼杀)模式原理的精彩文章,尽管写作已有十多年的历史,但在尝试将功能从一个单体迁移到更小的服务时,这个指导原则同样也适用。

其核心模式描述了应该以服务的形式从单体中提取出功能,这些服务通过RPC或REST或通过消息传递和事件与单体交互。随着时间的推移,单体中的功能(和相关代码)将被淘汰,这导致新的微服务“扼杀了”现有的代码库。这种模式的主要缺点是,只要单体仍处于服务状态,你仍需要维护现有的基础设施和正在部署微服务的新平台,两个平台同时维护。

最早谈论使用这种模式应用到微服务的公司是Groupon,早在2013年就有了“ I-Tier:拆除单体 ”。从他们的工作中可以学到许多教训,但我们绝对不需要在2018年像他们那样编写自定义NGINX模块了,因为Groupon最初使用“Grout”,现在存在像Ambassador和Traefik这样的现代开源API网关,它们使用简单的声明性配置来提供类似同样功能。

Monolith-in-a-Box:简化持续交付
我看到团队迁移到微服务并部署到Kubernetes上的一种越来越常见的模式就是我所说的“monolith-in-a-box”。当我们 在2015年的ContainerSched会议上分享关于迁移notonthehighstreet.com的单体Ruby on Rails应用程序(亲切地称为MonoNOTH)到基于微服务架构的故事时,我与Nic Jackson一起讨论了这个问题。

简而言之,此迁移模式包括将现有的单体应用程序打包装在容器中,并像运行任何其他新服务一样运行它。如果你正在实施新的部署平台,例如Kubernetes,那么也可以在里面运行单体。

这种模式的主要好处是持续交付管道的同质化 - 每个应用程序和服务可能需要自定义构建步骤(或构建容器)才能正确编译和打包代码,但是在创建运行时容器之后,管道中的所有其他步骤都可以使用容器抽象作为部署工件。

这个模式最终目标是将您的单体组件部署到新基础架构,并逐步将所有流量转移到这个新平台。这能在完成单体分解之前停用旧的基础结构。如果遵循这种模式,那么我认为在Kubernetes中运行边缘网关更有意义,因为它最终将路由所有流量。


结论
从基于虚拟机(VM)的基础架构迁移到像Kubernetes这样的云本机平台时,非常值得花时间实施有效的边缘/入口解决方案来帮助迁移。

有多种选择来实现这一点:使用现有的单体作为网关; 在现有基础架构中部署或使用边缘网关,在当前服务和新服务之间路由流量; 或在新的Kubernetes平台中部署边缘网关。

在Kubernetes中部署边缘网关可以在实现诸如“Monolith-in-a-Box”之类的迁移模式时提供更大的灵活性,并且可以更快地向完全基于微服务的应用程序过渡。

Using API Gateways to Facilitate Your Transition f