【转】应用架构一团糟?如何将单体应用改造为微服务

概述

将单体应用改造为微服务实际上是应用现代化的过程,这是开发者们在过去十年来一直在做的事情,所以已经有一些可以复用的经验。

全部重写是绝对不能用的策略,除非你要集中精力从头构建一个基于微服务的应用。虽然听起来很有吸引力,但是风险很大,很有可能会失败。就像MartinFowler所说的: 『The only thing a Big Bang rewrite guarantees is a Big Bang!』

你应该循序渐进地重构你的单体应用。你可以逐步地构建一个部分微服务化的应用,然后和你的单体应用集成起来。单体应用的实现的功能会逐渐变少,最终消失或变成一个新的微服务组件。

种应用现代化的策略为Strangler Application。这个名字来源于在热带雨林发现的一种植物Strangler vine, 为了够到充足的阳光, 它们绕树生长,一直向上。当树木死后,只会留下一个树形的藤蔓。应用的现代化就是类似的模式,我们会在旧有的应用上,构建一个新的包含微服务的应用,慢慢取代旧的应用。下面一起来看下这些策略:

策略1:止损

Law of Holes告诉我们,如果你正在一个洞里,就不要继续再挖了。当你的单体应用已经变得无法管理的时候,就不要再继续扩大它的规模了。 比如你想添加新功能,不要在单体应用中添加代码,而要将新的代码放在另一个单独的微服务中。 下图展示了使用这种方法后的系统架构: 

除了新服务和旧的单体应用,还有两个组件。一个是 请求路由 (request router),用来处理过来的(比如HTTP)请求,类似于API网关。这个路由发送与新功能相应的请求到新的服务上,将旧服务相关的请求路由到单体应用上。

另一个组件是 胶水代码 (glue code),用来将服务与单体应用集成起来。一个服务很少是隔离存在的,需要访问单体应用的数据。胶水代码就负责这些数据集成。微服务组件可以通过它来读写单体应用中的数据。

一个服务可以通过三种方式访问单体应用中的数据:

  • 通过调用单体应用提供的远程API

  • 直接访问单体的数据库

  • 保存一份数据的副本,和单体数据库保持同步

胶水代码有时被称为 防腐层(anti-corruption layer) ,可以防止拥有自己原始领域模型的服务,被来自单体领域模型的概念所影响。

胶水代码可以在两个不同的模型间充当翻译官,防腐层这个词最初出现在Eric Evans写的《Domain DrivenDesign》一书中。开发一个防腐层不是一个小工程,但如果你想从单体地狱中走出来,这是很重要的。

用轻量级的服务实现一个新功能,有很多好处。首先,可以防止单体应用变得更难以管理;其次,这个应用可以被独立地开发,部署和扩展。

然而,这个方法并不能解决在旧有的单体部分遇到的问题,你还需要破坏原有的单体部分。

策略2:前后端分离

缩减单体应用的一个策略是将表现层从业务逻辑和数据访问层中分离出来,一个典型的企业应用至少包括三种组件:

  • 表现层: 这层组件用来处理HTTP请求,实现(REST)API或者基于HTML的Web UI。在一个有着复杂的用户接口的应用中,表现层通常有大量的代码;

  • 业务逻辑层: 应用的核心代码,用来实现业务规则;

  • 数据访问层: 访问数据库或信息中介的组件。

在表现逻辑与业务和数据访问逻辑之间通常有着明显的区分。业务层有一个粗粒度的API,包含一个或多个外立面组成,外立面封装了业务逻辑组件。这个API是自然的『缝合』,所以可以将单体分割为更小的应用,一个应用包含了表现层,另一个应用包含了业务和数据访问层。分隔后,表现逻辑层应用可以远程调用业务逻辑层应用,下图展示了改造前后的架构:

这样分隔单体应用有两个主要好处。 首先你可以独立地开发,部署和扩展两个应用, 比如对于表现层开发者来说,他们可以实现用户界面的快速迭代,A/B测试也很容易实现; 其次,这样做会向外开放一个微服务也可以调用的远程API。

但是这个策略只是部分解决方案,很有可能会变成两个混乱的单体应用。需要用下面第三个策略去减少单体部分的比重。

策略3:提取服务

第三个策略的目的是将单体中的模块,转变为单独的微服务。每次提取一个模块,就改造为微服务,单体部分就缩减了。一旦你转化了足够的模块,最后不管单体部分是完全消失了,还是变小成了另一个微服务,都不是问题了。

优先改造哪个模块?

一个大型的复杂的单体应用,通常包含数十甚至上百个模块,都可以被提取出来,选择先提取哪个是个问题。可以从容易被提取的开始,积累微服务的经验,然后提取那些能给你带来最大好处的模块。

通常提取那些频繁变化的模块很有用 ,一旦你将这个模块提取出来,就可以独立开发和部署它了,可以加速开发。

