Chris Richardson 微服务系列翻译全7篇链接:

原文链接:Refactoring a Monolith into Microservices


微服务重构的概述

将单体应用转化为微服务是应用现代化的一种形式,数十年来开发者们一直致力于此。因此,将应用重构为微服务时,我们可以借鉴其中的一些经验。

首先不要大规模地重写代码,不要集中所有力量从头构建一个新的微服务应用,这中方式听起来很吸引人,但是会有极大的风险,有可能以失败告终。正如 Martin Fowler 所言:

the only thing a Big Bang rewrite guarantees is a Big Bang!

相反,我们应该渐进式的重构单体应用。逐步构建由微服务组成的新应用,与单体应用一起运行;随着时间的推移,单体应用实现的功能会不断收缩,直至完全消失或者转变为另一个微服务。这一方法虽然充满挑战,但风险远小于大规模重写代码。

Martin Fowler 将这一策略称为“杀手应用”。这一名称源自热带雨林中的杀手藤。杀手藤附生于大树的周围,企图得到树冠处的阳光,最后树木死后,留下树状的藤蔓。应用现代化也遵循这一方式。我们将围绕着遗留应用构建由一些列微服务组成的新应用,直至遗留应用消失。

接下来了解不同的实现策略。

策略一:停止挖坑

如果发现自己掉入坑里,应该马上停止挖坑。一旦单体应用变的难以管理,你应该停止让单体应用继续变的庞大,实现新功能时,不应该往单体应用中添加新的代码。相反的,而是把新代码放到独立的微服务中。下图展示了此方法的系统架构:

除了新服务和遗留的单体应用,这个系统还包括其他两个组件:第一个是请求路由,用来处理 HTTP 请求,与之前文章中所说的 API 网关类似。路由将与新功能相对应的请求发送到新服务上去,将遗留请求发送到已有的单体应用上去。

另一组件是胶水代码,用来集成微服务与单体应用。微服务很少独立存在,通常需要访问单体应用拥有的数据。胶水代码存在于单体应用或微服务中,或者两者兼有,用来负责数据的集成。微服务使用胶水代码来对单体应用的数据进行读写。

微服务可以通过以下三种方式来访问单体应用的数据:

  • 调用单体应用提供的 API
  • 直接访问单体应用的数据库
  • 维护一份数据副本,与单体应用的数据库保持同步

胶水代码也被称为 anti-corruption layer。因为胶水代码能防止拥有全新领域模型的服务被遗留单体应用的领域模型所污染。胶水代码在两种不同的模型间进行转换。anti-corruption layer 这一术语来自 Eric Evans 撰写的 Domain Driven Design 中。要想远离单体应用的泥淖,开发 anti-corruption layer 是必不可少的。

以轻量级微服务的方式实现新功能有许多优点:它能够防止单体应用变的不可管理。微服务能够独立开发、部署和扩展。你可以通过创建新的服务来体会到微服务架构的好处。

然而,这一方法并没有解决单体应用的问题。要想解决这些问题,需要拆分单体应用。让我们看一下拆分的策略。

策略二:前后端分离

缩小单体应用的策略之一是将展示层从业务逻辑层和数据访问层中拆分出来。典型的企业应用包括一下三种组件:

  • 展示层:处理 HTTP 请求并实现基于 REST API 或 HTML 的 Web UI。在一个-
    用户界面复杂的应用中,展示层通常包含了大量的代码
  • 业务逻辑层:应用的核心,实现了业务逻辑
  • 数据访问层:访问数据库和消息代理等基础架构组件

通常展示层对于业务逻辑层与数据访问层来讲,彼此有着清晰的划分。业务层由若干个 API 组成,内部封装了业务逻辑。这些 API 是将单体应用拆分为两个更小应用的分界线。一个应用包含表示层,另一个应用包含业务逻辑层和数据访问层。拆分后,展示逻辑的应用向业务逻辑的应用发起远程调用。下图展示了重构前后的构架:

