微服务理论向介绍

微服务介绍

微服务概述

微服务架构的由来

​ 微服务最早由Martin Fowler与James Lewis于2014年共同提出,微服务架构风格是一种使用一套小服务来开发单个应用的方式途径,每个服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API,这些服务基于业务能力构建,并能够通过自动化部署机制来独立部署,这些服务使用不同的编程语言实现,以及不同数据存储技术,并保持最低限度的集中式管理。

什么是微服务架构

​ 微服务的概念源于2014年3月Martin Fowler所写的一篇文章“Microservices” .

https://martinfowler.com/articles/microservices.html

​ 维基上对其定义为:一种软件开发技术- 面向服务的体系结构(SOA)架构样式的一种变体,将应用程序构造为一组松散耦合的服务。在微服务体系结构中,服务是细粒度的,协议是轻量级的。

​ 另一种定义:微服务是一种分布式系统解决方案,推动细粒度服务的使用,每个服务都可以独立运行, 且这些服务可以协同工作。

​ 微服务的理解,什么是"微"、什么是"服务", 微 狭义来讲就是体积小.而服务,一定要区别于系统,服务一个或者一组相对较小且独立的功能单元,是用户可以感知最小功能集。

​ 微服务的特点:小而独立.“小”,小就是简单,简单到通过名字或者定义就可以知道它大概能干什么事了,而且只干这一件事;“独立”,微服务定义中的任何一个系统都应该可以独立部署、独立运行,并能独立完成一个业务闭环。

​ 通常而言,微服务架构是一种架构模式或者说是一种架构风格。它提倡将单一应用程序划分成一组小的服务,每个服务运行独立的自己的进程中,服务之间互相协调、互相配合,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API) 。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。

为什么需要微服务架构

SOA架构特点

系统集成:站在系统的角度,解决企业系统间的通信问 题,把原先散乱、无规划的系统间的网状结构,梳理成 规整、可治理的系统间星形结构,这一步往往需要引入 一些产品,比如 ESB、以及技术规范、服务管理规范; 这一步解决的核心问题是【有序】

系统的服务化:站在功能的角度,把业务逻辑抽象成 可复用、可组装的服务,通过服务的编排实现业务的 快速再生,目的:把原先固有的业务功能转变为通用 的业务服务,实现业务逻辑的快速复用;这一步解决 的核心问题是【复用】

业务的服务化:站在企业的角度,把企业职能抽象成 可复用、可组装的服务;把原先职能化的企业架构转变为服务化的企业架构,进一步提升企业的对外服务能力;“前面两步都是从技术层面来解决系统调用、系统功能复用的问题”。第三步,则是以业务驱动把一个业务单元封装成一项服务。这一步解决的核心问题是【高效】

单体架构的优缺点

​ “单体应用(monolith application)”就是将应用程序的所有功能都打包成一个独立的单元,可以是JAR、EXE、BIN或其它归档格式。

优点

  • 开发简单直接,集中式管理, 基本不会重复开发

  • 功能都在本地,没有分布式的管理开销和调用开销。

缺点

  • 开发效率低:所有的开发在一个项目改代码,递交代码相互等待,代码冲突不断

  • 代码维护难:代码功能耦合在一起,新人不知道何从下手

  • 部署不灵活:构建时间长,任何小修改必须重新构建整个项目,这个过程往往很长

  • 稳定性不高:一个微不足道的小问题,可以导致整个应用挂掉

  • 扩展性不够:无法满足高并发情况下的业务需求

微服务的优缺点

优点

  • 微服务是松藕合的,无论是在开发阶段或部署阶段都是独立的。

  • 能够快速响应, 局部修改容易, 一个服务出现问题不会影响整个应用。

  • 易于和第三方应用系统集成, 支持使用不同的语言开发, 允许你利用融合最新技术。

  • 每个微服务都很小,足够内聚,足够小,代码容易理解。团队能够更关注自己的工作成果, 聚焦指定的业务功能或业务需求。

  • 开发简单、开发效率提高,一个服务可能就是专一的只干一件事, 能够被小团队单独开发,这个小团队可以是 2 到 5 人的开发人员组成。

缺点

  • 运维要求较高

​ 整体应用可能只需部署至一小片应用服务区集群,而微服务架构可能变成需要构建/测试/部署/运行数十个独立的服务,并可能需要支持多种语言和环境。这导致一个整体式系统如果由20个微服务组成,可能需要40~60个进程。必须有坚实的DevOps开发运维一体化技能:开发人员需要熟知运维与投产环境,开发人员也需要掌握必要的数据存储技术如NoSQL,具有较强DevOps技能的人员比较稀缺,会带来招聘人才方面的挑战。

  • 分布式的复杂性

