重点面试题
什么是微服务
微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分为一组小的服务, 每个服务运行在其独立的自己的进程中,服务之间相互协调、互相配合,为用户提供最终价值。服 务之间采用轻量级的通信机制互相沟通(通常是基于HTTP的RESTful API),每个服务都围绕着具体
的业务进行构建,并且能够被独立的构建在生产环境、类生产环境等。另外,应避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行
构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也 可以使用不同的数据存储。
SpringCloud有什么优势
使用 Spring Boot 开发分布式微服务时,我们面临以下问题
- 与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。
- 服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。
- 冗余-分布式系统中的冗余问题。
- 负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路, 中央处理单元,或磁盘驱动器的分布。
- 性能-问题 由于各种运营开销导致的性能问题。
- 部署复杂性-Devops 技能的要求。
什么是 OAuth?
OAuth 代表开放授权协议。这允许通过在 HTTP 服务上启用客户端应用程序(例
如第三方提供商 Facebook,GitHub 等)来访问资源所有者的资源。因此,您可
以在不使用其凭据的情况下与另一个站点共享存储在一个站点上的资源。
使用 Spring Cloud 有什么优势?
使用 Spring Boot 开发分布式微服务时,我们面临以下问题
- 与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。
- 服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。
- 冗余-分布式系统中的冗余问题。
- 负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机集群,网络链路,中央处理单元,或磁盘驱动器的分布。
- 性能-问题 由于各种运营开销导致的性能问题。
- 部署复杂性-Devops 技能的要求。
服务注册和发现是什么意思?Spring Cloud 如何实现?
当我们开始一个项目时,我们通常在属性文件中进行所有的配置。随着越来越多的服务开发和部署,添加和修改这些属性变得更加复杂。有些服务可能会下降,而某些位置可能会发生变化。手动更改属性可能会产生问题。 Eureka 服务注册和发现可以在这种情况下提供帮助。由于所有服务都在 Eureka 服务器上注册并通过调用 Eureka 服务器完成查找,因此无需处理服务地点的任何更改和处理。
负载平衡的意义什么?
在计算中,负载平衡可以改善跨计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器等多种计算资源的工作负载分布。负载平衡旨在优化资源使用,最大化吞吐量,最小化响应时间并避免任何单一资源的过载。使用多个组件进行负载平衡而不是单个组件可能会通过冗余来提高可靠性和可用性。负载平衡通常涉及专用软件或硬件,例如多层交换机或域名系统服务器进程。
Eureka和zookeeper都可以提供服务注册与发现的功能,请说说两个的区别?
Zookeeper保证了CP(C:一致性,P:分区容错性),Eureka保证了AP(A:高可用)
- 当向注 册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的信息,但不能容忍直接 down掉不可用。也就是说,服务注册功能对高可用性要求比较高,但zk会出现这样一种情况,当 master节点因为网络故障与其他节点失去联系时,剩余节点会重新选leader。问题在于,选取leader时间过长,30 ~ 120s,且选取期间zk集群都不可用,这样就会导致选取期间注册服务瘫痪。 在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够恢复,但是漫长的选取时间导致的注册长期不可用是不能容忍的。
- Eureka保证了可用性,Eureka各个节点是平等的,几个节点挂掉不会影响正常节点的工作,剩余 的节点仍然可以提供注册和查询服务。而Eureka的客户端向某个Eureka注册或发现时发生连接失败,则会自动切换到其他节点,只要有一台Eureka还在,就能保证注册服务可用,只是查到的信息 可能不是最新的。除此之外,Eureka还有自我保护机制,如果在15分钟内超过85%的节点没有正常 的心跳,那么Eureka就认为客户端与注册中心发生了网络故障,此时会出现以下几种情况:
- Eureka不在从注册列表中移除因为长时间没有收到心跳而应该过期的服务。
- Eureka仍然能够 接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点仍然可用)
- 当 网络稳定时,当前实例新的注册信息会被同步到其他节点。 因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个微服务瘫痪
SpringBoot和SpringCloud的区别?
- SpringBoot专注于快速方便的开发单个个体微服务。
- SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整 合并管理起来, 为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策 竞选、分布式会话等等集成服务
- SpringBoot可以离开SpringCloud独立使用开发项目, 但是SpringCloud离不开SpringBoot ,属于 依赖的关系.
- SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。
Ribbon和Feign的区别?
Ribbon和Feign都是调用其他服务的,但方式不同。
- 启动类注解不同,Ribbon是@RibbonClient feign 的是@EnableFeignClients
- 服务指定的位置不同,Ribbon是在@RibbonClient注解上声明,Feign 则是在定义抽象方法的接口中使用@FeignClient声明。
- 调用方式不同,Ribbon需要自己构建http 请求,模拟http请求
什么是CAP理论?
CAP 也就是 Consistency(一致性)、Availability(可用性)、Partition Tolerance(分区容错性) 这三个单词首字母组合。
在理论计算机科学中,CAP 定理(CAP theorem)指出对于一个分布式系统来说,当设计读写操作时,只能能同时满足以下三点中的两个:
- 一致性(Consistence) : 所有节点访问同一份最新的数据副本
- 可用性(Availability): 非故障的节点在合理的时间内返回合理的响应(不是错误或者超时的响应)。
分区容错性(Partition tolerance) : 分布式系统出现网络分区的时候,仍然能够对外提供服务。
什么是限流?
限流是从用户访问压力的角度来考虑如何应对系统故障。一般可以用sentinel框架处理
限流为了对服务端的接口接受请求的频率进行限制,防止服务挂掉。比如某一接口的请求限制为 100 个每秒, 对超过限制的请求放弃处理或者放到队列中等待处理。限流可以有效应对突发请求过多。
什么是降级?
降级是从系统功能优先级的角度考虑如何应对系统故障。
服务降级指的是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。
什么是熔断?
熔断和降级是两个比较容易混淆的概念,两者的含义并不相同。
降级的目的在于应对系统自身的故障,而熔断的目的在于应对当前系统依赖的外部系统或者第三方系统的故障。
什么是排队?
另类的一种限流,类比于现实世界的排队。玩过英雄联盟的小伙伴应该有体会,每次一有活动,就要经历一波排队才能进入游戏。一般用消息中间件如:kafka、RabbitMQ解决
为什么使用消息队列?
解耦、异步、削峰
解耦
传统模式的缺点:
系统间耦合性太强,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!
异步
传统模式:
一些非必要的业务逻辑以同步的方式运行,太耗费时间。
削峰
传统模式缺点
并发量大的时间,所有的请求直接怼到数据库,造成数据库连接异常
spring cloud 5大组件有哪些?
一代:
eureka:注册中心
ribbon:负载均衡
feign:远程调用
hystrix:服务熔断
getway:网关
二代阿里云:
nacos:注册中心/配置中心
ribbon:负载均衡
feign:远程调用
sentinel:服务保护
getway:网关
ribbon负载均衡策略有哪些?
Ribbon提供了多种负载均衡策略,如随机(Random)、轮询(Round Robin)、最少活跃调用(Least Active)等。其中,默认的负载均衡策略是随机(Random)。在Ribbon中,负载均衡策略是通过IRule接口定义的,可以通过实现该接口来定义自己的负载均衡策略。例如,可以自定义一个基于权重比例的负载均衡策略,通过配置不同的权重比例来影响随机选择服务器的结果。同时,Ribbon还支持自定义均衡策略,可以通过继承AbstractLoadBalancerRule抽象类来实现自己的负载均衡策略。
什么是服务雪崩怎么解决这个问题?
服务雪崩指的是,一个服务不可用,导致调用这个服务服务的服务也不可用,从而导致整个链路的服务不可用。
解决服务雪崩有两种方式:
服务降级:他是服务自我保护的一种方式,或者说是保护下游服务的一种方式,他的主要作用是不会受请求突增影响,而变得不可用,保证服务不会崩溃。
服务熔断:他默认是关闭的需要手动打开,在一定时间内服务请求失败超过一定的阈值,就会开启服务熔断,然后每个一段时间重新请求微服务,如果请求可达,则关闭熔断,如果服务还是不可达,则继续走熔断机制。
Nacos中的保护阈值的作用是什么?
假如现在有一个服务,本来有10个实例,但是现在挂掉了8个,剩下2个正常实例,此时本来由10个实例处理的流量,就全部交给这个两个正常实例来处理了,此时这两个实例很有可能是处理不过来的,最终导致被压垮,为了应对这种情况,Nacos提供了保护阈值这个功能,我们可以给某个服务设置一个0-1的阈值,比如0.5,那就表示,一旦实例中只剩下一半的健康实例了,比如10个实例,只剩下5个健康实例了,那么消费者在进行服务发现时,则会把该服务的所有实例,也包括不健康的实例都拉取到本地,然后再从所有实例中进行负载均衡,选出一个实例进行调用,在这种情况下,选出来的即可能是一个健康的实例,也可能是挂掉的实例,但是通过这种方式,很好的保护的剩下的健康实例,至少保证了一部分请求能正常的访问,而不至于所有请求都不能正常访问,这就是Nacos中的保护阈值,同时,这个功能在Spring Cloud Tencent中叫全死全活。
Nacos的就近访问是什么意思?
首先,在Nacos中,一个服务可以有多个实例,并且可以给实例设置cluster-name,就是可以再进一步的给所有实例划分集群,那如果现在某个服务A想要调用服务B,那么Naocs会看调用服务A的实例是属于哪个集群的,并且调用服务B时,那就会调用同样集群下的服务B实例,根据cluster-name来判断两个实例是不是同一个集群,这就是Nacos的就近访问
微服务面试题
Spring Cloud 5大组件有哪些?
早期的Spring Cloud五大组件是
- Eureka : 注册中心
- Ribbon : 负载均衡
- Feign : 远程调用
- Hystrix : 服务熔断
- Zuul/Gateway : 网关
随着SpringCloudAlibba在国内兴起 , 我们项目中使用了一些阿里巴巴的组件 - 注册中心/配置中心 Nacos
- 负载均衡 Ribbon
- 服务调用 Feign
- 服务保护 sentinel
- 服务网关 Gateway
服务注册
服务注册和发现是什么意思?Spring Cloud 如何实现服务注册发现?
我理解的是主要三块大功能,分别是服务注册 、服务发现、服务状态监控
我们当时项目采用的eureka作为注册中心,这个也是spring cloud体系中的一个核心组件
服务注册:服务提供者需要把自己的信息注册到eureka,由eureka来保存这些信息,比如服务名称、ip、端口等等
服务发现:消费者向eureka拉取服务列表信息,如果服务提供者有集群,则消费者会利用负载均衡算法,选择一个发起调用
服务监控:服务提供者会每隔30秒向eureka发送心跳,报告健康状态,如果eureka服务90秒没接收到心跳,从eureka中剔除
我看你之前也用过nacos、你能说下nacos与eureka的区别?
我们当时xx项目就是采用的nacos作为注册中心,选择nacos还要一个重要原因就是它支持配置中心,不过nacos作为注册中心,也比eureka要方便好用一些,主要相同不同点在于几点:
共同点
Nacos与eureka都支持服务注册和服务拉取,都支持服务提供者心跳方式做健康检测
Nacos与Eureka的区别
- Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
- 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
- Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
- Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式
Nacos配置中心实现原理
负载均衡
你们项目负载均衡如何实现的 ?
在服务调用过程中的负载均衡一般使用SpringCloud的Ribbon 组件实现 , Feign的底层已经自动集成了Ribbon , 使用起来非常简单
当发起远程调用时,ribbon先从注册中心拉取服务地址列表,然后按照一定的路由策略选择一个发起远程调用,一般的调用策略是轮询
Ribbon负载均衡策略有哪些 ?
我想想啊,有很多种,我记得几个:
- RoundRobinRule:简单轮询服务列表来选择服务器
- WeightedResponseTimeRule:按照权重来选择服务器,响应时间越长,权重越小
- RandomRule:随机选择一个可用的服务器
- BestAvailableRule:忽略那些短路的服务器,并选择并发数较低的服务器
- ZoneAvoidanceRule:区域敏感策略,以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询(默认)
如果想自定义负载均衡策略如何实现 ?
提供了两种方式:
- 创建类实现IRule接口,可以指定负载均衡策略,这个是全局的,对所有的远程调用都起作用
- 在客户端的配置文件中,可以配置某一个服务调用的负载均衡策略,只是对配置的这个服务生效远程调用
熔断、降级
什么是服务雪崩,怎么解决这个问题?
服务雪崩是指一个服务失败,导致整条链路的服务都失败的情形,一般我们在项目解决的话就是两种方案,第一个是服务降级,第二个是服务熔断,如果流量太大的话,可以考虑限流
服务降级:服务自我保护的一种方式,或者保护下游服务的一种方式,用于确保服务不会受请求突增影响变得不可用,确保服务不会崩溃,一般在实际开发中与feign接口整合,编写降级逻辑
服务熔断:默认关闭,需要手动打开,如果检测到 10 秒内请求的失败率超过 50%,就触发熔断机制。之后每隔 5 秒重新尝试请求微服务,如果微服务不能响应,继续走熔断机制。如果微服务可达,则关闭熔断机制,恢复正常请求
限流
你们项目中有没有做过限流 ? 怎么做的 ?
我当时做的xx项目,采用就是微服务的架构,因为xx因为,应该会有突发流量,最大QPS可以达到2000,但是服务支撑不住,我们项目都通过压测最多可以支撑1200QPS。因为我们平时的QPS也就不到100,为了解决这些突发流量,所以采用了限流。
-
我们当时采用的nginx限流操作,nginx使用的漏桶算法来实现过滤,让请求以固定的速率处理请求,可以应对突发流量,我们控制的速率是按照ip进行限流,限制的流量是每秒20
-
我们当时采用的是spring cloud gateway中支持局部过滤器RequestRateLimiter来做限流,使用的是令牌桶算法,可以根据ip或路径进行限流,可以设置每秒填充平均速率,和令牌桶总容量
限流常见的算法有哪些呢?
比较常见的限流算法有漏桶算法和令牌桶算法
- 漏桶算法是把请求存入到桶中,以固定速率从桶中流出,可以让我们的服务做到绝对的平均,起到很好的限流效果
- 令牌桶算法在桶中存储的是令牌,按照一定的速率生成令牌,每个请求都要先申请令牌,申请到令牌以后才能正常请求,也可以起到很好的限流作用
它们的区别是,漏桶和令牌桶都可以处理突发流量,其中漏桶可以做到绝对的平滑,令牌桶有可能会产生突发大量请求的情况,一般nginx限流采用的漏桶,spring cloud gateway中可以支持令牌桶算法
分布式事务
什么是CAP理论?
CAP主要是在分布式项目下的一个理论。包含了三项,一致性、可用性、分区容错性
- 一致性(Consistency)是指更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致(强一致性),不能存在中间状态。
- 可用性(Availability) 是指系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。
- 分区容错性(Partition tolerance) 是指分布式系统在遇到任何网络分区故障时,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。
为什么分布式系统中无法同时保证一致性和可用性?
首先一个前提,对于分布式系统而言,分区容错性是一个最基本的要求,因此基本上我们在设计分布式系统的时候只能从一致性(C)和可用性(A)之间进行取舍。
如果保证了一致性(C):对于节点N1和N2,当往N1里写数据时,N2上的操作必须被暂停,只有当N1同步数据到N2时才能对N2进行读写请求,在N2被暂停操作期间客户端提交的请求会收到失败或超时。显然,这与可用性是相悖的。
如果保证了可用性(A):那就不能暂停N2的读写操作,但同时N1在写数据的话,这就违背了一致性的要求。
解决分布式事务的思想和模型:
- 最终一致思想:各分支事务分别执行并提交,如果有不一致的情况,再想办法恢复数据(AP)
- 强一致思想:各分支事务执行完业务不要提交,等待彼此结果。而后统一提交或回滚(CP)
什么是BASE理论?
BASE是CAP理论中AP方案的延伸,核心思想是即使无法做到强一致性(StrongConsistency,CAP的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性(Eventual Consitency)。它的思想包含三方面:
- Basically Available(基本可用):基本可用是指分布式系统在出现不可预知的故障的时候,允许损失部分可用性,但不等于系统不可用。
- Soft state(软状态):即是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
- Eventually consistent(最终一致性):强调系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。其本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
Seata事务管理中有三个重要的角色:
•TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
•TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
•RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
你们采用哪种分布式事务解决方案?
seata
分布式服务的接口幂等性如何设计?
采用的token+redis实现的,流程是这样的
- 第一次请求,也就是用户打开了商品详情页面,我们会发起一个请求,在后台生成一个唯一token存入redis,key就是用户的id,value就是这个token,同时把这个token返回前端
- 第二次请求,当用户点击了下单操作会后,会携带之前的token,后台先到redis进行验证,如果存在token,可以执行业务,同时删除token;如果不存在,则直接返回,不处理业务,就保证了同一个token只处理一次业务,就保证了幂等性
任务调度
xxl-job路由策略有哪些?
xxl-job提供了很多的路由策略,我们平时用的较多就是:轮询、故障转移、分片广播…
xxl-job任务执行失败怎么解决?
有这么几个操作
- 第一:路由策略选择故障转移,优先使用健康的实例来执行任务
- 第二,如果还有失败的,我们在创建任务时,可以设置重试次数
- 第三,如果还有失败的,就可以查看日志或者配置邮件告警来通知相关负责人解决
如果有大数据量的任务同时都需要执行,怎么解决?
我们会让部署多个实例,共同去执行这些批量的任务,其中任务的路由策略是分片广播
在任务执行的代码中可以获取分片总数和当前分片,按照取模的方式分摊到各个实例执行就可以了
监控
你们的微服务是怎么监控的?
我们项目中采用的skywalking进行监控的
- skywalking主要可以监控接口、服务、物理实例的一些状态。特别是在压测的时候可以看到众多服务中哪些服务和接口比较慢,我们可以针对性的分析和优化。
- 我们还在skywalking设置了告警规则,特别是在项目上线以后,如果报错,我们分别设置了可以给相关负责人发短信和发邮件,第一时间知道项目的bug情况,第一时间修复