如何用微服务重构应用程序

在决定使用微服务之后,为了将微服务付诸实践,也许你已经开始重构你的应用程序或把重构工作列入了待办事项清单。

无论是哪种情况,如果这是你第一次重构应用程序,那么您和您的团队必将在某个时刻面临一个显而易见的问题:如何重构应用程序以实现微服务?

这也正是这篇文章要思考和探讨的。

重构基础

在讨论如何将重构转化为微服务之前,退后一步,仔细观察微服务的内容和时间是很重要的。以下两个要点将会对任何微服务重构策略产生重大影响。

重构=重新设计

将一个单体式的应用程序重构为微服务,与重新设计一个基于微服务的应用程序, 有着本质区别。也许您更倾向于摒弃旧的应用程序(特别是面对杂乱无序的旧应用程序,这些应用程序在补丁修改和加固补充方面带来了沉重的技术债负担),制定一套新的需求, 并从零开始创建一个全新的应用程序,直接在微服务级别工作。

正如Martin Fowler在这篇文章中所指出,在微服务级设计一个新的应用程序可能不是一个好主意。Fowler的分析中最重要的一点是,在移动到基于微服务的架构时,从现有的单体式应用程序开始可以真正发挥微服务的优势。

通过现有的单体式应用程序,您可能会清楚地了解各种组件如何协同工作,以及应用程序如何作为一个整体运行的。而令人惊奇的是,从单体式的应用程序开始,您可以更深入地了解微服务之间的界限。通过观察他们是如何协作的,您可以更容易地看到,某个微服务能够独立于另一个微服务。

重构并不通用

对于重构,不存在一种适用一切的通用性方法,您所做的设计选择,从整体架构到代码级,都应考虑到应用程序的功能、运行条件以及开发平台和编程语言等因素。例如,您可能需要考虑代码打包—如果您正在使用Java,则可能涉及从大型企业应用程序存档(EAR)文件(每个文件可能包含多个Web应用程序存档(WAR)软件包)转移到单独的 WAR文件。

一般重构策略

以上是我们介绍的高层次考虑因素,现在让我们来看看重构的实现策略。对于现有的单体式应用程序进行重构,有三种基本方法。

增量

通过此策略,您可以逐个重构应用程序。随着时间的推移,这些组件通常是大规模的服务或相关服务组。要成功做到这一点,首先需要确立应用程序中的大范围边界,然后针对这些边界定义的单元进行重构,一次一个单元。您将持续不断地把每个大区域移动到微服务中,直到最终没有原始应用程序为止。

大变小

“大到小”策略在许多方面都是对增量重构基本主题的变体。然而,在大到小的重构中,您首先要将应用程序重构为单独的、大规模的、“粗粒度的”(使用Fowler的术语)块,然后逐渐将它们分解成更小的单元,直到整个应用程序被重构为真正的微服务。

此策略的主要优点是,它允许您稳定重构单元之间的交互,然后将它们分解为下一级,并在您开始下一轮重构之前,让您更清晰地了解较低层服务之间的边界和交互。

批量替换

通过批发更换,您可以一次性重构整个应用程序,直接从单体式转移到一组微服务器。它的优势在于,它允许您从顶层架构下进行重新设计,为重构作准备。虽然这一策略与微服务不一样,但它确实与微服务有着相同的风险,特别是当它涉及到广泛的重新设计时。

重构中的基本步骤

那么,将一个单体式应用程序重构为微服务的基本步骤是什么?有几种方法可以打破这个流程,但对于大多数重构项目来说,以下五个步骤是(或应该)通用的。

(1)准备工作

迄今为止我们所讨论的大部分是准备工作。要牢记的要点是,在重构现有的单体式应用程序之前,大架构以及要进行重构的基于微服务的版本的功能应已就绪。在重构时试图修复功能失调的应用程序,这只会使两项工作更加困难。

(2)设计:微服务域