另外一个就是提取那些资源需求和其它部分有很大不同的模块。 比如将一个有内存数据库的模块转变为服务,就可以把它部署在内存很大的主机上;同样的,提取那些实现复杂算法的模块,就可以把它部署在CPU多的主机上。总之这样做有助于你扩展应用。

当决定了提取哪个模块后,需要看下现有的粗粒度边界,可以帮助你将模块转化为服务。比如一个只会通过异步信息和其它应用交互的模块,就很容易能被改造为微服务。

如何提取一个模块?

第一步是在模块和单体之间定义一个粗粒度的接口。 由于单体和微服务的数据互相都有需求,所以它 很像一个双向的API。但是在这个模块和应用的剩余部分之间,有着混乱的依赖关系和细粒度的交互模式,所以实现这个API还是很有挑战的。通过域模型实现的业务逻辑,改造起来尤其困难,因为各个域模型间的关系复杂。通常需要进行大量的代码修改,去打破这些依赖。

一旦你实现了细粒度的接口,就可以将模块改造为一个独立的服务。要写代码实现单体和微服务间的通信,通过使用了IPC机制的API。下图展现了一个架构在改造前,改造中和改造后的样子:

 

在这个例子中,模块Z是待提取的模块。模块X使用了Z的组件,Z又使用了模块Y。

  1. 改造的第一步是定义一对粗粒度的API,第一个接口是模块X调用模块Z的入站接口,第二个是模块Z调用模块Y的出站接口;

  2. 第二步是将这个模块改造为独立的服务。入站接口和出站接口都通过IPC机制的代码实现。可能你需要通过结合模块Z到微服务底盘框架(用来处理横切关注点,比如服务发现)上,来构建这个服务。

一旦你提取了这个模块,就可以独立地开发,部署和扩展它了。你甚至可以从头重写这个服务,将这个服务和单体结合起来的API代码就成了防腐层,相当于两个域模型之间的翻译官。每次提取一个服务,都是向着微服务又进了一步,单体的比重会逐步缩减。

总结

将单体架构改造为微服务的过程是一种应用现代化的形式,不应该从头重写来实现。而是应该循序渐进地改造你的应用成为一系列微服务。有三种策略可以应用: 用微服务实现新的功能;将表现层组件从业务和数据访问组件中分离出来;改造单体中的模块为微服务。 随着时间的推移,你的微服务比重会增大,你的开发团队的灵活性和速度也会提高

转载于:https://www.cnblogs.com/cim3221847/p/6129433.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/255831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 解决ssh连接慢的问题

备份文件 cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak 编辑文件 vi /etc/ssh/sshd_config 输入/ 查找GSSAPIAuthentication 设置如下 GSSAPIAuthentication no # 是否允许使用基于 GSSAPI 的用户认证。默认值为"no"。仅用于SSH-2 详细解释 输入/ 查找UseDNS …

ABB机器人与PC计算机控制口连接 超级终端 命令清单

条件: 9 针串口通信 RS232。 PC 启动超级终端软件。Windows -> Start -> Accessories -> Terminal 通信设置: 1. 波特率 9600 8 位2. 1 个停止位 没有奇偶校验3. 没有 Modern 采用直接串口连接4. 使用 Xon/Xoff 通信形式当故障发生时&#xff0…

【Hibernate】Hibernate系列6之HQL查询

HQL查询 6.1、概述 6.2、分页查询 6.3、命名查询 6.4、投影查询-部分字段查询 6.5、报表查询 6.6、迫切左外连接、左外连接 6.7、迫切内连接、内连接 6.8、QBC查询、本地查询 转载于:https://www.cnblogs.com/junneyang/p/5254641.html

【深度学习】——梯度下降优化算法(批量梯度下降、随机梯度下降、小批量梯度下降、Momentum、Adam)