​ 作为一种分布式系统,微服务引入了复杂性和其他若干问题,例如网络延迟、容错性、消息序列化、不可靠的网络、异步机制、版本化、差异化的工作负载等,开发人员需要考虑以上的分布式系统问题。

  • 隐式接口及接口匹配问题

​ 把系统分为多个协作组件后会产生新的接口,这意味着简单的交叉变化可能需要改变许多组件,并需协调一起发布。在实际环境中,一个新品发布可能被迫同时发布大量服务,由于集成点的大量增加,微服务架构会有更高的发布风险。

  • 重复劳动

​ 对于单体架构来讲,如果某段业务被多个模块所共同使用,我们便可以抽象成一个工具类,被所有模块直接调用,但是微服务却无法这样做,因为这个微服务的工具类是不能被其它微服务所直接调用的,从而我们便不得不在每个微服务上都建这么一个工具类,从而导致代码的重复。

  • 异步机制

    微服务往往使用异步编程、消息与并行机制,如果应用存在跨微服务的事务性处理,其实现机制会变得复杂化。

  • 可测性的挑战

​ 在动态环境下服务间的交互会产生非常微妙的行为,难以可视化及全面测试。经典微服务往往不太重视测试,更多的是通过监控发现生产环境的异常,进而快速回滚或采取其他必要的行动。但对于特别在意风险规避监管或投产环境错误会产生显著影响的场景下需要特别注意。

微服务架构与单体架构的区别
  1. 单体架构所有的模块全都耦合在一块,当代码量增大时,维护的困难呈指数增长,微服务每个模块就相当于一个单独的项目,代码量明显减少,遇到问题也相对来说比较好解决。
  2. 单体架构所有的模块都共用一个数据库,存储方式比较单一,微服务每个模块都可以使用不同的存储方式(比如有的用redis,有的用mysql等),数据库也是单个模块对应自己的数据库。
  3. 单体架构所有的模块开发所使用的技术一样,微服务每个模块都可以使用不同的开发技术,开发模式更灵活。
微服务架构与SOA架构的区别

SOA和微服务架构一个层面的东西,核心目的都是以服务为核心的架构,强调敏捷及快速推出市场. 而对于ESB和微服务网关是一个层面的东西,一个谈到是架构风格和方法,一个谈的是实现工具或组件。

​ SOA(Service Oriented Architecture)“面向服务的架构”:他是一种设计方法,其中包含多个服务, 服务之间通过相互依赖最终提供一系列的功能。一个服务 通常以独立的形式存在与操作系统进程中。各个服务之间 通过网络调用。

​ 微服务架构:其实和 SOA 架构类似,微服务是在 SOA 上做的升华,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。

微服务架构 = 80%的SOA服务架构思想 + 100%的组件化架构思想 + 80%的领域建模思想

功能 SOA 微服务
组件大小 大块业务逻辑 单独任务或小块业务逻辑
耦合 通常松耦合 总是松耦合
公司架构 任何类型 小型、专注于功能交叉团队
管理 着重中央管理 着重分散管理
目标 确保应用能够交互操作 执行新功能、快速拓展开发团队

微服务架构的主要特点

​ 微服务架构是一种松耦合的、有一定的有界上下文的面向服务架构。它的主要特点是组件化、松耦合、自治、去中心化,体现在以下几个方面:

  • 细粒度的服务分解
    服务粒度要小,而每个服务是针对一个单一职责的业务能力的封装,专注做好一件事情。
  • 独立部署运行和扩展
    每个服务能够独立被部署并运行在一个进程内。这种运行和部署方式能够赋予系统灵活的代码组织方式和发布节奏,使得快速交付和应对变化成为可能。
  • 独立开发和演化
    技术选型灵活,不受遗留系统技术约束。合适的业务问题选择合适的技术可以独立演化。服务与服务之间采取与语言无关的API进行集成。相对单体架构,微服务架构是更面向业务创新的一种架构模式。
  • 独立团队和自治
    团队对服务的整个生命周期负责,工作在独立的上下文中,自己决策自己治理,而不需要统一的指挥中心。团队和团队之间通过松散的社区部落进行衔接。

微服务架构的一些通用特性

