导图社区 微服务架构
微服务架构的思维导图,介绍了微服务是什么、微服务的坑、微服务最佳实践(方法篇)、微服务最佳实践(基础设施篇),微服务架构是一种将应用程序构建为一组小型、独立服务的方法。
编辑于2023-05-27 10:38:25 湖南微服务架构
微服务是什么
经典定义
In short, the microservice architectural style is an approach to developing a<br>single apliation as a suite of small services, each running in its own process<br>and communicating with lightweight mechanisms, often an HTTP resource API.<br>These services are buit around business capabilities and independently<br>deployable by fully automated deployment machinery.
关键词: small lightweight. automated, 基本上浓缩了微服务的精华
微服务与SOA的关系
微服务是一种和SOA相识,但本质上不同的架构理念<br><br>
相似点在于下图中交叉的地方,就是两者都关注"服务"<br>都是通过服务的拆分来解决可扩屏性问题
本质上不同的地方在于几个核心理念的差异:是有<br>ESB、服务的粒度、架构设计的目标等。
SOA与务对比图
微服务和SOA的对比
服务粒度
整理上来说,SOA的服务粒度要粗一些,而微服务的服务要细一些。
例如,对一个大型企业来说,”员工管理系统"就是一个SOA架构中服务,而如果<br>采用微服务,则”员工管理系统“会被拆分更多的服务,比如”员工信息管理“、”员工考勤管理“、<br>"员工假期管理"和"员工福利管理"等更多服务。
服务通信
SOA采用了ESB作为服务间通信关键组件,负责服务定义、服务路由、消息转换、消息传递总体上是重量级的实现
微服务推荐使用统一的协议和格式, 例如,RESTful 协议、RPC 协议,无须ESB这样的重量级实现
服务交付
SOA对服务的交付并没有待殊要求,因为SOA更多考虑的是兼容已有的系统
微服务的架构理念要求“快速交付”,相应地要求采取自动<br>化测试、持续集成、自动化部署等敏捷开发相关的最佳实践<br>
如果没有这些基础能力支撑,微服务规模一旦变大(例如,超过20个微服务),整体<br>就难以达到快速交付的要求,这也是很多企业在实行微服务时踩过的一个明显的坑, 就<br>是系统拆分为微服务后,部署的成本呈指数上升<br><br>
应用场景
SOA更加适合于庞大、复杂、异构的企业级系统,这也是SOA诞生的背景。这类系统<br>的典型特征就是很多系统已经发展多年,采用不同的企业级技术,有的是内部开发的,<br>有的是外部购买的,无法完全推倒重来或者进行大规模的优化和重构。因为成本和影响<br>太大,只能采用兼容的方式进行处理,而承担兼容任务的就是ESB<br>
微服务更加适合于快速、轻量级、基于Web的互联网系统,这类系统业务变化快,需要<br>快速尝试、快速交付;同时基本都是基于Web,虽然开发技术可能差异很大(例如,<br>Java、 C++、.NET等),但对外接口基本都是提供HTTP RESTful风格的接口,无须考<br>虑在接口层进行类似SOA的ESB那样的处理<br>
微服务不见得不SOA更优秀
SOA和微服务是两种不同理念的架构模式,并不存在孰优孰劣,只是应用场景不同而<br>已。我们介绍SOA时候提到其产生历史背景是因为企业的IT服务系统庞大而又复杂,<br>改造成本很高,但业务上又要求其互通,因此才会提出SOA这种解决方案。如果我们<br>将微服务的架构模式生搬硬套到企业级IT服务系统中,这些IT服务系统的改造成本可<br>能远远超出实施SOA的成本
主要看应用场景,不见得微服务比SOA要优秀
微服务的坑
服务划分过细,服务间关系复杂
服务划分过细,单个服务的复杂度确实下降了,但整个系统的复杂度却上升了,因为微<br>服务将系统内的复杂度转移为系统间的复杂度了。
从理论的角度来计算,n个服务的复杂度是nx(n-1)/2,整体系统的复杂度是随着微服<br>务数量的增加呈指数级增加的。图中形象了说明了整体复杂度:粗粒度划分服务时,系<br>统被划分为3个服务,虽然单个服务较大,但服务间的关系很简单:细粒度划分服务<br>时,虽然单个服务小了-些,但服务间的关系却复杂了很多。
服务数量太多,团队效率急剧下降
开发工程师要设计多个接口,打开多个工程,调试时要部署多个程序,提测时打多个包
测试工程师要部署多个环境,准备多个微服务的数据,测试多个接口
运维工程师每次上线都要操作多个微服务,并且微服务之间可能还有依赖关系
调用链太长,性能下降
由于微服务之间都是通过HTTP或者RPC调用的,每次调用必须经过网络。一 般线上的<br>业务接口之间的调用,平均响应时间大约为50毫秒,如果用户的一起请求需要经过6<br>次微服务调用,则性能消耗就是300毫秒,这在很多高性能业务场景下是难以满足需求<br>的。为了支撑业务请求,可能需要大幅增加硬件,这就导致了硬件成本的大幅上升。
调用链太长,问题定位困难
Service C的数据库出现慢查询,导致Service C给Service B的响应错误,Service B<br>给Service A的响应错误,Service A给用户的响应错误。我们在实际定位时是不会有<br>样例图中这么清晰的,最开始是用户报错,这时我们首先会去查ServiceA。导致<br>Service A故障的原因有很多,我们可能要花半个小时甚至1个小时才能发现是<br>Service B返回错误导致的。于是我们又去查Service B,这相当于重复Service A故障<br>定位的步骤...如此循环下去,最后可能花费了几个小时才能定位到是ServiceC的数<br>据库慢查询导致了错误。
没有自动化支撑,无法快速交付
没有【自动化测试】支撑,每次测试时需要测试大量接口
没有【自动化部署】支撑,运维人员献shel命令逐台部。理部众部弄6-7个服务.几十台机器,手都要敲麻
没有【自动化监控】。每次故障定位都需要人工查几十台机器<br>几百个微服务的各种状态和各种日志文件
没有服务治理,微服务数虽多了后管理混乱
【服务路由】假设某个微服务有60个节点,部署在20台机器上,那么其他依赖的微<br>服务如何知道这个部署情况呢?
【服务故障隔离】假设上述例子中的60个节点有5个节点发生故障了,依赖的微服务<br>如何处理这种情况呢?
【服务注册和发现】同样是上述的例子,现在我们决定从60个节点扩容到80个节<br>或者将60个节点缩减为40个节点,新增或者减少的节点如何让依赖的服务知道<br>呢?
微服务最佳实践(方法篇)
确认服务粒度:“三个火枪手” 原则
【“三个火枪手”原则】即一个微服务三个人负责开发。当我们在实施微服务架构时,<br>根据团队规模来划分微服务数量,如果业务规继续发展,团队规模扩大,我们再将已有<br>的微服务进行拆分(就是保证三个开发人员对一个微服务,微服务数量=团队人数/3,拆<br>分粒度是变化的)
例如,团队最初有6个人,那么可以划分为2个微服务,随着业务的发展,业务功能越<br>来越多,逻辑越来越复杂,团队扩展到12个人,那么我们可以将已有的2个微服务进<br>行拆分,变成4个微服务。
"三个火枪手"的原则主要应用于微服务设计和开发阶段,如果微服务经过一段时间发<br>展后已经比较稳定,处于维护期了,无须太多的开发,那么平均1个人维护1个微服务<br>甚至几个微服务都可以。当然考虑到人员备份问题,每个微服务最好都安排2个人维<br>护,每个人都可以维护多个微服务。
拆分方法
基于业务逻辑拆分
这是最常见的一种拆分方式,将系统中的业务模块按照职责范围识别出来,每个单独的<br>业务模块拆分为一个独 立的服务。
实践中经常对拆分粒度出现理解差异
基于业务逻辑拆分虽然看起来很直观,但在实践过程中最常见的一个问题就是团队成员<br>对于“职责范围”的理解差异很大,经常会出现争论,难以达成一致意见。例如:假设<br>我们做一个电商系统,第一种方式是将服务划分为“商品”、"交易"、“用户” 3个服务,<br>第二种方式是划分为“商品"、“订单“、“支付”、”发货“、“买家 、“卖家”6个服务,<br>哪种方式更合理,是不是划分越细越正确?
根据“三个火枪手”原则来拆分业务
导致这种困惑的主要根因在于从业务的角度来拆分的话,规模粗和规模细都没有问题,<br>因为拆分基础都是业务逻辑,要判断拆分粒度,不能从业务逻辑角度,而要根据前面介<br>绍的“三个火枪手"的原则,计算- -下大概的服务数量范围,然后再确定合适的“职责<br>范围”。否则就可能出现划分过粗或者过细的情况,而且大部分情况下会出现过细的情况。
例如:如果团队规模是10个人支撑业务,按照“三个火枪手”规则计算,大约需要划<br>分为4个服务,那么”登录、注册、用户信息管理”都可以划到”用户服务”职责范围<br>内;如果团队规模是100人支撑业务,服务数量可以达到40个,那么“用户登录”就<br>是一个服务了:如果团队规模达到1000人支撑业务,那“用户连接管理”可能就是一<br>个独立的服务了。
基于可扩展拆分
将系统中的业务模块按照稳定性排序,将已经成熟和改动不大的服务拆分为稳定服务,<br>将经常变化和迭代的服务拆分为变动服务。稳定的服务粒度可以粗-一些,即使逻辑上没<br>有强关联的服务,也可以放在同一个子系统中。这样拆分主要是为了提升项目快速迭代<br>的效率,避免在开发的时候,不小心影响了已有的成熟功能导致线上问题。
例如将“日志服务”和“升级服务”放在同一个子系统中;不稳定的服务粒度可以细一<br>些,但也不要太细,始终记住要控制服务的总数量
基于可靠性拆分(基于核心与否拆分)
将系统中的业务模块按照优先级排序,将可靠性要求高的核心服务和可靠性要求低的非<br>核心服务拆分开来,然后重点保证核心服务的高可用。具体拆分的时候,核心服务可以<br>是一个也可以是多个,只要最终的服务数量满足“三个火枪手”的原则就可以。
拆出核心业务的好处
避兔非核心服务故障影响核心服务
例如,日志上报一般都属于非核心服务,但是在某些场景下可能有大量的日志上报,如<br>果系统没有拆分,那么日志上报可能导致核心服务故障;拆分后即使日志上报有问题,<br>也不会影响核心服务
核心服务高可用方案可以更简单
核心服务的功能逻辑更加简单,存储的数据可能更少,用到的组件也会更少,设计高可<br>用方案大部分情况下要比不拆分简单很多
能够降低高可用成本
将核心服务拆分出来后,核心服务占用的机器、带宽等资源比不拆分要少很多。因此,<br>只针对核心服务做高可用方案,机器、带宽等成本比不拆分要节省较多。
基于性能拆分
将性能要求高或者性能压力大的模块拆分出来,避免性能压力大的服务影响其他服务
常见的拆分方式和具体的性能瓶颈有关,可以拆分Web服务、数据库、缓存等, 将容<br>易遇到性能瓶颈的拆出来
例如电商的抢购,性能压力最大的是入的排队功能,可以将排队功能独立为一个服务
几种拆分方法混合使用
以上几种拆分方式不是多选一。而是可以根据实际情况自由排列组合,完全根据业务需求
例如可以基于可靠性拆分出服务A,基于性能拆分出服务B,基于可扩展拆分出C/D/F<br>三个服务,加上原有的服务X,最后总共拆分出6个服务(A/B/C/D/F/X)
微服务最佳实践(基础设施篇)
基础设施很重要
大部分人主要关注的是微服务的"small" 和"lightweight" 特性,但实际上真正决定<br>微服务成败的,恰恰是那个被大部分人都忽略的"automated" 。为何这样说呢?因为<br>服务粒度即使划分不合理,实际落地后如果团队遇到麻烦,自然会想到拆服务或者合服<br>务;如果“automated"相关的基础设施不健全,那微服务就是焦油坑,让研发、测<br>试、运维陷入我上一期讲的各种微服务陷阱中
基础设施没到位,微服务就是“焦油坑”
小公司也可实施微服务
第一个原因是已经有开源的微服务基础设施全家桶了,例如大名鼎鼎的Spring Cloud<br>项目,涵盖了服务发现、服务路由、网关、配置中心等功能
第二个原因是如果微服务的数量并不是很多的话,并不是每个基础设施都是必须的
基础设施可逐步搭建
1 服务发现、服务路由、服务容错
这是最基本的微服务基础设施
2 接口框架、API网关
主要是为了提升开发效率,接口框架是提升内部服务的 开发效率,API网关是为了提升与外部服务对接的效率
3 自动化部署、 自动化测试配置中心
主要是为了提升测试和运维效率
4 服务监控、服务跟踪和服务安全
主要是为了进一步提升运维效率
基础设施
自动化测试
微服务将原本大-统的系统拆分为多个独立运行的“微”服务,微服务之间的接口数量<br>大大增加,并且微服务提倡快速交付,版本周期短,版本更新频繁。如果每次更新都靠<br>人工回归整个系统,则工作量大,效率低下,达不到"快速交付”的目的,因此必须通<br>过自动化测试系统来完成绝大部分测试回归的工作。
自动化测试涵盖的范围包括代码级的单元测试、单个系统级的集成测试、系统间的接口<br>测试,理想情况是每类测试都自动化。如果因为团队规模和人力的原因无法全面覆盖,<br>至少要做到接口测试自动化。(保障每个接口是OK的)
至少做到自动完成API接口测试
自动化部署
相比大一统的系统,微服务需要部署的节点增加了几倍甚至十几倍,微服务部署的频率<br>也会大幅提升(例如,我们的业务系统70%的工作日都有部署操作) , 综合计算下<br>来,微服务部署的次数是大一统系统部署次数的几十倍。这么大量的部署操作,如果继<br>续采用人工手工处理,需要投入大量的人力,且容易出错,因此需要自动化部署的系统<br>来完成部署操作。
自动化部属包含哪些方面?
版本管理
资源管理
机器管理
虚拟机管理等
部署操作
回退操作
配置中心
微服务的节点数量非常多,通过人工登录每台机器手工修改,效率低,容易出错。特别<br>是在部署或者排障时,需要快速增删改查配置,人I操作的方式显然是不行的
除此以外,有的运行期配置需要动态修改并且所有节点即时生效,人工操作是无法做到<br>的。综合上面的分析,微服务需要一个统一 的配置中心来管理所有微服务节点的配置。
配置中心包含哪些方面?
配置版本管理
例如,同样的微服务,有10个节点是给移动用户服务的,有20个节点给联通用户服<br>务的,配置项都- -样,配置值不一样
增删改查配置
节点管理
配置同步
配置推送等
接口框架
微服务提倡轻量级的通信方式,一般采用HTTP/REST或者RPC方式统-接口协议。但<br>在实践过程中,光统一接口协议还不够,还需要统一接口传递的数据格式。
统一接口框架
统一接口协议
HTTP/REST
RPC
统一数据格式
JSON/XML
JSON/XML数据规范(大小写,固定字段等)
例子
API网关
系统拆分为微服务后,内部的微服务之间是互联互通的,相互之间的访问都是点对点<br>的。如果外部系统想调用系统的某个功能,也采取点对点的方式,则外部系统会非<br>常”头大”。因为在外部系统看来,它不需要也没办法理解这么多微服务的职责分工和<br>边界,它只会关注它需要的能力,而不会关注这个能力应该由哪个微服务提供。
除此以外,外部系统访问系统还涉及安全和权限相关的限制,如果外部系统直接访问某<br>个微服务,则意味着每个微服务都要自己实现安全和权限的功能,这样做不但工作量<br>大,而且都是重复工作。综合上面的分析,微服务需要一个统- 的API网关,负责外部<br>系统的访问操作。
API网关是外部系统访问的接口,所有的外部系统接入系统都需要通过API网关,主要<br>包括接入鉴权(是否允许接入)、权限控制 (可以访问哪些功能)、传输加密、 请求路<br>由、流量控制等功能。
服务发现
为啥需要服务发现?
微服务种类和数量很多,如果这些信息全部通过手工配置的方式写入各个微服务节点,<br>首先配置工作量很大,配置文件可能要配几百上千行,几十个节点加起来后配置项就是<br>几万几十万行了,人工维护这么大数量的配置项是一项灾难
其次是微服务节点经常变化,可能是由于扩容导致节点增加口,也可能是故障处理时隔离<br>掉一部分节点, 还可能是采用灰度升级,先将一部分节点升级到新版本,然后让新老版<br>本同时运行。不管哪种情况,我们都希望节点的变化能够及时同步到所有其他依赖的微<br>服务。如果采用手工配置,是不可能做到实时更改生效的。因此,需要-套服务发现的<br>系统来支撑微服务的自动注册和发现。
需要-套服务发现的系统来支撑微服务的自动注册和发现
服务发现的两种实现方式
自理式
自理式结构就是指每个微服务自己完成服务发现(微服务依赖/调用别的微服务时自己去<br>服务注册中心找)
架构:例如,图中SERVICE INSTANCE A访问SERVICE REGISTRY获取服务注册信<br>息,然后直接访问SERVICE INSTANCE B
实现简单,压力分散
自理式服务发现实现比较简单,因为这部分的功能一般通过统一 的程序库或者程序包提<br>供给各个微服务调用,而不会每个微服务都自己来重复实现-遍
并且由于每个微服务都承担了服务发现的功能,访问压力分散到了各个微服务节点,性<br>能和可用性上不存在明显的压力和风险
代理式
代理式结构就是指微服务之间有一个负载均衡系统(图中的LOAD BALANCER节点)<br>由负载均衡系统来完成微服务之间的服务发现
架构图
风险挺大
第一个风险是可用性风险,- -旦LOAD BALANCER系统故障,就会影响所有微服务之间的调用
第二个风险是性能风险,所有的微服务之间的调用流量都要经过LOAD BALANCER系<br>统,性能压力会随着微服务数量和流量增加而不断增加,最后成为性能瓶颈。因此<br>LOAD BAL ANCER系统需要设计成集群的模式,但LOAD BALANCER集群的实现本<br>身又增加了复杂性
核心是注册表
不管是自理式还是代理式,服务发现的核心功能就是服务注册表,注册表记录了所有的<br>服务节点的配置和状态,每个微服务启动后都需要将自己的信息注册到服务注册表,然<br>后由微服务或者LOAD BALANCER系统到服务注册表查询可用服务。
微服务启动后把自己的信息注册到服务注册表是前提,后续有别的服务依赖/调用它才有<br>根有据。而别的服务调用微服务时,怎么去注册中心”找”。自己去找为自理式,统-<br>别人给你找为代理式。而且找到后也可能是多个。
服务路由
有了服务发现后,微服务之间能够方便地获取相关配置信息,但具体进行某次调用请求<br>时,我们还需要从所有符合条件的可用微服务节点中挑选出一个具体的节点发起请求,<br>这就是服务路由需要完成的功能。
服务发现找到多个可用节点,服务路由选取一个完成请求
服务路由通常和服务发现放在一起实现
对于自理式服务发现,服务路由是微服务内部实现的
对于代理式服务发现,服务路由是由LOAD BAL ANCER系统实现的
核心的功能就路由算法
随机路由
轮询路由
最小压力路由
最小连接数路由
服务容错
系统拆分为微服务后,单个微服务故障的概率变小,故障影响范围也减少,但是微服务<br>的节点数量大大增加。从整体上来看,系统中某个微服务出故障的概率会大大增加。如<br>果不及时处理故障,故障扩散开来就会导致看起来系统中很多服务节点都故障了,因此<br>需要微服务能够自动应对这种出错场景,及时进行处理。否则,如果节点一故障就需要<br>人工处理,投入人力大,处理速度慢;而一且处理速度慢,则故障就很快扩散,所以我<br>们需要服务容错的能力。
常见的服务容错包括请求重试、流控和服务隔离。通常情况下,服务容错会集成在服务<br>发现和服务路由系统中。
服务监控
系统拆分为微服务后,节点数量大大增加,导致需要监控的机器、网络、进程、接口调<br>用数等监控对象的数量大大增加 <br>
同时,-旦发生故障,我们需要快速根据各类信息来定位故障。这两个目标如果靠人力<br>去完成是不现实的
举个简单例子:我们收到用户投诉说业务有问题,如果此时采取人工的方式去搜集、分<br>析信息,可能把几十个节点的日志打开-遍就需要十几分钟了,因此需要服务监控系统<br>来完成微服务节点的监控。
主要作用
实时搜集信息并进行分析,避免故障后再来分析.减少了处理时间
服务监控可以在实时分析的基础上进行预警,在问题萌芽的阶段发觉并预警,降低了问!<br>题影响的范围和时间 <br>
通常情况下,服务监控需要搜集并分析大量的数据,因此建议做成独立的系统,而不要<br>集成到服务发现、API 网关等系统中
服务跟踪
服务监控可以做到微服务节点级的监控和信息收集,但如果我们需要跟踪某一个请求在<br>微服务中的完整路径,服务监控是难以实现的。因为如果每个服务的完整请求链信息都<br>实时发送给服务监控系统,数据量会大到无法处理。
服务监控和服务跟踪的区别可以简单概括为宏观和微观的区别
例如,A服务通过HTTP协议请求B服务10次,B通过HTTP返回JSON对象,服务<br>监控会记录请求次数、响应时间平均值、响应时间最高值、错误码分布这些信息:而服<br>务跟踪会记录其中某次请求的发起时间、响应时间、响应错误码、请求参数、返回的<br>JSON对象等信息。
服务安全
系统拆分为微服务后,数据分散在各个微服务节点上。从系统连接的角度来说,任意微<br>服务都可以访问所有其他微服务节点:但从业务的角度来说,部分敏感数据或者操作,<br>只能部分微服务可以访问,而不是所有的微服务都可以访问,因此需要设计服务安全机<br>制来保证业务和数据的安全性
服务安全三部分
接入安全
数据安全
传输安全
在配置中心实现
通常情况下,服务安全可以集成到配置中心系统中进行实现,即配置中心配置微服务的<br>接入安全策略和数据安全策略,微服务节点从配置中心获取这些配置信息,然后在处理<br>具体的微服务调用请求时根据安全策略进行处理。由于这些策略是通用的,一般会把策<br>略封装成通用的库提供给各个微服务调用。
实现架构
B从配置中心获取安全策略,然后对A的请求做出必要的限制调用安全策略库),总之要<br>实现的目的是,哪些微服务让其访问,哪些不让其访问。