目录 梯度 梯度下降 常用的梯度下降算法(BGD,SGD,MBGD) 梯度下降的详细算法 算法过程 批量梯度下降法(Batch Gradient Descent) 随机梯度下降法(Stochastic Gradient Descent&#xff09…

Javascript隐式转换

乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知。 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲…

双工位机器人 焊接夹具注意事项 o(╯□╰)o

焊接夹具设计注意事项 一套完美的夹具,需要机械设计人员正确的设计思想,良好的配件质量,钳工负责认真的装配质量,卡具在使用中不断的修磨和改进,才会达到好的效果。 本人非机械设计,只是在使用焊接卡具过程中遇到了很多卡具设计上…

【公共类库】加密解密

public static class MyEncryption{#region Md5加密/// <summary>/// 使用MD5加密/// </summary>/// <param name"str">需要加密的数据。</param>/// <param name"kind">加密类型&#xff1a;1-普通加密&#xff1b;2-密码加…

使用JOTM实现分布式事务管理(多数据源)

使用spring和hibernate可以很方便的实现一个数据源的事务管理,但是如果需要同时对多个数据源进行事务控制,并且不想使用重量级容器提供的机制的话,可以使用JOTM达到目的. JOTM的配置十分简单,spring已经内置了对JOTM的支持,一.<bean id"jotm" class"org.spri…

【机器学习】——《机器学习实战》面试复习

目录 一、机器学习概念 二、机器学习步骤 三、有监督学习 1、k-近邻算法 核心思想 实例&#xff1a;手写数字的识别 优缺点&#xff1a; 2、决策树 相关概念 核心思想 一些小技巧 优缺点 3、神经网络 4、SVM——支持向量机 核心思想 SVM和SVR的区别 ​ 优缺点…

一键分享代码

文章出处&#xff1a;http://share.baidu.com/code/advance 一、概述 百度分享代码已升级到2.0&#xff0c;本页将介绍新版百度分享的安装配置方法&#xff0c;请点击左侧列表查看相关章节。 二、代码结构 分享代码可以分为三个部分&#xff1a;HTML、设置和js加载&#xff0c;…

ubuntu安装LDAP

参考文献&#xff1a; https://help.ubuntu.com/12.04/serverguide/openldap-server.html&#xff08;最主要的&#xff09; http://www.linuxidc.com/Linux/2011-08/40020.htm http://blog.chinaunix.net/uid-24276740-id-3360306.html 前言 在网上搜索ldap的安装配置&#xf…

58.贪心算法练习:  最小新整数

总时间限制: 1000ms 内存限制: 65536kB 描述 给定一个十进制正整数n(0 < n < 1000000000)&#xff0c;每个数位上数字均不为0。n的位数为m。现在从m位中删除k位(0< m)&#xff0c;求生成的新整数最小为多少&#xff1f;例如: n 9128456, k 2, 则生成的新整数最小…

ABB机器人之LOADDATA

ABB机器人之LOADDATA loaddata是用来描述连接到机器人机械接口的负载&#xff08;机器人的安装法兰&#xff09;。loaddata数据通常定义有效载荷或负荷&#xff08;通过指令gripload设置机器人抓手负载 或mechunitload指令设置变位机负载。loaddata通常也作为tooldata的一部分&…

【深度学习】——性能指标(ROC、MAP、AUC等)

目录 一、分类任务性能指标 1、混淆矩阵 2、精确度ACCURACY 正确数/总数 3、查全率&#xff08;RECALL&#xff09;——真正正样本中预测正确的比例 4、查准率&#xff08;precision&#xff09;——预测为正样本中的预测正确的比例 5、F-score——对查准率和查全率进行结…

【深度学习】——过拟合的处理方法

目录 一、什么是过拟合&#xff1f;&#xff08;overfitting&#xff09; 二、过拟合的表现&#xff08;判定方法&#xff09; 训练集、测试集、验证集区别 测试集与验证集的区别 三、产生过拟合的原因 1、样本方面 2、模型方面 四、避免过拟合的方法 1、样本方面 1&…

ASP.NET页面的字符编码设置

在用ASP.NET写网上支付的接口程序时&#xff0c;遇到一个奇怪问题&#xff0c;通过表单提交过去的中文全是乱码&#xff0c;英文正常。而用asp程序进行测试&#xff0c;可以正常提交中文&#xff0c;asp页面中有这样的HTML代码&#xff1a; <meta http-equiv"Content-T…

帝人製机--适合的机遇--遇到恰到好处的产品--工业机器人减速机造就一个百年企业

持之以恒是成功的必要条件&#xff0c;但是也要有恰当的土壤。日本Nabtesco(纳博特斯克)旧名&#xff1a;帝人製机(TEIJINSEIKI)高性能日本RV减速机纳博特斯克(Nabtesco)公司是一家居世界领先地位的精密传动控制系统及组件製造商。目前全世界已有超过两百万件由Nabtesco製造的精…

Python个人项目--豆瓣图书个性化推荐

项目名称: 豆瓣图书个性化推荐 需求简述&#xff1a;从给定的豆瓣用户名中&#xff0c;获取该用户所有豆瓣好友列表&#xff0c;从豆瓣好友中找出他们读过的且评分5星的图书&#xff0c;如果同一本书被不同的好友评5星&#xff0c;评分人数越多推荐度越高。 输入&#xff1a;豆…

#define宏定义形式的函数导致的bug

定义了一个宏定义形式的"函数": #define SUM8(YY)\ {\ int Y YY>>2;\ ...\ } 然后使用的时候&#xff0c;传入了一个同名的变量Y: int Y Ywin[x]; SUM8(Y) 本意是想展开成int Y Ywin[x]>>2; 但实际上#define只是把参数名(YY)替换&#xff0c;与函数…

【深度学习】——BN层(batch normalization)

目录 一、“Internal Covariate Shift”问题 二、BatchNorm的本质思想 两个参数r和β的意义——精髓所在 三、训练阶段如何做BatchNorm 四、BatchNorm的推理(Inference)过程 五、BatchNorm的好处 一般使用在卷积层后、激活层前 Batch Normalization作为最近一年来DL的重要…