微服务架构是近年社区讨论比较多的话题,为此,InfoQ 在 QCon 北京 2015 大会上策划了“微服务架构”专题。
ThoughtWorks 的首席咨询师王磊是国内较早倡导和实践微服务的先行者。他将在QCon 北京的“微服务架构”专题中分享《使用微服务架构改造企业核心业务系统的实践》。
王磊是开源软件的爱好者和贡献者,社区活动的参与者,《Ruby Gems 开发实战》(Practical RubyGems)一书的译者,GDCR 西安的组织者。他于2012 年加入ThoughtWorks,为国内外诸多客户提供项目交付和咨询服务;在加入ThoughtWorks 之前,曾就职过多家知名外企,具有丰富的敏捷项目实战经验。目前致力于微服务架构、高可用的Web 应用以及DevOps 的研究与实践。
InfoQ 在会前对他进行了专访。
InfoQ:首先,您能谈谈微服务这个概念提出的背景吗?
王磊:我觉得主要基于三个方面,互联网行业的快速发展,敏捷、精益方法论的深入人心以及传统 IT 系统面临互联网的挑战。过去的十年中,互联网对我们的生活产生了翻天覆地的变化。网上购物、网上订餐、网上支付,想到的,想不到的活动都可以在网上进行,越来越多的公司开始依赖互联网技术打造其核心的竞争优势。在这种情况下,如何快速响应用户的需求,如何用有效的技术服务于用户、并为用户持续提供价值,逐渐成为决定企业是否具有市场竞争力的重要因素之一。
纵观 IT 行业过去这些年中敏捷、精益、持续交付等价值观、方法论的提出以及实践,归根到底也是在围绕着如何帮助企业应变市场变化、提高对市场的响应力以及可持续发展能力。Lean Startup 帮助组织分析并建立最小 MVP,通过迭代持续改进;敏捷方法论帮助组织消除浪费,通过反馈不断找到正确的方向;持续交付帮助组织构建更快、更可靠、可频繁发布的部署和交付机制;云、虚拟化和基础设施自动化 (Infrastructure As Code) 的使用则极大的简化环境的创建、配置、安装以及部署;DevOPS 文化的推行更是打破了传统开发与运维之间的壁垒,帮助组织形成从开发、测试到部署、运维这样一个全功能化的高效能团队。经过这些方法论、价值观,或者说流程改进实践的推行和尝试后,在宏观上已经基本上形成了一套可遵循、可参考、可实施的体系。这时候,逐渐完善并改进各个细节的需求就会更加强烈。所谓细节,就是类似如何找到灵活性高、扩展性好的架构方式、如何用更合适的技术解决业务难题等。譬如说,在持续交付流水线已经趋于可靠、稳定的前提下,如何在技术上、架构上进行优化,进一步缩短产品构建的周期、进一步缩短自动化测试的周期等。
互联网时代的产品通常有几类特点:创新成本低、需求变化快,用户群体庞大,它和几年前我们熟悉的传统企业的 IT 系统——我们一般称为单块架构应用 (逻辑分层、功能集中、代码和数据中心化,并且运行在同一进程的应用程序)——有着本质的不同。这类单块架构系统随着需求变化快,用户访问量增加,面临着越来越多的挑战。譬如说,随着功能的增多,代码量逐渐增多,产品的维护成本、人员的培养成本、缺陷修复成本、技术架构演进的成本、系统扩展成本等都在增加。因此,在面临这种挑战下,如何找到一种更有效的、更灵活、更适应当前时代需求的应用架构方式就成了大家关注的焦点。
所以说,微服务的诞生并不是偶然,而是多重因素推动下的一个必然结果。
InfoQ:它能解决我们哪些痛点呢?
王磊:基本上,从我个人的观点,我认为微服务的出现解决了单块架构面临的以下一些挑战:
痛点 1:技术架构 / 平台升级难
传统的单块架构系统倾向采用统一的技术平台或方案来解决所有问题。而微服务的异构性,可以针对不同的业务特征选择不同的技术方案,有针对性的解决具体的业务问题。
对于单块架构的系统,初始的技术选型严重限制将来采用不同语言或框架的能力。如果想尝试新的编程语言或者框架,没有完备的功能测试集,很难平滑的完成替换,而且系统规模越大,风险越高。基于微服务架构,使我们更容易在遗留系统上尝试新的技术或解决方案。譬如说,可以先挑选风险最小的服务作为尝试,快速得到反馈后再决定是否试用于其他服务。这也意味着,即便对一项新技术的尝试失败,也可以抛弃这个方案,并不会对整个产品带来风险。
痛点 2:测试、部署成本高
单块架构系统运行在一个进程中,因此系统中任何程序的改变,都需要对整个系统重新测试并部署。 而对于微服务架构而言,不同服务之间的打包、测试或者部署等,与其它服务都是完全独立的。对某个服务所做的改动,只需要关注该服务本身。从这个角度来说,使用微服务后,代码修改、测试、打包以及部署的成本和风险都比单块架构系统降低很多。
痛点 3:可伸缩性差
单块架构系统由于单进程的局限性,水平扩展时只能基于整个系统进行扩展,无法针对某一个功能模块按需扩展。 而服务架构则可以完美地解决伸缩性的扩展问题。系统可以根据需要,实施细粒度的自由扩展。
痛点 4:构建全功能团队难
康威定律指出:一个组织的设计成果,其结构往往对应于这个组织中的沟通结构。传统的开发模式在分工时往往以技术为单位,比如 UI 团队、服务端团队和数据库团队,这样的分工可能会导致任何功能上的改变都需要跨团队沟通和协调。而微服务则倡导围绕服务来分工,团队需要具备服务设计、开发、测试到部署所需的所有技能。
痛点 5:异常破坏性大
微服务架构同时也能提升错误的隔离性。例如,如果某个服务的内存泄露,只会影响自己,其他服务能够继续正常地工作。与之形成对比的是,单块架构中如果有一个不合格的组件发生异常,有可能会拖垮整个系统。
InfoQ: 对于一个已有的单块架构,如何才能恰当地拆分成多个微服务?在一个微服务架构中,如何才能避免出现 monster service?因为如果业务稍微复杂的话,很难如愿地划分出高内聚低耦合的微服务,很多服务之间会有着千丝万缕的联系。把它们放在一起容易产生 monster service,拆分出来相互之间的调用又过于频繁。比如在一个订单系统中,Order Service 可能会调用 Product Service、Inventory Service 和 Customer Service,而 Inventory Service 可能也会调用 Product Service。如果系统越发复杂,各个服务之间的联系更加紧密的时候,微服务的粒度应该是什么样的?
王磊:首先,我认为微服务的‘微’并不是一个真正可衡量、看得见、摸得着的‘微’。这个‘微’所表达的,是一种设计思想和指导方针,是需要团队或者组织共同努力找到的一个平衡点。譬如说,有人觉得用代码行数来作为‘微’的衡量标准比较合适,也有人觉得微服务就应该逻辑简单,应该花费个 2 周的时间就能重写。我们知道对于不同的语言,完成同样功能的代码行数完全不一样,因此数字显然无法成为衡量微服务是否够微的因素。而 2 周时间,对个人而言,和其经验、业务背景、技术的熟悉程度都有关系,所以也无法成为衡量的标准。因此,微服务到底有多微,是个仁者见仁,智者见智的问题,最重要的是,团队觉得合适就好。
另外,微服务的实践,对运维和部署流水线要求非常高。微服务的粒度越细,就意味着需要部署的业务单元就越多,业务单元越多,就需要更稳定的自动化机制,能够创建运行环境,安装依赖,部署应用等;同时,由于生产环境上可运行的业务单元增多,登录服务器节点,查看日志,发现问题已经变得不现实。因此如何建立高效的监控、报警机制也是一个值得探索的话题。除此之外,单块架构的集成测试、功能测试维护起来都不容易,在分布式环境下、多个业务单元相互协同工作的微服务架构下,如何有效做集成测试以及测试策略会发生怎么样的改变,也是需要组织或者团队仔细思考的问题。当然,随着微服务数量的增多,最复杂的还是如何管理这些服务以及可视化服务之间的依赖,传统的 SOA、WebService 定义了类似服务注册、服务查找等机制,这是一种解决方式,但会形成‘中心’点,因为服务之间需要先从中心点找到需要协作的服务,再开始互相通信。我们目前采用的方式是通过对两两服务间进行测试,并上传测试成功后的接口数据,然后采用其他工具根据这些数据画出整体的服务依赖图。目前感觉这种方式现阶段还比较适合。所以,微服务的粒度也需要团队内部根据实际的运维能力出发,切忌为了微服务而微服务。
对于已有的单块架构而言,拆分微服务其实有很多的考虑因素,例如
- 业务的独立性
- 业务单元可能的扩展性
- 组织的运维能力
- 组织的持续交付能力
- 微服务管理的成本
另外,对于微服务的划分,可以基于业务模型,例如您所说的 Product、Customer、Inventory 等,也可以基于具体的业务行为,例如 Checkout、发送 Email 等,还可以考虑使用 Domain Driven Design 提倡的 BoundedContext 来做划分。
至于微服务的粒度,按照 Gartner 的企业系统分层,系统其实是分成三类的:数据系统,核心系统和创新系统。对于数据系统,考虑到需求不会那么频繁的变化,而且数据量也不一定很大,但考虑到需要企业长期维护,因此微服务的易维护性能发挥很大的作用,但也许可扩展性不是重要的考虑因素。对于核心系统,可能和数据系统类似,但更多需要考虑的是不同系统之间的集成,因此,如何有效集成不同系统,尽量不应该依赖于单一数据库作为集成点,可能是粒度划分的重要因素。对于创新性要求较高的系统,一般要求变化频繁,更新频繁,因此更能体现其灵活性、易维护性、独立性的价值。我们目前的助力客户的核心业务系统,其实是核心系统和创新系统的结合体。
InfoQ:相比单块架构,微服务是把进程内的调用转换成了服务之间的 HTTP 调用,是否会由此产生性能问题?
王磊:同单块架构相比,微服务更强调分布式的、跨进程的调用。由于分布式系统设计本身的复杂性,需要考虑到网络、带宽、延迟,以及容错性、数据一致性等,因此,如果只考虑接口调用之间的成本,分布式调用的成本肯定会远远高于进程内的调用成本。但是如果我们把范围放大了看,从整个产品或者应用的角度出发,因为微服务以及分布式带来的优势是易扩展性、灵活性以及独立性,因此,我们需要根据实际业务、根据组织的运维能力,找到一个实施微服务的平衡点。
InfoQ:如果某个服务的 API 发生改变的话,如何确保其消费者仍然能够得到正确的数据?能否简要介绍一下你们是如何编写契约测试的?
王磊:对,基于契约测试的机制就是为了解决这个问题的。
目前,我们是采用 PACT作为契约测试工具。PACT 是采用 Ruby 实现的一个契约测试工具,个人感觉从设计的思路、实现方式、易用性等方面来看,它非常棒,另外文档也很全面。实际上,PACT 也是随着 ThoughtWorks 在助力客户(澳洲最大的房产互联网门户)使用微服务改造后台业务系统的过程中所诞生的,它的灵感是来自微服务架构下如何解决服务调用者和服务提供者之间集成测试难的问题。关于如何编写 PACT 测试,官方的文档已经很全面了,所以,有兴趣的朋友们可以了解一下。
另外,ThoughtWorks 还开源了一个叫 PACTO的契约测试工具,也是用 Ruby 实现的,不过我在项目中并没有使用过,感兴趣的朋友也可以了解一下。
InfoQ:微服务架构是否适用于互联网应用?
王磊:我觉得是非常适合的。因为从微服务诞生的背景、时机,到微服务本身的特点和优势来看,微服务作为一种应用架构模式,是非常适合互联网的快速变化的。一方面,微服务能满足互联网快速变化的需求,另外一方面,微服务也能降低技术选型、包括技术替换的风险,除此之外,微服务是真正意义上的按需扩展,我们可以根据对系统功能进行合适粒度的划分,来决定什么样的功能需要扩展,以及怎么样的水平扩展。
我们知道,互联网不仅市场变化快,而且技术方案变化也快。譬如,短短几年几年时间,光前端 JavaScript 的框架,就出现了好几十个,从早一点的 Backbone、Ember 到 AngularJS、ReactJS 等等,类似的后端的框架、工具,数据存储系统等也是层出不穷。
其实,业界著名的使用微服务架构例子,大部分都是来自互联网行业。譬如 Amazon、Netflix、Gilt 以及 REA 等等。不过,他们也是在经过了长时间对持续交付、DevOps 以及运维方面的实践和经验积累之后,逐渐地、持续地采用微服务架构的。
InfoQ:感谢您接受我们的采访,期待您在 QCon 上的精彩分享。
感谢臧秀涛对本文的审校。
评论