根据MartinFowler的分析,微服务架构有以下的一些通用特性,但并非所有微服务架构应用都必须具备所有这些特性:

  1. 过服务实现应用的组件化(Componentizationvia Services):微服务架构中将组件定义为可被独立替换和升级的软件单元,在应用架构设计中通过将整体应用切分成可独立部署及升级的微服务方式进行组件化设计。
  2. 围绕业务能力组织服务(Organizedaround Business Capabilities):微服务架构采取以业务能力为出发点组织服务的策略,因此微服务团队的组织结构必须是跨功能的(如:既管应用,也管数据库)、强搭配的DevOps开发运维一体化团队,通常这些团队不会太大(如:亚马逊的“Two pizzateam”- 不超过12人)。
  3. 产品而非项目模式(Productsnot Projects):传统的应用模式是一个团队以项目模式开发完整的应用,开发完成后就交付给运维团队负责维护;微服务架构则倡导一个团队应该如开发产品般负责一个“微服务”完整的生命周期,倡导“谁开发,谁运营”的开发运维一体化方法。
  4. 智能端点与管道扁平化(Smartendpoints and dumb pipes):微服务架构主张将组件间通讯的相关业务逻辑/智能放在组件端点侧而非放在通讯组件中,通讯机制或组件应该尽量简单及松耦合。RESTful HTTP协议和仅提供消息路由功能的轻量级异步机制是微服务架构中最常用的通讯机制。
  5. “去中心化”治理(DecentralizedGovernance):整体式应用往往倾向于采用单一技术平台,微服务架构则鼓励使用合适的工具完成各自的任务,每个微服务可以考虑选用最佳工具完成(如不同的编程语言)。微服务的技术标准倾向于寻找其他开发者已成功验证解决类似问题的技术。
  6. “去中心化”数据管理(DecentralizedData Management):微服务架构倡导采用多样性持久化(PolyglotPersistence)的方法,让每个微服务管理其自有数据库,并允许不同微服务采用不同的数据持久化技术。
  7. 基础设施自动化(InfrastructureAutomation):云化及自动化部署等技术极大地降低了微服务构建、部署和运维的难度,通过应用持续集成和持续交付等方法有助于达到加速推出市场的目的。
  8. 故障处理设计(Designfor failure):微服务架构所带来的一个后果是必须考虑每个服务的失败容错机制。因此,微服务非常重视建立架构及业务相关指标的实时监控和日志机制。
  9. 演进式的设计(EvolutionaryDesign):微服务应用更注重快速更新,因此系统的计会随时间不断变化及演进。微服务的设计受业务功能的生命周期等因素影响。如某应用是整体式应用,但逐渐朝微应用架构方向演进,整体式应用仍是核心,但新功能将使用应用所提供的API构建。再如在某微服务应用中,可替代性模块化设计的基本原则,在实施后发现某两个微服务经常必须同时更新,则这很可能意味着应将其合并为一个微服务。

微服务本质

  1. 微服务,关键其实不仅仅是微服务本身,而是系统要提供一套基础的架构,这种架构使得微服务可以独立的部署、运行、升级,不仅如此,这个系统架构还让微服务与微服务之间在结构上“松耦合”,而在功能上则表现为一个统一的整体。这种所谓的“统一的整体”表现出来的是统一风格的界面,统一的权限管理,统一的安全策略,统一的上线过程,统一的日志和审计方法,统一的调度方式,统一的访问入口等等。
  2. 微服务的目的是有效的拆分应用,实现敏捷开发和部署 。
  3. 微服务提倡的理念团队间应该是 inter-operate, not integrate 。inter-operate是定义好系统的边界和接口,在一个团队内全栈,让团队自治,原因就是因为如果团队按照这样的方式组建,将沟通的成本维持在系统内部,每个子系统就会更加内聚,彼此的依赖耦合能变弱,跨系统的沟通成本也就能降低。

什么样的项目适合微服务

微服务可以按照业务功能本身的独立性来划分,如果系统提供的业务是非常底层的,如:操作系统内核、存储系统、网络系统、数据库系统等等则不适合使用微服务架构.

  1. 记录型系统(System of Record)将从微服务方法中获益最多。例如可将大型应用按相对独立的业务功能分解成若干个微服务实现。
  2. 交互型系统(System of Engagement)也将受益于微服务方法,例如渠道应用可以应用“后端服务前端”的模式实现。
  3. 分析型系统(System of Insight)则可能对微服务受益不多。其他架构模式如管道及过滤模式可能更适用于分析型系统。

能不能做成微服务,取决于四个要素:

  • 小:微服务体积小,2 pizza 团队。
  • 独:能够独立的部署和运行。
  • 轻:使用轻量级的通信机制和架构。
  • 松:为服务之间是松耦合的。

微服务设计