以这种方式拆分单体应用有两大好处:1)它使得两个应用可以独立的开发、部署和扩展。尤其是,它使得展示层的开发者能够快速迭代用户界面,轻松的进行 AB 测试。2)暴露了可被其他服务调用的 API
这种策略也只是部分解决方案,很有可能两个应用会变成难以管理的单体应用。这时需要使用第三种策略来消除剩余的单体应用。

策略三:提取微服务

重构的第三个策略是将单体中现有的模块变成独立的微服务,每次提取模块为微服务时,单体就会缩小,一旦转化了足够多的模块,单体应用将不再是问题,要么消息,要么变成另一个微服务。

为需要转化为微服务的模块设置优先级

大型、复杂的单体应用由数十甚至数百个模块组成,所有模块都是可提取的。弄清楚哪个模块需要首先被提取往往是挑战性的问题。一个好的方式是先选择易于提取的模块,这将给开发者熟悉微服务以及积累提取经验。之后可以提取哪些可以带来最大收益的模块。

将模块转变为微服务通常需要一定时间,一般会根据获得收益的大小来给模块排序。通常转换经常变化的模块带来的收益也最大。一旦把一个模块转换为微服务,就可以独立开发、部署它了,从而加快了开发速度。

提取那些对资源有独特需求的模块也会带来很多好处。例如,把需要内存数据库的模块转化为微服务,就能部署在大内存的主机上。同样的,将实现计算密集型算法的模块提取出来也是值得的,该微服务可以部署在拥有多个 CPU 的主机上。这种方式使得应用更容易扩展。

当决定哪些模块需要提取时,找出现有粗粒度的边界(即分界线)也大有裨益。这会使模块转化为微服务更加简单、省力。例如:一个只通过异步消息与其他部分通信的模块,转化为微服务是更简单的。

如何提取模块

提取模块的第一步是确定模块和单体应用的接口粒度。单体应用和微服务需要访问彼此的数据,更像是双向 API,模块和应用其它部分之间存在着互相依赖,因此实现这些 API 一般充满挑战。重构时使用领域模型来实现业务逻辑变的尤为困难,一般需要大的代码改动才能打破这些依赖。

一旦实现粗粒度的接口,就可以将模块转化为独立的微服务。要做到这一点,必须能够让单体应用和微服务通过 API 通信。 下图展示了重构前、重构中和重构后的不同架构:

模块 Z 是要被提取的模块,它使用到模块 Y ,同时它的组件被模块 X 使用。重构的第一步就是定义一组粗粒度 API,第一个接口是模块 X 调用模块 Z 的 接口。第二个接口是模块 Z 调用模块 Y的接口。

重构的第二步是把模块转变为独立的微服务。对内和对外接口通过 IPC 机制实现,开发人员可能只需要将模块 Z 与微服务支撑框架(Microservice Chassis framework)组合起来构建微服务。

一旦将模块提取完毕,你就拥有了一个新的微服务,它能够独立于单体应用和其它微服务进行开发、部署和扩展。如果想重写微服务的代码,集成微服务和单体应用的 API 会成为这两个领域模型之间的 anti-corruption layer。每提取一个模块,就向着微服务的方向又迈进了一步。随着时间推移,单体应用将会逐渐消失,你也会拥有更多的微服务。

总结

将单体应用迁移到微服务的过程是应用现代化的一种形式。并不需要从头重写代码,而是渐进式地将应用重构为一组微服务。其中有三种策略:使用微服务实现新功能;将展示层从业务逻辑层、数据访问层中拆分;将单体应用内的模块转化为微服务。随着时间的推移,微服务的数量将会增加,从而提升团队的敏捷和效率。

