美文网首页系统架构
你真的需要微服务吗?

你真的需要微服务吗?

作者: 猿学堂 | 来源:发表于2019-11-24 20:03 被阅读0次

    1、前述

    自互联网尤其是云平台爆发以来,软硬件基础设施的服务模式不断更新,从早期的IaaS、PaaS、SaaS三大件,到后来的FaaS、BaaS、DaaS,一切以aaS格式表述的新词从各个服务公司的口中提出来,成为技术服务模式的前沿和潮流。所有平台式技术服务的输出,都会以不同形式降低原有的软件开发及运维成本。

    开发及运维成本的降低,促使企业可以以同样的人力去维护更加庞大复杂的基础设施平台。在这个基础上,企业可以应对越来越复杂化的应用架构改造升级。而这种改造升级在云平台及成熟的大规模运维工具出现之前,是几乎不可能的。

    微服务便是在这种大背景下应运而生的一种架构形式。离开了云基础设施、容器以及大规模的资源编排工具,基于微服务架构的软件系统运维成本大大高于传统架构模式,这足以让绝大多数公司望而却步。

    当下的应用架构,微服务和ServiceMesh、云原生俨然已经成为一种事实标准,而传统的Web应用架构、模块化架构已经被弃之如敝履,鲜有人提及。许多人拿着微服务去应用于一切软件架构场景。从未考虑,由微服务架构导致的应用层面的复杂度上升是否真的划算,传统的架构形式是否是一种更合适的选择。

    此时,我们应问一句:你真的需要微服务吗?你的架构是不是过度设计了?

    我们有必要从传统应用架构模式出发,结合近十年来现代应用场景的不断变化,了解其所面临的挑战以及可能存在的解决方案。通过这个过程中去分析微服务产生的背后原因。只有纵向的去分析应用架构的发展历程,才会知其然更知其所以然,从而更理性的评估和设计软件架构,不会盲从而动。

    2、传统应用架构的局限及应对之道

    笔者注:软件应用架构类型繁多,要一一列举已超出本文范围。此处所谓的传统应用架构,主要是针对B/S、SOA等互联网应用架构,不考虑诸如C/S等架构形态。

    传统应用架构的上一次颠覆式突破应该是“动态脚本”到MVC。彼时,互联网应用无论从并发访问量还是数据量上,都未形成明显的瓶颈,反而业务复杂度以及由此导致的可维护性、业务组件的复用性是主要的问题。显而易见,基于“动态脚本”是无法实现良好的可维护性和可复用性的(这么说也有点绝对,只能说实现成本比较高,门槛也比较高,不适合推广到普通的研发团队)。

    MVC的出现完美的解决了这一问题。基于Java的Struts以及后起之秀Spring MVC,基于PHP的Zend Framwork、ThinkPHP都是MVC架构的杰出代表。MVC本质上解决了应用层的问题,但是对于视图层、存储层并未有好的解决方案。以基于Java的各MVC框架为例,视图层通过集成各种模板引擎解决,而存储层则完全交给了开发者,采用各种ORM框架来完成。Spring Framework这类“中间层”(如果可以这么叫)框架,像胶水一样,把各层的框架整合到一起,形成软件的主体技术架构。

    在MVC良好的运行的数年之后,两个主要矛盾促使了技术架构的又一次颠覆性变化。

    2.1、前后端分离

    我们知道,在很长一段时间内,Web应用是以后端为主导的,因为前端的产出物是静态页面,而实际部署环境却是“动态脚本”或者“模板文件”,这决定了前端在整个开发过程中“附属”于后端。还有一个问题,就是对于复杂的Web系统,传统的脚本形式复用程度较低,很难形成复用程度良好的前端组件。

    前端组件复用的问题,在MVC产生的时候,实际上就已经有相关的方案了,如JSF、Tapestry、Wicket等面向组件的开发框架便是为了解决此问题,像Tapestry、Wicket的模板直接是HTML,在一定程度上实现了前后端分离(只是技术上,而非工程上,所以并不是一个完美的方案)。

    在技术上和工程上都成熟的前后端分离方案当然是近几年基于NodeJS产生的各种开发框架及工程化方法。诸如Vuejs、Angularjs、Reactjs都是在这个背景下产生的,MVVM模式也已成为前端框架的构架方式。NodeJS的生态建设非常好,以致鼎盛时期,很多前端人员以为不再需要存在专门的后端开发工程师(这在今天看来,就像NoSQL风头正劲时,高喊关系数据库已死的人如出一辙)。

    前后端分离做到了开发人员的解耦,提升了开发效率,也促使原有的MVC架构趋向于服务化(不再需要“动态脚本”生成界面)。

    2.2、互联网规模的急速扩张

    近十年互联网规模的急速扩张、移动互联网的大规模普及、互联网企业对于用户越来越精细化的运营,这一切对系统架构提出了巨大的挑战。规模的扩张意味着并发访问量的上升,移动互联网的普及意味着交互场景的变化、不同形态产品(PC Web、Mobile Web、App)的后端架构的复用,而精细化运营则带来了海量数据的存储及计算的需求。

    这一切带来了三个重要的变革:

    • 为了承载大规模用户的并发访问,原有的小规模集群实例的方式已经远远不能满足运营的需要,大规模分布式集群架构应运而生。
    • 为了支撑不同形态产品的同时,最大程度的降低研发成本,前端领域日新月异、百花齐放。
    • 为了应对海量数据的存储以及计算,分布式存储、大数据计算平台也在几年内层出不穷。

    对于最后两点,本文不作展开讨论,仅讨论大规模分布式集群架构对传统应用架构的影响。

    3、传统应用架构的应对之道

    早期Web应用的典型架构如下图所示:

    image

    后端应用为了保证可用性,采用多实例的模式,进行负载均衡。数据库采用主备和读写分离的方式,确保数据安全。此外,通过缓存热点数据,提升数据访问性能。

    当并发量上升或者数据量到达一定规模之后,增加应用服务器数量或者数据缓存并不能显著提升应用的总体性能,因为此时系统的性能瓶颈集中于数据库,而热点数据只能算是一小部分数据。

    这个时候的解决方案就是拆表或者拆库。拆表并未降低数据库请求压力,但是提升了单个请求的处理性能(扫描数据量减小),副作用是增加了跨表查询的复杂度。拆库分为纵向和横向两个方向。所谓纵向,就是按照数据架构的边界和业务域,将数据库拆分为多个,如将数据库拆为产品数据库、订单数据库、用户数据库等。所谓横向,是每个数据库都包含所有的数据表,按照一定的拆分规则只存放一部分数据。如北京的数据一个库、上海的数据一个库。

    不难发现,横向的拆库是人为的将应用系统拆分为多个独立的实例,这对于涉及到跨库的业务时(如北京的用户办理上海的业务),实现非常复杂。因此更合适的方式是纵向拆库,然后在拆库的基础上,还可以配合拆表再作进一步优化。

    既然纵向上按照数据架构和业务域拆库是一种相对合理的方案,那么由此导致的应用模块化部署也就顺理成章了。变更后的架构如图所示:

    image

    再考虑对不同接入形式的支持,如Web、App,架构上便需要将Web控制层与应用服务层分离:

    [站外图片上传中...(image-78d57b-1574596990011)]
    随着存储技术的不断发展,数据库存储不再是一种单一的选型方案,而是在应用架构中综合不同中间件来应对不同的业务场景。如强一致性、结构化的处理结果采用关系数据库存储,而非结构化、弱一致性的数据通过分布式NoSQL来实现。NoSQL数据库由于其分布式架构,可以不用像关系数据库一样详细考虑各种拆库、拆表的方案。

    此种架构方案完全可以满足中等规模的软件系统对于性能、可用性的需求。但是随着业务的发展,会面临以下几个问题:

    • 应用集群规模的增加,导致运维成本的上升
    • 业务不断变化,会存在更频繁、更细粒度的交付

    云基础设施,尤其是容器技术的不断发展,有效的降低了大规模分布式集群的运维成本。而更细粒度的模块化部署也可以实现灵活的发布升级。这一切与“微服务”并没有直接关系。更多的是基础设施的改造、应用架构的拆分、细粒度的项目管理及团队组织架构。

    如果你的应用架构只是在上述方案的基础上,实现了云化部署、细粒度交付,那么这并不是微服务架构,即便你使用了当前的一些微服务框架,如Dubbo、Spring Cloud。

    4、微服务概念及价值

    4.1、什么是微服务

    维基百科的定义

    微服务(Microservices) 是一种软件架构风格,它以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模组化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关 (Language-Independent/Language agnostic) 的API集相互通讯。

    我们看一下微服务经常被人提及的一些特征和优势:

    特征:

    • 单一职责:这是良好的模块化架构均应具备的,并非微服务所独有
    • 轻量级的通信:在前述传统的模块化架构下,这也是需要具备的
    • 隔离性:此处指微服务都运行于独立的进程、独立的数据库。显然,从技术角度看,与传统模块化架构并没有太大区别
    • 技术异构:不同微服务可以采用不同的技术,降低了引入新技术的难度以及风险。同理,与之前架构差别不大

    优势:

    • 独立性:每个微服务的构建、部署、扩容、缩容、数据库都是独立的,互不影响
    • 敏捷性:功能单一、可快速添加新需求
    • 技术栈灵活:可以发挥不同语言的优势
    • 高效团队:可以多个小规模团队并行开发、独立交付
    • 容错:在微服务架构下,故障会被隔离在单个服务中。

    显然,这里面的大部分对于一个良好的传统模块化架构也是可以满足的。既然把微服务的优势都否定了,那么微服务的价值到底是什么?

    实际上有这个结论并不奇怪,因为微服务就是以良好的模块化为基础,在这一点上,它与传统的模块化架构没有区别。它的区别在于基于模块化架构,附加的一些架构特性,这些是微服务所特有的,也是微服务的真正优势。

    笔者注:容错需要微服务是完全自治的,这对于微服务的设计、数据一致性等提出了非常高的要求。而且多数业务场景下,可能直接不可用是更合理的。

    笔者注:除了以上特征及优势,还有人认为微服务提升了资源利用率,这种观点基本就属于错误了。与基于云的微服务部署相比,显然单机多实例部署的利用率更高,只是运维比较复杂而已。还有认为微服务提升了服务性能的,就更是错误了。任何增加网络开销的调整,都会降低性能。因此如果你的微服务性能提升了,只能说是分布式、异步处理或者其它架构调整带来的效果。

    4.2、微服务的价值

    传统模块化架构的不足之处在于,它对于细粒度部署产生的应用架构层面的问题并未形成统一、完善的解决方案。

    • 路由:当系统以模块为单位独立部署运行时,模块与模块之间的接口调用是远程调用。因此需要按照一定的路由规则去完成。如负载均衡、同机房、IP段等等。
    • 安全:当模块之间的调用变为远程调用后,访问安全也是需要重点考虑的。
    • 限流:服务需要通过灵活的限流措施,来控制模块之间的远程访问。避免上游的流量洪峰压垮下游服务集群,导致故障进一步扩散。
    • 缓存:对于远程调用,可以通过结果缓存的方式提升访问效率,尤其是对于一些查询类接口。
    • 监控:对服务的运行状态进行有效监控,及时发现异常。
    • 重试:对于访问失败的情况,可以采用重试的方式确保链路执行成功。
    • 熔断:当服务出现过载现象后,可以对系统进行有效保护,避免出现系统故障。
    • 版本管理:可以支持多版本并存,以支持不同模块的调用和灰度测试。

    微服务框架针对以上几个方面,提供了系统化的解决方案。因此,我们基于此可以构建更加健壮的模块化系统架构。配合云基础设施、持续交付则为微服务的大规模高效运维提供了保障,也是微服务架构取得成功的一大前提。

    4.3、微服务的代价

    微服务导致应用架构以及数据架构的急速复杂化,主要体现在以下几个方面:

    • 数据一致性:因为每个微服务都拥有一个独立的数据库,因此微服务之间的调用会跨越多个数据库,甚至多种存储。此时,数据一致性的解决方案将会非常复杂。
    • 服务调用管控的复杂化:当拥有数百个(微服务架构很常见,但是传统模块化架构并不多见)微服务且存在各种远程调用依赖时,如何有效维护服务之间的依赖关系是一项非常困难的工作。
    • 测试完整的服务调用链条更复杂:当一个完整的业务链条跨越数个服务才可以完成时,测试该服务的难度也比传统架构要困难很多。

    当然,我们得承认,传统模块化架构也会存在这些问题,只是微服务加速了这一点,因为它们的粒度更细。

    如果你了解过微服务数据一致性的方案(如Saga),也许你会直接选择放弃。虽然这是一句玩笑话,但是确实需要在数据一致性与其带来的成本之间好好权衡。与数据一致性相比,可能你更关心代码的可读性、业务逻辑可维护性。

    通过一些工具,我们可以有效缓解服务调用管控的复杂化问题,前提是你的架构有必要如此复杂,否则再有效的工具也是在增加你的成本。

    5、如何选择

    在微服务与传统的模块化架构之间我们该如何选择呢?

    在回答这个问题之前,实际上我们应该审视一下自己的需求,微服务带来的收益是否远远大于成本。你的需求是不是模块化可以解决的?如果不能,还需要引进哪些架构层面的方案?如果就架构质量而言,4.2节中提到的你一个都用不着,那就没必要考虑微服务架构了,或者说即便引用了微服务框架,如Dubbo,但你的系统实际上并不是微服务架构。

    除此之外,我们还要考虑数据架构。你是否需要如此细粒度的数据库的拆分,还要考虑各种冗余及同步策略以确保数据可以有效的访问(如订单上的客户信息、地址信息)?如果应用架构充分服务化,但是数据库还是集中存储,那么这也不是微服务架构。

    微服务架构的细粒度带来的是高度并行和自由(无论是应用还是开发过程),同时也带来了各种的成本,任何架构都有其优势,也有其劣势。我们要结合实际需求,尤其是系统的非功能性需求,团队组织结构、研发过程、运维环境等因素来选择合适的架构方案。

    扫描关注我们

    image

    相关文章

      网友评论

        本文标题:你真的需要微服务吗?

        本文链接:https://www.haomeiwen.com/subject/wccrwctx.html