​ 微服务架构的核心目标是把复杂问题简单化,通过服务划分,把一个完整的系统拆分成多个高内聚、低耦合的小的子系统。使每个子系统可以独立的运行、升级和测试。然后再通过一些集成手段将这些子系统组合在一起,对外提供完整功能的过程。所以我们对微服务设计的过程就是对系统如何做拆分和集成的过程。

单一职责原则

  • 意思是每个微服务只需要实现自己的业务逻辑就可以了,比如订单管理模块,它只需要处理订单的业务逻辑就可以了,其它的不必考虑。

服务自治原则

  • 意思是每个微服务从开发、测试、运维等都是独立的,包括存储的数据库也都是独立的,自己就有一套完整的流程,我们完全可以把它当成一个项目来对待。不必依赖于其它模块。

轻量级通信原则

  • 首先是通信的语言非常的轻量,第二,该通信方式需要是跨语言、跨平台的,之所以要跨平台、跨语言就是为了让每个微服务都有足够的独立性,可以不受技术的钳制。

接口明确原则

  • 由于微服务之间可能存在着调用关系,为了尽量避免以后由于某个微服务的接口变化而导致其它微服务都做调整,在设计之初就要考虑到所有情况,让接口尽量做的更通用,更灵活,从而尽量避免其它模块也做调整。

拆分

对微服务的拆分,从根本上是对业务的拆分,我们可以从以下几个方面来考虑。

  • 限界上下文

​ 限界上下文是在DDD领域驱动设计的方法论中提出的,它认为每个给定的领域都可以包含多个限界上下文,而每个上下文可以分成内部和外部两部分,内部部分是系统内的,不会受其它子域模型的变化而变化,同样自己内部模型的变化也不会影响到其它子域。而外部部分需要参与和其它上下文的通讯。每个上下文都有明确的接口,该接口的定义决定了它会暴露哪些功能给其它上下文。所以我们在定义限界上下文时就是在划分子域边界,而且每个边界内的职责一定是单一的。同时我们在定义上下文的名字的时候一定要在自然语言上保持独立,这个被叫做正交原则。它是为了告诉我们,每个服务子域的定义要清晰独立,不能产生歧义,也不要和其它上下文的名字产生混淆。
​ 限界上下文的划分面向的是业务领域,而不是技术领域.限界上下文的划分同样也不是面向数据模型的,之前说过,微服务和其它分布式服务架构最大的一个区别就是看是否采用了领域驱动设计的理论指导,这个理论的主导思想告诉我们系统模型的建立,不应该采用针对数据CRUD的操作,这被定义为“贫血”模式,它提倡的是针对领域模型驱动的“充血”模式。

  • 数据模型

​ 找到限界上下文,我们划分出了各个独立的服务子域,下一步就可以对数据库进行拆分了,将数据库进行必要的拆分能将复杂数据结构进行分解,可以通过找到缺失领域,共享静态资源,读写分离与不分离等方法进行分解

  • 康威定律

​ 当我们通过上面提到的方法和原则进行服务拆分后,是不是就一定会得到一个可以实施的微服务架构呢?实际上可能还有其它的因素对其进行制约,开发团队的组织结构就是非常重要的一个因素。也就是说微服务的设计要适应于实施它的开发团队的组织结构。这个理论就是康威定律。从软件开发成本角度来看,团队内部成员的沟通成本应该是最低的,所以要把一个独立的系统开发工作交付给一个团队肯定比交付给多个团队更能有利于沟通成本的降低,也最有利于软件交付。限界上下文在划分的时候首先就应该考虑这一点。这是一个团队的多个人负责一个服务的情况,那么从另一个角度想,可不可以由一个人负责多个服务呢,这肯定也是不被建议的,为什么呢?当一个人在开发多个系统时,必然会在测试,部署等环节增加额外的工作量,远没有在一个进程内对系统进行开发方便。如果确实可以拆分出更细粒度的子系统来,建议先通过工程进行拆分,而不是服务,等系统发展起来后,需要加入更多的成员来完成这一个系统时,再拆分服务。所以当一个项目由一个5人的团队开发时,最后划分出10个子服务来肯定是有问题的。

集成

整个系统被拆分成多个独立的子系统后,面临的第一个问题就是如何集成在一起,对外形成一个完整的系统。业内出现了一些成熟的开源的技术框架,比如spring-cloud,dubbo等,都是针对微服务,SOA等面向服务的架构风格的技术实现。但除了这些技术框架,我们还应该掌握哪些集成原则呢?

  • 宽进严出