Chris Richardson微服务翻译:重构单体服务为微服务的更多相关文章

  1. Chris Richardson微服务翻译:微服务之事件驱动的数据管理

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理(本文) 微服 ...

  2. Chris Richardson微服务翻译:微服务架构中的服务发现

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现(本文) 微服务之事件驱动的数据管理 微服 ...

  3. Chris Richardson微服务翻译:构建微服务之微服务架构的进程通讯

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯(本文) 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服 ...

  4. Chris Richardson微服务翻译:构建微服务之使用API网关

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关(本文) 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服 ...

  5. Chris Richardson微服务翻译:微服务介绍

    作者简介:Chris Richardson,世界著名的软件架构师,经典著作<POJOS IN ACTION>的作者,cloudfoundry.com 的创始人 微服务目前正受到大量的关注, ...

  6. Chris Richardson微服务翻译:微服务部署

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现 微服务之事件驱动的数据管理 微服务部署( ...

  7. 【转】「Chris Richardson 微服务系列」微服务架构的优势与不足

    Posted on 2016年5月4日 编者的话|本文来自 Nginx 官方博客,是微服务系列文章的第一篇,主要探讨了传统的单体式应用的不足,以及微服务架构的优势与挑战. 作者介绍:Chris Ric ...

  8. 【CHRIS RICHARDSON 微服务系列】事件驱动的数据管理-5

    编者的话 |本文来自 Nginx 官方博客,是「Chris Richardson 微服务」系列的第五篇文章.第一篇文章介绍了微服务架构模式,并且讨论了使用微服务的优缺点:第二和第三篇描述了微服务架构模 ...

  9. 【CHRIS RICHARDSON 微服务系列】微服务架构中的进程间通信-3

    编者的话 |本文来自 Nginx 官方博客,是微服务系列文章的第三篇,在第一篇文章中介绍了微服务架构模式,与单体模式进行了比较,并且讨论了使用微服务架构的优缺点.第二篇描述了采用微服务架构的应用客户端 ...

随机推荐

  1. mongodb 3.4 集群搭建:分片+副本集

    mongodb是最常用的nodql数据库,在数据库排名中已经上升到了前六.这篇文章介绍如何搭建高可用的mongodb(分片+副本)集群. 在搭建集群之前,需要首先了解几个概念:路由,分片.副本集.配置 ...

  2. mysql查询进程、导入数据包大小设置

    mysql查询进程.导入数据包大小设置 zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2017-12-27 查询正在执行的进程: ...

  3. windows7 创建http 服务器

    利用windows7 操作系统自带的功能创建http 服务器 方法/步骤     打开控制面板--程序---开启和关闭windows功能.   选择IIS(internet information S ...

  4. CentOS 7 学习(三)配置Tomcat集群

    所谓集群,就是把多台服务器集合起来,对外提供一个接口访问,对用户来说完全透明,常用的办法就是前端放一个服务器,将用户请求分发到不同的服务器,大致有以下几种方案 1)采取DNS轮询:将用户的连接解析到不 ...

  5. Android(Java) 字符串的常用操作,获取指定字符出现的次数,根据指定字符截取字符串

    /*这是第100000份数据,要截取出100000*/ String s="这是第100000份数据"; String s1 = s.substring(s.indexOf(&qu ...

  6. 7.python常用模块

    1.time 常用表示时间方式: 时间戳,格式化的时间字符串,元组(struct_time) UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时 ...

  7. geoserver发布地图服务WMTS

    WMTS: 切片地图web服务(OpenGIS Web Map Tile Service) WMTS提供了一种采用预定义图块方法发布数字地图服务的标准化解决方案.WMTS弥补了WMS不能提供分块地图的 ...

  8. bzoj 1597: [Usaco2008 Mar]土地购买

    Description 农 夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000 ...

  9. a标签实现一键拨号、发短信、发邮件、发起QQ会话

    a标签href的妙用:   <a href="tel:400-888-6633">拨打电话<a> <a href="sms:19956321 ...

  10. 本机向windows服务器传输文件的三种方法

    闲来无事,在腾讯云上申请了一个免费的服务器,想将自己写的网页发布到服务器上,服务器的申请很简单,百度搜索 腾讯云 ,然后新人第一次注册能申请到免费一个月的云主机,虽然配置不怎么高,但是还是能用的,这是 ...