在大规模、应用广泛的架构之下,您需要在重构之前制定(并应用)一些设计决策。特别是,您需要考虑哪种微服务组织形式最适合您的应用程序。组织微服务最自然的方式通常是进入基于通用功能、使用或资源访问的域:

  • 功能域。相同功能域内的微服务执行一组相关功能,或具有相关性的职责。例如,购物车和结帐服务可以包含在相同的功能域中,而库存管理服务将占用另一个域。
  • 使用域。如果您通过使用破解您的微服务器,那么每个域将围绕一个用例,或者更常见的,一组相互关联的用例。用例通常围绕用户(个人或其他应用程序)采取的一组相关行动,例如选择购买商品或输入付款信息。
  • 资源域。访问相关资源组(如数据库、存储或外部设备)的微服务也可以形成不同的域。这些微服务通常会处理这些资源与所有其他域和服务的交互。

请注意,在给定的应用程序中,三种组织形式都可能都存在。如果有一个总体规则,那么简单地说,您应该在它们最适合的时间和地点应用它们。

(3)设计:基础设施和部署

此步骤非常重要,但却很容易被视作事后再来考虑的问题。您正在将一个应用程序转换为一种非常动态的微服务群,通常在容器或虚拟机中,并由可能由多个应用程序组合的基础架构部署、编排和监控。此基础架构是您应用程序架构的一部分; 它可能(并且可能会)接管以前在单体式应用程序中由高级架构处理的一些职责。

(4)重构

这是您将应用程序代码实际重构为微服务的一个重点。确立微服务边界,识别每个微服务候选项的依赖关系,在代码和单元架构级别上进行必要的更改,以便它们可以作为独立的微服务来容纳,并将其封装在容器或VM中。这不会是一个没有问题的过程,因为在主要应用程序的规模上重写代码非常不易,但是,只要准备充分,您遇到的问题就更有可能局限于现有的代码问题。

(5)测试

当您进行测试时,您需要在基础架构(包括容器/ VM部署和资源使用)级别以及整体应用级别上查找微服务和微服务交互级别的问题。通过使用基于微服务的应用程序,所有这些都很重要,每个应用程序都可能需要自己的一套测试/监视工具和资源。当您发现问题时,了解什么级别的问题应该被处理是非常重要的。

结论

对微服务的重构可能需要下些功夫,但这并不难。只要您能做好准备,并清楚地了解所涉及的问题,您就能有效地重构您的微服务应用,而无需从头到尾重新设计。

原文来源:Rancher Labs


9月27日,北京海航万豪酒店,容器技术大会Container Day 2017即将举行。

CloudStack之父、海航科技技术总监、华为PaaS部门部长、恒丰银行科技部总经理、阿里云PaaS工程总监、民生保险CIO······均已加入豪华讲师套餐!

11家已容器落地企业,15位真·云计算大咖,13场纯·技术演讲,结合实战场景,聚焦落地经验。免费参会+超高规格,详细议程及注册链接请戳

这里写图片描述

高速换轮:Uber如何用微服务重构工程系统?

05-20