​ 我们设计的服务可能会作为消费方去调用别人的服务,同时也会作为服务方为别的系统提供服务,但是在一些安全或者参数的规范性校验上,我们却知之甚少,当需要和关联服务交互时,在接口设计上我们应该做到宽进严出,就是说我们对自己要给别人提供的服务严格按照接口规范去输出,尽量不给对方返回没有在接口文档中出现的错误,而对于我们依赖的服务,要做到不信任原则,及要尽量考虑对方接口返回的未知错误,做到最大限度的容错性。

  • 同步还是异步

​ 当面对系统之间的集成时,我们经常会犹豫到底应该采用同步方式,还是异步方式,同步带来的好处就是交互简单,调用端可以在一个线程或进程中就完成对依赖服务的请求和相应,这也是我们在服务集成时最先考虑的方式。但是由于随着系统规模的不断变大,产生的并发请求量也会急剧增加,对系统的响应延时和吞吐量的要求也愈来愈高,所以一些不需要立即获取响应结果的请求完全可以通过异步的方式来处理。不管是同步还是异步都有其存在的道理,我们应该对具体的业务要求进行取舍,不过近年来,一种新的调用机制逐渐被人们应用起来,这就是响应式调用,响应式的调用方式使调用的细节被屏蔽,调用方只需要简单的对调用的结果进行观察,而不用关心调用本身是阻塞的还是非阻塞的,唯一需要做的就是等待结果返回后作出响应就可以了,同时它更棒的地方在于,调用方可以将多个调用组合起来,这样很容易实现了对下游服务并发调用的需求。

  • 编排和协同

​ 当一个复杂的业务流程需要多个服务的配合来完成时,我们该采用怎样的方式来组合这些服务呢,前面提到过,基于SOA的服务架构是一种把各个服务通过编排的方式集成在一起的,如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v74fkRwc-1595745035302)(C:\Users\CR553\AppData\Roaming\Typora\typora-user-images\1595693846892.png)]当用户注册成功后,我们要调用安全中心同步用户信息,还要调用积分中心给新用户增加积分,最后调用消息中心给用户发消息。这种通过编排把各个服务组织在一起的方式导致了用户中心服务承担了太多的责任,它的业务逻辑中耦合了很多无关的业务代码,这是服务中心化的一种体现。我们应该去除它,如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PHp40Ga3-1595745035305)(C:\Users\CR553\AppData\Roaming\Typora\typora-user-images\1595693866188.png)]
                      
这种方式被定义为协同,它是通过消息事件的订阅和发布来减少系统与系统之间的耦合,从根本上消除了中心服务节点。所以在设计非强依赖系统间调用关系时,建议采用协同方式来代替编排。

微服务拆分带来的问题

​ 由于微服务天生是基于分布式系统架构的,所以分布式系统固有的问题它都有,比如数据的一致性、服务的可用性等。另外,由于微服务对系统划分的粒度非常细,本来很多单体的系统被部署到了多个进程中,这给测试、部署、监控等环节所带来的复杂性也是超乎想象的。那因此我们就放弃微服务了吗?当然不会,任何系统架构的设计过程,其实都是在解决系统复杂度的过程。微服务架构的复杂度虽然大,但是并不是不能解决的,下面针对几个常见的问题来分析一下在微服务架构中应该如何应对。

  • 数据的一致性

我们在一个只拥有一个数据库的系统中处理事务是很简单的事情,很多关系型数据对ACID的实现都是非常严的,但是到了微服务架构的环境中,保持事务的完整性似乎变的不可能,由于网络传输的不可靠性(虽然这种情况出现的概率很小),被分散在多个进程中的系统在共同完成一个写操作时就会可能出现维护自己的数据状态时不能保持一致性的问题,比如不能够同时提交本地事务,或者不能够同时回滚。

对于这个问题,我们应该怎么做呢?

​ 首先要有重试机制,及当对一个子服务的写操作请求失败后,可以重试几次,直到系统的响应成功为止,这就要求每个有写操作的子服务需要支持幂等,因为有可能上一次已经写成功了,只是由于网络问题,没有正常返回结果。由于许多时候网络问题不是瞬间的,可能会持续一段时间,那么我们就一直重试下去吗?

