关注嘉为科技,获取运维新知
01
当人们谈论微服务的时候,
他们究竟在说些什么?
微服务由MicroServices翻译而来,是一种软件架构风格,它以专注于单一责任与功能的小型功能区块为基础,利用模组化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关的API集互相通讯。
以上是维基百科对微服务的定义,专业词汇不算少,接下来我们通过对比传统的单体架构、SOA架构来理解微服务。
如何理解单体架构和微服务架构?
打个比方,现在需求生产一辆玩具车,一种做法是设计一条工序繁多、功能强大的生产流水线,各种原材料经过该流水线的加工处理,最终直接产出一辆完整的玩具车;
另一种做法是设计很多条工序简单、功能单一的流水线,分别用于生产车门、底盘、座椅、轮胎等部件,每个部件都预留好接口,生产完部件再将它们拼装成玩具车。
单体架构类似前一种生产玩具车的做法,最终产品很完整,但内部结构可能非常复杂,各部件难以拆分和替换,非要替换部件的话只能修改整条生产流水线,代价大,影响范围广。
微服务架构类似后一种做法,将复杂的生产流水线拆分成很多功能单一的流水线,各部件的生产流程相对简单,只要合理设计好部件的接口,最终也能顺利拼装出玩具车,如果想要替换部件,只需修改生产该部件的流水线,其他流水线几乎不受影响,修改成本低,影响小,效率高。
所以,当人们谈论微服务的时候,其实他们谈的是如何设计“乐高积木”,以及如何将这些“乐高积木”拼装成一套软件系统。
02
单体架构哪里错了?
自软件工程面世以来,单体架构就一直存在到现在,期间曾有SOA架构出来挑战其地位,最后以失败告终,现在又轮到微服务来下战书。讲道理,单体架构存在了几十年,贡献了大量优秀软件项目,为什么总有新架构来挑衅呢?
单体架构会将应用程序的所有功能都打包成一个独立的程序包,一个刚设计完的单体应用往往都具备一些共同点:结构清晰、依赖简单、方便开发和调试、易于部署和测试,一切完美无瑕。然而,软件项目是一个不断迭代和变化的过程,加模块、扩功能、改需求简直就是家常便饭,而所有的变化最终都得靠修改这个单体应用的代码来实现。
结果可想而知,就算开始时的设计再合理再完美,也会因为频繁的迭代和变更成长为一个庞然大物四不像,离当初的目标越来越远。
随着软件系统越来越庞大和复杂,潜藏的问题开始凸显出来——
代码难以维护:一个大型单体应用可能有几十人甚至几百人参与过代码开发,其内部结构的复杂度已经没有任何个人可以完全掌握;
性能难以扩展:几乎没有办法对局部高频使用的功能做针对性扩展,就算只为了提高很小一部分功能的负载能力,也不得不完整地扩展整套应用,造成严重的资源浪费;
系统稳定性差:改一发而动全身,有时一个微不足道的小问题,却能让整个系统无法正常使用;
开发效率低:所有人都在同一份代码上开发,代码冲突不断,开发工作因为代码版本的同步问题而停滞不前;
部署耗时:应用启动消耗时间长,任何小问题都可能导致启动失败,一旦出错只能全部重新来过;
技术过时:单体架构的技术选型,大多在开始的时候就确定了,如果一个工程迭代了很多年,那么几乎用不上后来出现的新技术,除非整体重构,而重构的代价是巨大的,过时的技术又吸引不了优秀开发者,进退两难。
所以说,单体架构小时候还是很优秀,只是成长的过程中承受不了各方面的变更压力,最终畸形了。如果可以不成长,单体架构依然是很好的选择,但事实证明这不太现实。
03
微服务和SOA有什么区别?
软件架构历史沿着单体架构、SOA架构、微服务架构的路径发展,如果比较这三者的差异,会发现SOA和微服务的理念其实很像,都是分布式架构,甚至微服务的很多概念都沿袭自SOA。
SOA即Service-Oriented Architecture,面向服务的体系架构,它也是以服务为维度来设计软件的。SOA的服务是宏观意义上的服务,或者说是功能组件,比如从ERP中抽离出一个功能相对独立的统一用户管理的小型系统,可独立部署使用,也可提供用户信息给ERP的其他模块使用。
虽然SOA谈的是面向服务,但它的核心组件其实是应用,服务只是应用对外提供的一种能力,并不能独立存在。所以,SOA可以理解为面向小型应用的架构,这些小型应用可以对外输出服务能力,服务接口大多数时候采用SOAP协议(即WebService),并通过ESB组件进行通信和管理。
SOA架构本来是为了去中心化,结果ESB却成为了事实上的中心和瓶颈,再加上重量级的SOAP协议性能不佳,最终慢慢走向没落。
微服务的“微”字,也许当初就是相对SOA服务而言的,实践微服务的先行者和贡献者Netflix公司,就曾将他们的架构称为“细粒度的SOA”,可见微服务和SOA一脉相承。
相比较SOA而言,微服务抛弃了SOAP协议,改用轻量级的HTTP RESTful API,抛弃繁琐的ESB组件,取而代之的是更加灵活轻便的API网关。微服务不再以小型应用为单位进行服务拆分,大多数微服务可能仅仅是一堆后端接口的集合,自身都构不成一个完整的功能模块。
微服务的服务拆分粒度比SOA更小也更灵活,可以由少数业务关联的API组成一个服务,也可以由很多API组成一个服务,甚至可以将单独一个高负载的接口封装成微服务,这一切完全根据业务需求、性能要求和扩展弹性来灵活设计。
所以,微服务是一个比SOA更轻量、更方便扩展、去中心化更彻底的分布式架构。轻量级这点很关键,它使得持续部署成为了可能,微服务、DevOps、容器化几乎是同一时间流行起来的,相信这不是简单的偶然事件。
04
微服务是软件架构的银弹吗?
布鲁克斯在30多年前的论文提出,没有任何一种单纯的技术或管理上的进步,能够保证在十年内大幅度地提高生产率、可靠性和简洁性,是为“没有银弹”。微服务的出现能否打破这魔咒呢?答案依然是“没有银弹”。
软件架构没有最好的,只有最合适的。支撑阿里双十一的技术架构足够强大了吧?然而它却不一定适合你,一是没有海量并发处理能力的需求,势必造成资源浪费,二是维护这样一套架构,额外需求的开发、运维人员可能比原本开发业务系统的人员还多。盲目跟风微服务,其结局也可能跟前面的例子一样,得不偿失。
首先,微服务的优势还是明显的——
◉ 复杂度可控:将原本单体应用内部的复杂度分而治之,每个微服务只负责单一的职责,复杂度显著降低;
◉ 独立部署,稳定性高:每个微服务单独一个进程,单个微服务的宕机、重新部署,对整个系统而言只是局部功能的暂时不可用,其他功能依然可以正常使用,而且,微服务一般会做双节点以上的高可用,因此系统的整体稳定性是比较高的;
◉ 扩展方便:针对负载高的微服务,可以快速地进行水平扩展,哪个负载压力大扩哪个,跟打地鼠游戏一样简单,弹指挥间实现服务的升降级;
◉ 技术选型灵活:由于微服务通过标准的HTTP协议通讯,对开发语言没有任何限制,因此每个微服务都可以自由选择技术类型,互不影响,新语言、新技术,想用就用。
不过,微服务的缺点也不少,特别对于小型项目来说。如果开发一个简单的CMS系统,也搬出微服务一整套架构,那就是杀鸡用牛刀,过度设计。让程序员抓狂的事情,一是产品经理变更需求,二是架构师过度设计。
接下来我们细数一下微服务的缺点——
◉ 维护难度高:虽然单个微服务的复杂度不高,但把所有微服务组合成一个完整应用的难度却不低,微服务的总体复杂度甚至高于单体架构。
一个微服务架构,不可或缺的组件包括API网关、服务注册与发现、消息机制、容错管理、负载均衡、日志收集、应用监控等等,必须把这些组件都准备完毕后,才能真正开始业务代码的开发。当某个功能报错时,整条调用链路的任何一环都可能导致这个错误,排查难度高,不像单体应用直接调试代码那么简单。
◉ 分布式事务:微服务的设计原则之一包括数据库隔离,这就成了分布式数据库,原本一个简单事务就能解决多表写操作,现在不得不考虑CAP理论和取舍、两段式提交、事务补偿等一大堆跟业务无关的技术难题;
原本一个JOIN语句就能搞定的联表查询,现在不得不考虑API调用链、并行处理、数据缓存等等,而最终的查询性能可能还不如JOIN来得高效。
◉ 异步消息:为了提高整体的吞吐能力和交互体验,很多时候消息队列是必须的,将接口调用的阻塞等待转化成异步回调,一个接口瞬间变俩,如果再加上分布式事务,编程复杂度直线上升。
◉ 调试复杂:微服务架构的应用,几乎很难在开发人员的电脑上运行所有的组件和服务,这将耗费非常多的CPU和内存资源,所以只能一部分服务在本地运行,一部分服务在公共服务器上运行,调试代码的时候需要到处切换环境排错,服务器上的接口还不方便debug,效率低下。
◉ 技术门槛高:拿Java Web项目来说,原本开发一个单体应用,程序员只要掌握好Java开发基础、常用框架技术、数据库基础差不多就够了,而一旦改用微服务,什么服务注册发现、消息队列、API网关、负载均衡、分布式事务、容错处理等一系列新技术、传统技术统统都得掌握,而且写代码时还必须头脑清晰有大局观,否则很容易写出一堆Bug。
◉ DevOps能力:除了开发技能过关外,团队还必须具备一定的DevOps能力了,否则会花费一大部分的时间在编译出包、部署排错、集成测试这些重复又琐碎的事情上面。
可见,微服务不是放之四海而皆准的银弹,只有深入理解微服务的优势和劣势,客观认识自身项目的业务和技术需求,才能做出最恰当的技术架构选择,避免为了微服务而微服务。
如果你已经跟微服务确认过眼神是符合实际要求的架构,那么后面的文章,我们将开始介绍具体的微服务落地技术。