1 基础知识篇
1、什么是微服务架构?
微服务架构是一种架构模式或者说是架构风格,它提倡将单一应用程序划分成一组小的服务。每个服务运行在其独立的自己的
进程中服务之间相互配合、相互协调,为用户提供最终价值。服务之间采用轻量级通信。每个服务都围绕具体业务进行构建,
并能够独立部署到生产环境等。
2、微服务的优缺点是什么?
优点:松耦合,聚焦单一业务功能,无关开发语言,团队规模降低。在开发中,不需要了解多于业务,只专注于当前功能,便
利集中,功能小而精。微服务一个功能受损,对其他功能影响并不是太大,可以快速定位问题。微服务只专注于当前业务逻辑
代码,不会和 html、css 或其他界面进行混合。可以灵活搭配技术,独立性比较好。每个微服务都有自己独立的数据库,
数据库的表复杂度降低
缺点:随着服务数量增加,管理复杂,部署复杂,服务器需要增多,服务通信和调用压力增大,运维工程师压力增大,人力资
源增多,系统依赖增强,数据一致性,性能监控。
3、什么是Spring Cloud?
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务
发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring
Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发
工具包。
4、Spring Boot和Spring Cloud之间关系?
Spring Boot:专注于快速方便的开发单个个体微服务(关注微观)
Spring Cloud:关注全局的微服务协调治理框架,将Spring Boot开发的一个个单体微服务组合并管理起来(关注宏观)
Spring Boot可以离开Spring Cloud独立使用,但是Spring Cloud不可以离开Spring Boot,属于依赖关系。
5、Spring Cloud和 Dubbo有哪些区别?(高频)
相同点:它们都是分布式管理框架。
区别:
1、dubbo使用的是RPC通讯,占用带宽会少一点。Spring Cloud使用的是HTTP的Rest方式进行通讯,带宽会多一点,同时
使用http协议一般会使用JSON报文,消耗会更大。
2、dubbo 开发难度较大,所依赖的jar包有很多问题大型工程无法解决。Spring Cloud 对第三方的继承可以一键式生成,天
然集成。
6、什么是Eureka以及它的架构是什么样子?
介绍:eureka是Netflix开发的服务发现组件,本身是一个基于REST的服务。Spring Cloud将它集成在其子项目spring-
cloud-netflix中, 以实现Spring Cloud的服务发现功能。
架构:
基本流程如下:
-
拦截我们的RestTemplate请求http://userservice/user/1
-
RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
-
DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
-
eureka返回列表,localhost:8081、localhost:8082
-
IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
-
RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求
9、在Ribbon中定义了哪些常用的负载均衡算法以及默认的负载均衡算法是哪一个?(高频)
常用的负载均衡算法:
1、RoundRobinRule:简单轮询服务列表来选择服务器
2、AvailabilityFilteringRule:对以下两种服务器进行忽略:
(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间
就会几何级地增加。
(2)并发数过高的服务器、如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以
由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。
3、WeightedResponseTimeRule: 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,
这个权重值会影响服务器的选择。
4、ZoneAvoidanceRule:以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。
而后再对Zone内的多个服务做轮询。它是Ribbon默认的负载均衡规则。
5、BestAvailableRule:忽略那些短路的服务器,并选择并发数较低的服务器。
6、RandomRule: 随机选择一个可用的服务器。
7、RetryRule:重试机制的选择逻辑。
默认的负载均衡算法:ZoneAvoidanceRule
10、什么是fegin?以及如何去使用?
概述:
1、fegin一个声明式的http的客户端工具用来简化远程调用,基于接口的注解的方式来声明一个http的客户端
2、feign整合了ribbon,具有负载均衡的能力
3、整合了Hystrix,具有熔断的能力
使用:
1、添加pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
2、在启动类上添加@EnableFeignClients注解
3、定义一个接口,通过@FeignClient(value = "leadnews-article")指定调用的哪个服务
11、你们项目中的配置信息是如何进行管理的?
项目中的配置信息使用的是统一配置中心,常见的统一配置中心有:Spring Cloud Config和nacos。我们项目中使用的是nacos,使用nacos可以很轻松的实现配置
信息的热更新。
具体的使用方式如下所示:
1、在nacos中创建一个配置信息,指定配置信息的dataId。dataId的组成:${application.name}-${profile}.yml
2、在项目中添加依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
3、在项目的classpath路径下创建一个bootstrap.yml文件,文件中的内容如下所示:
server: port: 51803 spring: application: name: user-service # 指定服务名称 cloud: nacos: config: server-addr: 192.168.200.130:8848 # 指定配置中心的ip地址和端口号 file-extension: yml # 指定配置中心中文件的扩展名
12、什么是Spring Cloud Gateway以及在你们的项目中如何去应用该组件的?(高频)
Spring Cloud Gateway:是Spring Cloud中所提供的一个服务网关组件,是整个微服务的统一入口,在服务网关中可以实现请求路由、统一的日志记录,流量监
控、权限校验等一系列的相关功能!
项目应用:权限的校验
具体实现思路:使用Spring Cloud Gateway中的全局过滤器拦截请求(GlobalFilter、Order),从
请求头中获取token,然后解析token。如果可以进行正常解析,此时进行放行;如果解析不到直接返回。
2 服务保护篇
13、什么是雪崩效应以及常见的解决方案有哪些?(高频)
雪崩效应:一个服务的不可用导致整个系统出现不可用的现象。如下图所示:
令牌桶算法:令牌桶是一个存放固定容量令牌的桶,按照固定速率r往桶里添加令牌;桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃;当一个请求
达到时,会尝试从桶中获取令牌;如果有,则继续处理请求;如果没有则排队等待或者直接丢弃;可以发现,漏桶算法的流出速率恒定,而令牌桶算法的流
出速率却有可能大于r;
从作用上来说,漏桶和令牌桶算法最明显的区别就是是否允许突发流量(burst)的处理,漏桶算法能够强行限制数据的实时传输(处理)速率,对突发流量
不做额外处理;而令牌桶算法能够在限制数据的平均传输速率的同时允许某种程度的突发传输。
15、Nginx中如何实现限流?
nginx的限流主要是两种方式:限制访问频率和限制并发连接数。nginx按请求速率限速模块使用的是漏桶算法,即能够强行保证请求的实时处理速度不会
超过设置的阈值。
nginx官方版本限制IP的连接和并发分别有两个模块:
1、limit_req_zone:用来限制单位时间内的请求数,即速率限制 , 采用的漏桶算法 "leaky bucket"。
2、limit_conn_zone:用来限制同一时间连接数,即并发限制。
limit_req_zone限流配置:
http { # 定义限流策略,$binary_remote_addr对客户端的ip进行限流,zone:定义共享内存区来存储访问信息, rateLimit:10m 表示一个大小为10M,名字为rateLimit的内 # 存区域。1M能存储16000 IP地址的访问信息,10M可以存储16W IP地址访问信息。rate定义了最大访问频率,1s最多允许1个请求访问。 limit_req_zone $binary_remote_addr zone=rateLimit:10m rate=1r/s ; # 搜索服务的虚拟主机 server { location / { # 使用限流策略,burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区(队列)当有大量请求(爆发)过来时, # 超过了访问频次限制的请求可以先放到这个缓冲区内。nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所 # 有请求会等待排队。 limit_req zone=rateLimit burst=5 nodelay; proxy_pass http://train-manager-search ; } } }
limit_conn_zone限流配置:
http { # 定义限流策略,$binary_remote_addr对客户端的ip进行限流、$server_name对虚拟主机支持的最大连接数进行限流 limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_zone $server_name zone=perserver:10m; # 搜索服务的虚拟主机 server { location / { # 对应的key是 $binary_remote_addr,表示限制单个IP同时最多能持有1个连接。 limit_conn perip 1; # 对应的key是 $server_name,表示虚拟主机(server) 同时能处理并发连接的总数。 # 注意,只有当 request header 被后端server处理后,这个连接才进行计数。 limit_conn perserver 10 ; proxy_pass http://train-manager-search ; } } }
16、Sentinel中提供了哪些流控模式分别表示什么意思?(高频)
常见的流控模式:
1、直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式
2、关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流。如下流控模式:
表示的意思:当/write资源访问量触发阈值时,就会对/read资源限流,避免影响/write资源。
3、链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流
例如有两条请求链路:
-
/test1 --> /common
-
/test2 --> /common
如果只希望统计从/test2进入到/common的请求,则可以这样配置:
17、Sentinel中提供了哪些流控效果分别表示什么意思?(高频)
常见的流控效果:
1、快速失败:达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式。
2、warm up:预热模式,对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值。这种模式主要应用
于服务的冷启动,请求阈值初始值是 maxThreshold / coldFactor,持续指定时长后,逐渐提高到maxThreshold值。而coldFactor的默认值是3。例
如,我设置QPS的maxThreshold为10,预热时间为5秒,那么初始阈值就是 10 / 3 ,也就是3,然后在5秒后逐渐增长到10。如下图所示:
3、排队等待:让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长。后来的请求必须等待前面执行完成,如果请求预期的等待时间超
出最大时长,则会被拒绝。
18、实现线程隔离有几种方式?Sentinel中使用的是哪一种方式?(高频)
线程隔离方式:
1、线程池隔离:有额外开销,但隔离控制更强
2、信号量隔离:简单,开销小
在Sentinel是通过信号量来实现线程隔离。如下图所示:
19、简述Sentinel中熔断器的工作原理?(高频)
熔断降级是解决雪崩问题的重要手段。其思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而
当服务恢复时,断路器会放行访问该服务的请求。断路器控制熔断和放行是通过状态机来完成的:
状态机包括三个状态:
-
closed:关闭状态,断路器放行所有请求,并开始统计异常比例、慢请求比例。超过阈值则切换到open状态
-
open:打开状态,服务调用被熔断,访问被熔断服务的请求会被拒绝,快速失败,直接走降级逻辑。Open状态5秒后会进入half-open状态
-
half-open:半开状态,放行一次请求,根据执行结果来判断接下来的操作。
-
请求成功:则切换到closed状态
-
请求失败:则切换到open状态
-
3 分布式事务篇
20、什么是分布式事务?
概述:在分布式系统上一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务节点上,且属于不同的应用,分布式事务需要保证这些小操作要
么全部成功,要么全部失败。
如下所示:
某电商系统的下单操作,需要请求三个服务来完成,这三个服务分别是:订单服务,账户服务,库存服务。当订单生成完毕以后,就需要分别请求账户服务
和库存服务进行进行账户余额的扣减和库存扣减。假设都扣减成功了,此时在执行下单的后续操作时出现了问题,那么订单数据库就进行事务回滚,订单生
成失败,而账户余额和扣减则都扣减成功了。这就出现了问题,而分布式事务就是解决上述这种不一致问题的。
21、哪些场景下都会产生分布式事务?
场景1:跨库事务
跨库事务指的是,一个应用某个功能需要操作多个库,不同的库中存储不同的业务数据。如下所示:
场景二:分库分表
通常一个库数据量比较大或者预期未来的数据量比较大,都会进行水平拆分,也就是分库分表。如下图,将数据库B拆分成了2个库:
对于分库分表的情况,一般开发人员都会使用一些数据库中间件来降低sql操作的复杂性。
如,对于sql:insert into user(id,name) values (1,"tianshouzhi"),(2,"wangxiaoxiao")。这条sql是操作单库的语法,单库情况下,可以保证事务的一致
性。
但是由于现在进行了分库分表,开发人员希望将1号记录插入分库1,2号记录插入分库2。所以数据库中间件要将其改写为2条sql,分别插入两个不同的分
库,此时要保证两个库要不都成功,要不都失败,因此基本上所有的数据库中间件都面临着分布式事务的问题。
场景三:跨服务事务
跨服务事务指的是,一个应用某个功能需要调用多个微服务进行实现,不同的微服务操作的是不同的数据库。如下所示:
Service A完成某个功能需要直接操作数据库,同时需要调用Service B和Service C,而Service B又同时操作了2个数据库,Service C也操作了一个库。
需要保证这些跨服务的对多个数据库的操作要不都成功,要不都失败,实际上这可能是最典型的分布式事务场景。
22、什么是CAP理论?
CAP定理是由加州大学伯克利分校Eric Brewer教授提出来的,他指出WEB服务无法同时满足一下3个属性:
1、一致性(Consistency) : 更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致(强一致性),不能存在中间状态。
2、可用性(Availability) : 系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。
3、分区容错性(Partition tolerance) : 分布式系统在遇到任何网络分区故障时,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发
生了故障。
如下所示:
23、为什么分布式系统中无法同时保证一致性和可用性?
首先一个前提,对于分布式系统而言,分区容错性是一个最基本的要求,因此基本上我们在设计分布式系统的时候只能从一致性(C)和可用性(A)之间进行取舍。
如果保证了一致性(C):对于节点N1和N2,当往N1里写数据时,N2上的操作必须被暂停,只有当N1同步数据到N2时才能对N2进行读写请求,在N2被暂停操作期
间客户端提交的请求会收到失败或超时。显然,这与可用性是相悖的。
如果保证了可用性(A):那就不能暂停N2的读写操作,但同时N1在写数据的话,这就违背了一致性的要求。
24、什么是BASE理论?
CAP是分布式系统设计理论,BASE是CAP理论中AP方案的延伸,核心思想是即使无法做到强一致性(StrongConsistency,CAP的一致性就是强一致
性),但应用可以采用适合的方式达到最终一致性(Eventual Consitency)。它的思想包含三方面:
1、Basically Available(基本可用):基本可用是指分布式系统在出现不可预知的故障的时候,允许损失部分可用性,但不等于系统不可用。
2、Soft state(软状态):即是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据
副本之间进行数据同步的过程存在延时。
3、Eventually consistent(最终一致性):强调系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。其本质是需要系统
保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
25、分布式事务的常见的解决方案有哪些?(高频)
方案一:2PC
两阶段提交又称2PC,2PC是一个非常经典的强一致、中心化的原子提交协议 。
中心化是指协议中有两类节点:一个是中心化协调者节点 (coordinator)和 N个参与者节点 (partcipant)。
两个阶段 :
1、第一阶段:投票阶段
2、第二阶段:提交/执行阶段。
举例订单服务A,需要调用支付服务B 去支付,支付成功则处理订单状态为待发货状态,否则就需要将购物订单处理为失败状态。 那么看2PC阶段是如何处
理的。
阶段一:
阶段一执行流程:
1、事务询问协调者向所有的参与者发送事务预处理请求,称之为Prepare,并开始等待各参与者的响应。
2、执行本地事务各个参与者节点执行本地事务操作,但在执行完成后并不会真正提交数据库本地事务,而是先向协调者报告说:“我这边可以处理了/我
这边不能处理”。
3、各参与者向协调者反馈事务询问的响应如果参与者成功执行了事务操作,那么就反馈给协调者Yes响应,表示事务可以执行,如果没有参与者成功执行事务,
那么就反馈给协调者 No 响应,表示事务不可以执行。
阶段二:
阶段二执行流程:
1、所有的参与者反馈给协调者的信息都是Yes,那么就会执行事务提交协调者向所有参与者节点发出Commit请求
2、事务提交参与者收到Commit请求之后,就会正式执行本地事务Commit操作,并在完成提交之后释放整个事务执行期间占用的事务资源。
方案二:3PC
三阶段提交又称3PC,其在两阶段提交的基础上增加了CanCommit阶段,并引入了超时机制。一旦事务参与者迟迟没有收到协调者的Commit请求,就会
自动进行本地commit,这样相对有效地解决了协调者单点故障的问题。
阶段一:
阶段一执行流程:
1、事务询问协调者向所有的参与者发送事务can commit请求,类似于2PC中的第二个阶段中的Prepare阶段,是一种事务询问操作,事务的协调者向所有
参与者询问“你们是否可以完成本次事务?”,并开始等待各参与者的响应。
2、如果参与者节点认为自身可以完成事务就返回“YES”,否则“NO”。
阶段二:
阶段二的执行流程:
1、在阶段一中,如果所有的参与者都返回Yes的话,那么就会进入PreCommit阶段进行事务预提交。此时分布式事务协调者会向所有的参与者节点发送
PreCommit请求。
2、参与者收到后开始执行事务操作,参与者执行完事务操作后(此时属于未提交事务的状态),就会向协调者反馈“Ack”表示我已经准备好提交了,并
等待协调者的下一步指令。
3、如果阶段一中有任何一个参与者节点返回的结果是No响应,或者协调者在等待参与者节点反馈的过程中超时。整个分布式事务就会中断,协调者就会向
所有的参与者发送“abort”请求。
阶段三:
阶段三执行流程:
1、在阶段二中如果所有的参与者节点都可以进行PreCommit提交,那么协调者就会从“预提交状态”-》“提交状态”。然后向所有的参与者节点发
送"doCommit"请求。
2、参与者节点在收到提交请求后就会各自执行事务提交操作,并向协调者节点反馈“Ack”消息,协调者收到所有参与者的Ack消息后完成事务。
3、相反,如果有一个参与者节点未完成PreCommit的反馈或者反馈超时,那么协调者都会向所有的参与者节点发送abort请求,从而中断事务。
方案三:TCC
TCC(Try-Confirm-Cancel)又称补偿事务。其核心思想是:"针对每个操作都要注册一个与其对应的确认和补偿(撤销操作)"。
它分为三个操作:
1、Try阶段:主要是对业务系统做检测及资源预留。
2、Confirm阶段:确认执行业务操作。
3、Cancel阶段:取消执行业务操作。
如下所示:
TCC事务的处理流程与2PC两阶段提交类似,不过2PC通常都是在跨库的DB层面,而TCC本质上就是一个应用层面的2PC,需要通过业务逻辑来实现。这
种分布式事务的实现方式的优势在于,可以让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能。 不足之处则在于对应用的侵入性
非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。此外,其实现难度也比较大,需要按照网络状态、系统故障等不同的失败原因
实现不同的回滚策略。为了满足一致性的要求,confirm和cancel接口还必须实现幂等。
方案四:MQ分布式事务
上面的三种分布式事务的解决方案适用于对数据一致性要求很高的场景。如果数据强一致性要求没那么高,可以采用消息中间件(MQ)实现事务最终一
致。 在支付系统中,常常使用的分布式事务解决方案就是基于MQ实现的,它对数据强一致性要求没那么高,但要求数据最终一致即可。
例如:向借呗申请借钱,借呗审核通过后支付宝的余额才会增加,但借呗和支付宝有可能不是同一个系统,这时候如何实现事务呢?实现方案如下图:
执行流程如下所示:
1、找花呗借钱
2、花呗借钱审核通过,同步生成借款单
3、借款单生成后,向MQ发送消息,通知支付宝转账
4、支付宝读取MQ消息,并增加账户余额
上图最复杂的其实是如何保障2、3在同一个事务中执行(本地事务和MQ消息发送在同一个事务执行),借款结束后,借呗数据处理就完成了,接下来支付
宝才能读到消息,然后执行余额增加,这才完成整个操作。如果中途操作发生异常,例如支付宝余额增加发生问题怎么办?此时需要人工解决,没有特别好
的办法,但这种事故概率极低。
26、Seata的架构是什么?(高频)
Seata事务管理中有三个重要的角色:
1、TC (Transaction Coordinator) -事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
2、TM (Transaction Manager) -事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
3、RM (Resource Manager) -资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
如下所示:
27、XA模式的工作流程是什么?(高频)
xa模式整个工作流程图如下所示:
分为两个阶段:
1、RM一阶段的工作:① 注册分支事务到TC ② 执行分支业务sql但不提交 ③ 报告执行状态到TC
2、TC二阶段的工作:TC检测各分支事务执行状态 ①如果都成功,通知所有RM提交事务 ②如果有失败,通知所有RM回滚事务
3、RM二阶段的工作:接收TC指令,提交或回滚事务
xa模式牺牲了可用性,保证了强一致性
28、AT模型的工作原理是什么?(高频)
at模式的整个工作流程图如下所示:
1、阶段一RM的工作:① 注册分支事务 ② 记录undo-log(数据快照)③ 执行业务sql并提交 ④报告事务状态
2、阶段二提交时RM的工作:删除undo-log即可
3、阶段二回滚时RM的工作:根据undo-log恢复数据到更新前
at模式牺牲了一致性,保证了可用性
29、TCC模型的工作原理是什么?(高频)
TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:
1、Try:资源的检测和预留;
2、Confirm:完成资源操作业务;要求 Try 成功 Confirm 一定要能成功。
3、Cancel:预留资源释放,可以理解为try的反向操作。
Seata中的tcc模型的执行流程如下所示:
1、阶段一RM的工作:① 注册分支事务 ② 执行try操作预留资源 ④报告事务状态
2、阶段二提交时RM的工作:根据各分支事务的状态执行confirm或者cancel