​ 肯定也不会,我们会采用补偿机制来修复事务的一致性,比如库存系统在扣减成功后,需要在订单系统上修改客户订单状态,但是尝试多次后,订单系统一直响应失败,那怎么办呢,可以给库存系统发一个增加库存的请求,算是补偿。这样整个系统在一定时间段内还是保证了数据是一致的状态。
​ 最后可以使用柔性事务(TCC),柔性事务这个词最早是由支付宝的团队提出的,它的核心思想是要求在涉及写操作的业务中支持一个软状态,怎么理解这个“软状态”呢,就是不是一个确定的状态,比如正在处理中的订单。举个例子,系统在从A状态到达B状态时必须要先经过C(软状态),而C不是一个实际的业务状态,这样做不但可以起到资源检查并预占的作用,同时还可以做为回退到A还是前进到B的中间状态节点。

  • 服务的容错性

在微服务架构中,肯定会有一个系统依赖其它系统来完成一次操作的情况,那么当依赖的下游系统宕机或者由于网络问题导致服务长时间不能响应的时候怎么办,上游系统不可能一直重试吧。这时我们需要采用熔断保护措施才能保证上游系统不被下游系统拖死,具体我们应该怎么做呢?

​ 超时,首先我们对任何服务的调用都应该有超时机制,当长时间没有应答时就要认为调用失败并终止等待了。
​ 隔离,即便有超时机制,系统也可能会因为超时时间过长,而处于“漫长”的等待中,更可怕的是当某个下游服务的整个集群全挂了的时候,上游服务不应该被这一个服务拖死。我们应该对资源进行合理分配,把调用下游接口的资源进行隔离,其实有很多时候只是一个不影响主业务流程的下游服务挂了,这不应该成为我们整个服务不能访问的原因,我们可以采用为每个对下游资源的调用分配最大个数的线程池或者连接池来解决这个问题。
​ 断路保护,在互联网的场景中,高并发、高吞吐的请求是非常普遍的要求,这种情况下,即便我们做了超时机制和资源隔离,也会由于大量的请求使我们的系统处于不必要的繁忙状态,我们应该对那些一直出错误的响应进行处理,把已经尝试过多次的失败请求进行累计,当达到一定值的时候,忽略对它的调用。我们之后定时去监控,看看它恢复了没有就可以了。
​ 服务降级,当系统出现断路的时候除了不再访问下游资源,还需要做些什么呢?总不能给用户返回一个下游服务有异常的错误,通常情况下我们会通过缓存或者静态资源来给用户返回一些非实时的数据,让用户无感知,这就是服务降级。

  • 系统的性能

在微服务环境中,当用户对系统发起一个请求后,最上游的服务要经过多次网络传输、多次请求/应答数据解析才能完成一个整体的请求交互,所以必将带来更多的资源开销和更大的访问延时,我们应该如何应对呢?

​ 首先,可以考虑使用RPC进行远程通讯,虽然目前基于restful的http请求很热,它所带来的简单性和规范性是一般RPC框架不具备的,但是不得不承认,基于二进制传输协议的RPC通讯框架在性能上的优势是http协议很难达到的。所以在一些对性能要求比较苛刻的系统中,优先考虑RPC。
​ 其次,增加缓存使用,缓存虽然不是分布式系统架构中的银弹,但是它无处不在,它的好处在这里我们就不深入讨论了。微服务系统性能瓶颈归根到底还是多次网络请求,解决它最好的办法就是减少调用,我们尽量把每次对下游系统的请求进行缓存,虽然有时这确实是一厢情愿,但在设计微服务系统时,请你首先考虑使用它。
​ 最后,我们说说扩展,前面聊了几点其实也只是尽量在缩小和单体系统之间的差距而已,并没有从根本上解决性能瓶颈。而对于系统扩展性,是微服务系统与生俱来就有的,通过扩展我们可以减少单个服务的复杂性,使某个服务的请求所要处理的业务逻辑简单很多,最常见的情况是数据库的结构简单了,之前需要各种关联的查询没有了,因为我们每个服务只负责自己的那几张表。这有什么好处呢,首先是垂直扩展简单了,系统的关联性减弱后,我们可以很容易的对系统进行拆分,使之前许多复杂的多表查询变成了简单的单表查询,从而使sql优化这些让我们经常头疼的东西减少了,更重要的是单表查询为我们带来的一个更大的好处就是使数据库的水平扩展也变得十分容易。所以在微服务架构的环境中,我们要始终考虑如何用多个简单的业务逻辑来代替一个复杂的业务逻辑,因为这样更容易实现数据库在水平和垂直方向上的扩展。

  • 实施复杂

当系统被拆分成多个单独的服务时,无论在部署、测试还是监控环节,都会产生大大超出单个系统的工作量,这在做集成测试的时候会尤为突出。小而多的应用服务必然需要更多的部署节点,应对这样的问题,需要我们必须接受自动化文化,自动化部署和自动化测试方案必须要在微服务实施开始前就规划好。关于自动化部署和测试的方案有很多,而且大多数都已经很成熟。