几个月前,我们讨论过Uber关于放弃它单一整体的代码库,而支持一种模块化的灵活的微服务结构。自那时候以来,我们已经花费了数千个小时,使用多种语言和多种不同的框架来扩展Uber的微服务(数以百计)生态系统。这种持续的重构是一个巨大的挑战,因此,我们趁机在Uber的微服务中采用了一套新的技术。通过一个技术栈和一套符合SOA迁移的标准,我们已经大大简化了整个服务的开发。rn rn开始一个新服务 rn rn rn在一个快速发展工程组织中,我们可能很难跟踪所有正在进行的工作。这种增长需要一个流程来防止不同团队之间的重复工作。在Uber,我们通过要求新服务的作者提交一份请求注解(RFC)来解决这个问题,RFC是一个新服务的高层次提案,概述了新服务的目的,架构,依赖,以及其他实现细节,以便其他Uber工程师进行讨论。RFC的目的有两个:rn rn1)征求意见,以便提高开发的服务质量,rn2)避免重复工作和挖掘合作机会。rn rn rn多个熟悉该领域的工程师会审核服务的设计。一旦反馈被纳入服务提案,就可以开始构建有趣的服务。rn rn实现一个新服务 rn rn rnTincup,我们的货币和汇率服务,这是一个很好的关于在Uber如何实现微服务的例子。Tincup是一个最新货币和汇率数据的接口。它有两个主要的服务:第一个是获取货币对象,第二个是获取给定货币的当前汇率(兑美元)。这两项功能是必须的,因为Uber是全球性的业务,汇率变动频繁,我们支持近60种货币的便捷交易。rn rn[img=http://img.bbs.csdn.net/upload/201605/20/1463739976_285973.jpg][/img]rn rn无论你在什么地方,你都可以通过点击侧边栏的图标来请求搭车。Tincup能保证你支付的是你所在国家的货币。rn rn通过新技术启动微服务 rn rn rn在构建Tincup时,需要重写所有与货币和汇率相关的逻辑,这就提供了一个好的机会来重新评估很久以前在Uber的设计方案。我们使用了很多新的框架,协议,约定来实现Tincup。rn rn首先,我们讨论了货币和汇率相关代码的整体结构。rn rn在Uber,近几年我们已经多次修改了许多数据集的持久层(像这一次)。每次的改变都是漫长而繁琐的。我们在这个过程中得到了很多经验教训,如果有可能的话,最好是将持久层与具体的应用逻辑进行分离。这就产生了一种应用开发的模式,我们称之为MVCS,它是对我们常用的MVC模式的扩展。它包含了一个服务层来实现应用的业务逻辑,通过将包含业务逻辑的服务层与应用的其它部分进行隔离,持久层就可以在不需要重构业务逻辑的前提下进行升级和替换(只有那些直接处理存储和读取数据的代码需要改变)。rn rn其次,我们认真考虑了货币和汇率的持久层。在Tincup之前,数据存在一个ID递增的关系型数据库——PostgreSQL中。rn rn然而,这种数据的存储方式不允许Uber的所有数据中心进行全球化的数据复制,因此,这一模式不符合我们现在全面发展(所有的数据中心同时提供服务)的架构。由于全球的数据中心都需要访问货币和汇率,我们在持久层使用UDR(Uber的全球复制可扩展数据存储)来实现数据交换。rn rn微服务中心成长的预期顾虑 rn rn rn在决定改变货币和汇率的设计之后,我们解决了很多工程生态系统中由微服务数量不断增加而自然而然会出现的问题。rn rn网络I/O的阻塞是一个严重的问题,可能会导致uWSGI工作线程的饥饿。如果所有的请求服务跟Tincup一样都是同步的,一个服务恶化的风险是可能会引起连锁反应,从而影响所有的调用者。我们决定采用Tornado(一个Python的基于循环事件的异步框架)来防止阻塞。由于我们已经将大量的代码从整体的基础代码库分离出来,我们便通过选择一个异步框架来保持现有应用逻辑保持与原来逻辑相同,这一点对保证风险最小化是非常重要的。Tornado满足我们这个要求,因为它允许我们使用一种非阻塞式的I/O来同步查找代码(此外,为了解决上述的I/O问题,许多服务的提供者使用一种新的Go语言)。rn rn曾经单个API的调用现在可能会波及到许多的微服务调用。为了便于在一个大的生态系统中发现其它服务和识别失败的点,Uber微服务在Hyperbahn(一个针对RPC在内部开发的网络多路复用帧协议)上使用开源的TChannel,TChannel为客户端和服务端提供协议,这两者通过Hyperbahn的智能路由进行连接。它解决了微服务世界中的几个核心的问题:rn1rn服务发现。所有的生产者和消费者通过路由网进行自我注册。消费者通过生产者的名称进行访问,而不需要知道生产者的服务器或端口。rn rn2rn容错。路由网可以追踪故障率和SLA( 服务等级协议)违例。它可以检测到不健康的主机,并随后将其从可用的主机池中进行删除。rn rn3rn速率限制和电路断开。这些特性确保来自客户端的错误请求和响应慢不会引起级联故障。rn rn rn由于微服务调用数量的快速增长,有必要为每个调用维护一个定义良好的接口。我们很清楚需要使用IDL(接口定义语言)来进行维护,我们最终决定使用Thrift。Thrift强制服务的提供者发布严格的接口定义,这就简化了整合服务的过程。Thrift拒绝不遵守接口定义的调用,而不是将其泄露到更深层次的代码而引起故障。这种公开声明接口的策略,强调向后兼容的重要性,因为多个版本的Thrift服务接口可能在任意时间中同时使用。服务的作者不能对接口做重大修改,只能对定义好的接口添加一些非重大改变的内容,直到所有消费者都不再使用。rn rn让Tincup成为行业佼佼者的准备:产品 rn rn rn最后,在Tincup的实现阶段将要完成时,我们是用一些有用的工具来准备生产环境的Tincup:rn rn首先,我们知道Uber的流行每天、每周、每年都是变化的。我们可以在预期的时间内看到巨大的高峰期,如除夕和万圣节,所以我们必须在发布之前确保这些服务能够处理这些增加的负载。按要求,在Uber发布一个新服务时,我们使用我们内建的Hailstorm来进行负载测试,确定Tincup功能点的缺陷和服务的中断点。rn rn然后,我们考虑Uber工程的另一个主要目标:更加有效的使用硬件。因为Tincup是一个相对轻量级的服务,它很容易与其他微服务共享机器。服务就是关爱,对吧?当然,事情也不总是如此:我们还是想确保每个服务独立运行,而不影响在同一台机器上的其他服务。为了防止这个问题,我们使用uContainer(Uber的Docker)来部署Tincup,以实现资源的隔离和限制。rn rn正如其名称所暗示的,uContainer使用Linux的容器功能和Docker来实现Uber服务的容器化。它将一个服务包装在一个隔离的环境中,以保证即使有其他服务在同一台主机上运行,该服务也能够始终如一的运行。uContainer扩展了Docker的功能,在Docker容器中增加了:rn1)更灵活的构建功能rn2)更多可视化工具。rn rn rn最后,为应对生产环境中不可避免的宕机和网络连接问题所做的准备,我们使用一个称之为uDestroy的内部工具来释放服务控制混乱问题。通过模拟宕机,我们可以认识的系统的恢复能力。由于我们在其发展的过程中定期的、有目的破坏系统,我们可以发现系统的漏洞,不断的提高系统耐用性。rn rn完成后的经验教训 rn rn rn通过构建Tincup来扩展 SOA的过程中,我们学到几条经验教训:rn rn用户的的迁移是一个长期的、缓慢的过程,所以尽可能的做到操作简单。提供代码示例。预测迁移完成所需的时间。rn技术栈的学习最好是建立在一个小的服务上。Tincup的应用逻辑非常简单,这样开发者可以集中精力去学习新的技术栈,而不是浪费时间在业务逻辑的迁移上。rn开发的初始阶段投入大量的时间在单元测试和集成测试,最终会收到回报的。在开发环境中执行代码调试会简单很多(压力也更小)。rn尽可能早的、频繁的去做负载测试。没有什么事情比发现你花费了几周或几个月实现的系统无法处理流量峰值更糟的了。rn rnUber的微服务 rn rn rnUber的SOA迁移为许多服务提供者,甚至是那些行业经验有限的人展示了机会。拥有一个服务是一项很大的责任,但是Uber开放的、知识共享的文化使得选择一套新的技术和拥有一个代码库成为了一种有回报、有价值的体验。rn rn来源:解放号杰微刊rn译者:刘晓鹏rn原文:REWRITING UBER ENGINEERING: THE OPPORTUNITIES MICROSERVICES PROVIDE

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试