作者:Christian Posta
译者:海松
原题:Low-risk Monolith to Microservice Evolution Part I
在为期两天的微服务研讨会中,我一直在思考如何向大家解释单体应用(monolith-application)分解以及它向微服务过渡后将会是什么样。本文是该主题的一小部分,但我想与大家分享,并得到反馈(在研讨会中,我们会更详细地讨论是否应该分解单体应用!)。本文中我总结了一些亲历的经验,以及在过去几年中与北美许多红帽(Red Hat)客户合作的经历。这里的第一部分主要探讨了架构,即将发布的第二部分则会介绍一些能提供 很大帮助的技术。关注我的Twitter(@christianposta)或 http://blog.christianposta.com,可以获取最近的更新和讨论。
在深入讨论之前,让我们先做以下假设:
建新的特性,要么围绕单体式应用重新实现现有的业务流程(这有点逆潮流而动)
一、抽取微服务
有关这个话题的会议或博文中,都提供了以下的建议:
但这些建议没什么用。
有效的建议应该像这样:
具体来说:
第1步:识别模块
这一过程从烦人的单体式应用开始。在上图中,我简化了这一点来表示其中可能涉及到的不同模块和数据库表。我们要确定哪些模块是想从单体式应用里拆分出来的,找出涉及到的表,然后继续。当然,现实情况是单体式应用极易与模块(如果有的话)相互缠绕。
第2步:拆分数据库表,用服务包装,更新依赖关系
第二步是确定Foo 模块使用了哪些表,将它们拆分,然后加入模块自身的服务中去。该服务就成为现在唯一能访问这些Foo表的服务了。再没有别的共享表了!这是件好事。过去引用Foo的所有功能现在都必须经过新创建的服务的API。在上图中,我们更新了Bar和Cheese服务,当它们需要Foo的时候,会引用Foo服务。
第3步:重复上述流程
最后一步是重复这个过程,直到单体式应用全部消失。在上图中,我们对Bar 服务做了同样的处理,把它搬到了一个架构里,在这里,服务拥有自己的数据和开放的API,这听起来已经很像是微服务了。
通常,这算是一套不错的指导方针,但上述步骤其实回避了许多我们不应忽略的真相。比如我们不能要求时间暂停,然后从数据库中把表删除。同样的:
……等等等等
现在让我们来看个具体的例子,看看这个方法/模式是什么样的,以及可供的选择都有哪些。
二、具体举例
这个例子来自上面提到的研讨会。我将在分析拆分服务时做些润色,但是研讨会上谈到的更多内容,包括领域驱动设计、耦合模型以及物理或逻辑架构,这里先暂时不提。这个方法表面上似乎只能用于分解现有单体式应用的功能,但其实它同样能为单体式应用增加新功能。后者出现的概率可能更高,因为直接变更单体式应用风险是相当大的。
三、了解单体式应用
这就是单体式应用(Monolith)。它建立在developers.redhat.com上的TicketMonster①教程的基础上。该教程最初只是探讨如何构建一个典型的Java EE应用程序,但最终却成了一个很好的例子:它不过于复杂,而且有足够的内容让我们可以用来说明一些关键点。在即将发布的整个主题的第二部分中,我们将深入探讨技术框架或平台。
在这张图中,单体式应用将所有模块/组件/UI共同部署到了一个单体数据库中。当我们试图变更时,就会牵一发而动全身。试想一下,这个应用程序已经使用10多年了,所以现在变更起来难度很大(有技术原因,还有团队或组织结构的原因)。我们希望拆分出UI和关键服务,使业务变更起来更快,更独立,以交付新的客户价值和商业价值。
注意事项
四、抽取UI
在这步中,我们将从单体式应用中解耦UI。实际上在这个架构中,我们并未从中删除任何东西。为了降低风险,我们添加了一个包含UI的新部署。这个架构中的新UI组件需要非常接近单体式应用中的同一个UI(甚至完全一致),并调用它的REST API。 所以这意味着单体式应用拥有一个合理的API可供外部UI使用。但是,我们可能会发现并不是这么回事:通常这类API可能更像是“内部的”API,这里,我们需要考虑集成单独的UI组件和后端的单体式应用,以及让面向公众的API更可用。
我们可将这个新的UI组件部署到架构中,并使用平台将流量缓慢地路由到这个新架构,同时仍路由一些流量到旧的单体式应用。这样我们就不用停机。同样的,在本主题的第二部分,我们会更详细地看到如何做到这点。无论如何,灰度上线(dark launch)/金丝雀 发布(canary)/滚动发布(rolling release)②等概念在这里(以及后续步骤中)都非常重要。
注意事项
五、从单体式应用中删除UI
在上个步骤中,我们引入了一个UI,并缓慢地将流量转移到新的UI(它与单体式应用直接通信)。在这一步中,我们将采用一个类似的部署策略,但不同的是,UI被删之后,我们缓慢地发布了一个单体式应用的新部署。如果发现问题,我们可以慢慢地让流量流出,然后回流。在把所有的流量都送到已删除UI的单体式应用(此后称后端-Backend)中,我们就可以完全删除单体式应用部署了。通过分离UI,我们现在已对单体式应用进行了小规模的分解,并依靠灰度上线(dark launch)/金丝雀测试(canary)/滚动发布(rolling release)降低了风险。
注意事项