微服务应该关注的问题

​ 单个微服务代码量小,易修改和维护。但是,系统复杂度的总量是不变的,每个服务代码少了,但服务的个数肯定就多了。就跟拼图游戏一样,切的越碎,越难拼出整幅图。一个系统被拆分成零碎的微服务,最后要集成为一个完整的系统,其复杂度肯定比大块的功能集成要高很多。
​ 单个微服务数据独立,可独立部署和运行。虽然微服务本身是可以独立部署和运行的,但仍然避免不了业务上的你来我往,这就涉及到要对外通信,当微服务的数量达到一定量级的时候,如何提供一个高效的集群通信机制成为一个问题。
​ 单个微服务拥有自己的进程,进程本身就可以动态的启停,为无缝升级打好了基础,但谁来启动和停止进程,什么时机,选择在哪台设备上做这件事情才是无缝升级的关键。这个能力并不是微服务本身提供的,而是需要背后强大的版本管理和部署能力。
​ 多个相同的微服务可以做负载均衡,提高性能和可靠性。正是因为相同微服务可以有多个不同实例,让服务按需动态伸缩成为可能,在高峰期可以启动更多的相同的微服务实例为更多用户服务,以此提高响应速度。同时这种机制也提供了高可靠性,在某个微服务故障后,其他相同的微服务可以接替其工作,对外表现为某个设备故障后业务不中断。同样的道理,微服务本身是不会去关心系统负载的,那么什么时候应该启动更多的微服务,多个微服务的流量应该如何调度和分发,这背后也有一套复杂的负载监控和均衡的系统在起作用。
​ 微服务可以独立部署和对外提供服务,微服务的业务上线和下线是动态的,当一个新的微服务上线时,用户是如何访问到这种新的服务?这就需要有一个统一的入口,新的服务可以动态的注册到这个入口上,用户每次访问时可以从这个入口拿到系统所有服务的访问地址。这个统一的系统入口并不是微服务本身的一部分,所以这种能力需要系统单独提供。
​ 还有一些企业级关注的系统问题,比如,安全策略如何集中管理?系统故障如何快速审计和跟踪到具体服务?整个系统状态如何监控?服务之间的依赖关系如何管理?等等这些问题都不是单个微服务考虑的范畴,而需要有一个系统性的考虑和设计,让每个微服务都能够按照系统性的要求和约束提供对应的安全性,可靠性,可维护性的能力。

一个完整的微服务系统,它最少要包含以下功能:

  • 日志和审计,主要是日志的汇总,分类和查询
  • 监控和告警,主要是监控每个服务的状态,必要时产生告警
  • 消息总线,轻量级的MQ或HTTP
  • 注册发现
  • 负载均衡
  • 部署和升级
  • 事件调度机制

以下功能不是最小集的一部分,但也应该在选择时进行考虑:

  • 认证和鉴权
  • 多语言支持, 是否支持多种编程语言
  • 统一服务构建和打包
  • 统一服务测试
  • 统一配置文件管理
  • 服务依赖关系管理
  • 问题跟踪调试框架
  • 灰度发布
  • 蓝绿部署
  • 资源管理,如:底层的容器, 虚拟机, 物理机和网络管理

微服务开发框架

微服务框架可以分为侵入式非侵入式两种,什么是侵入式和非侵入式呢?可以以微服务框架Spring Cloud来进行说明,在微服务框架中使用Eruka Server作为服务注册中心,在微服务单元上配置使用Eureka Client向注册中心进行注册,这样就会带来一个问题,在旧代码或者非JAVA代码(比如Python)中使用Spring Cloud微服务框架,这样就需要对旧代码及非JAVA代码进行微服务化的改造。Spring Cloud是侵入式的微服务框架,侵入式微服务架构还存在Dubbo框架。
什么是非侵入式的微服务框架呢,还是以微服务框架中微服务的注册来进行说明,比如将服务注册和服务调用从现有服务中抽离出来,形成一个服务代理。该服务代理也叫做Sidecar,负责找到目的服务并负责通讯的可靠性和安全等问题。当服务大量部署时,随着服务部署的Sidecar代理之间的链接形成了一个如下图所示的网格,该网格成为微服务的通讯基础设施层,承载微服务之间的所有流量,被称为Service Mesh(服务网格)。非侵入式的微服务框架的比较有代表性的方案有Istio和Conduit。

Spring Cloud

Spring Cloud作为一个微服务的开发框架,包括了很多的组件,其中包括Spring Cloud Netflix(Eureka、Hystrix、Zuul、Archaius)、Spring Cloud Config、Spring Cloud Bus、Spring Cloud Cluster、Spring Cloud Consul、Spring Cloud Security、Spring Cloud Sleuth、Spring Cloud Data Flow、Spring Cloud Stream、Spring Cloud Task、Spring Cloud Zookeeper、Spring Cloud Connectors、Spring Cloud Starters、Spring Cloud CLI等。

另外Spring Boot为Spring Cloud提供一个简化基于Spring的开发环境,可以适应Spring Boot快速开发单个微服务。

Dubbo

Dubbo是一个阿里巴巴开源出来的一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。其核心部分包含:

远程通讯:提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
自动发现:基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。

Spring Cloud VS Dubbo

一个关于Spring Cloud和Dubbo很有意思的比喻,使用Dubbo构建的微服务架构就像组装电脑,各个环节的可选自由度很高,但是最终结果很有可能因为一条内存质量不行就点不亮了,但是如果是一个高手,这一切都不存在问题。Spring Cloud就像品牌机,在Spring Source的整合下,做了大量兼容性的测试,保证了机器拥有更高的稳定性,但是如果要在使用非原装组件外配件时,需要对配件足够的了解。

Istio

Istio是一个用来连接、管理和保护微服务的开放平台。Istio提供一种简单的方式来建立已部署服务网络,具备负载均衡、服务间认证、监控等功能,而不需要改动任何服务代码。想要为服务增加Istio的支持,只需要在环境中部署一个特殊的边车(sidecar),使用Istio控制面板功能配置和管理代理,拦截微服务之间的所有网络通信。
Istio目前仅支持在Kubernetes上的服务部署,但未来版本中将支持其他环境。

Conduit

Conduit是为Kubernetes设计的一个超轻型服务网格服务,它可透明地管理在Kubernetes上运行的服务的运行时通信,使得它们更安全可靠。Conduit提供了可见性、可靠性和安全性的功能,而无需更改代码。
Conduit service mesh也是由数据面板和控制面板组成。数据面板承载应用实际的网络流量。控制面板驱动数据面板,并对外提供北向接口。

参考资料

两个披萨原则(The two pizza principle)

两个披萨原则最早是由亚马逊CEO贝索斯提出的,他认为如果两个披萨不足以喂饱一个项目团队,那么这个团队可能就显得太大了。

因为人数过多的项目会议将不利于决策的形成,而让一个小团队在一起做项目、开会讨论,则更有利于达成共识,并能够有效促进企业内部的创新。

​ 亚马逊内部有所谓的“两个披萨团队”,指的是团队的人数相当于可以吃掉2个披萨,这种组织理论非常知名。

https://wiki.mbalib.com/wiki/%E4%B8%A4%E4%B8%AA%E6%8A%AB%E8%90%A8%E5%8E%9F%E5%88%99

devops(开发运维一体化)

https://baike.baidu.com/item/devops/2613029

CI/CD(持续集成/持续交付)

参考CSDN: 敏捷开发、持续集成/交付(CI/CD)、DevOps学习笔记

https://blog.csdn.net/CrankZ/article/details/81545439

DDD(领域驱动架构)

参考知乎: 领域驱动架构(DDD)建模中的模型到底是什么?

https://www.zhihu.com/question/25089273

CSDN: 谈谈我对微服务的理解

https://blog.csdn.net/disdouble/article/details/83271917

博客园: 一文详解微服务架构

https://www.cnblogs.com/skabyy/p/11396571.html

CSDN: 微服务概念及优缺点

https://blog.csdn.net/kunyus/article/details/90670710

CSDN: SOA架构和微服务架构的区别

https://blog.csdn.net/zpoison/article/details/80729052

CSDN: 微服务框架的介绍

https://blog.csdn.net/polo2044/article/details/95319059

博客园: 一文详解微服务架构

https://www.cnblogs.com/skabyy/p/11396571.html

博客园: 一文详解微服务架构

https://www.cnblogs.com/skabyy/p/11396571.html

CSDN: 微服务概念及优缺点

https://blog.csdn.net/kunyus/article/details/90670710

CSDN: SOA架构和微服务架构的区别

https://blog.csdn.net/zpoison/article/details/80729052

CSDN: 微服务框架的介绍

https://blog.csdn.net/polo2044/article/details/95319059

博客园: 一文详解微服务架构

https://www.cnblogs.com/skabyy/p/11396571.html

猜你喜欢

转载自blog.csdn.net/weixin_44273948/article/details/107593280