10.SpringCloud面试题

345 阅读19分钟

一、 什么是微服务架构

1. 什么是微服务架构?微服务架构的特点是什么?

微服务架构就是将单体的应用程序分成多个应用程序,这多个应用程序就成为微服务,每个微服务运行在自己的进程中,并使用轻量级的机制通信。这些服务围绕业务能力来划分,并通过自动化部署机制来独立部署。这些服务可以使用不同的编程语言,不同数据库,以保证最低限度的集中式管理。

特点:

  1. 单一职责:微服务中每一个服务都对应唯一的业务能力,做到单一职责。
  2. 技术独立:因为是面向服务,提供Rest接口,使用什么技术没有人干涉
  3. 前后端分离
  4. 数据库分离
  5. 部署独立

2. Spring Cloud 是什么

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。 Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

3. SpringCloud的优缺点

  • 优点:

  1. 耦合度比较低。不会影响其他模块的开发。

  2. 减轻团队的成本,可以并行开发,不用关注其他人怎么开发,先关注自己的开发。

  3. 配置比较简单,基本用注解就能实现,不用使用过多的配置文件。

  4. 微服务跨平台的,可以用任何一种语言开发。

  5. 每个微服务可以有自己的独立的数据库也有用公共的数据库。

  6. 直接写后端的代码,不用关注前端怎么开发,直接写自己的后端代码即可,然后暴露接口,通过组件进行服务通信。

  • 缺点:

  1. 部署比较麻烦

  2. 针对数据的管理比麻烦,因为微服务可以每个微服务使用一个数据库。

  3. 系统集成测试比较麻烦

  4. 性能的监控比较麻烦。【最好开发一个大屏监控系统】

总的来说优点大过于缺点,目前看来Spring Cloud是一套非常完善的分布式框架,目前很多企业开始用微服务、Spring Cloud的优势是显而易见的。因此对于想研究微服务架构的同学来说,学习Spring Cloud是一个不错的选择。

4. SpringBoot和SpringCloud的区别?

SpringBoot专注于快速方便的开发单个个体微服务。 SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来, 为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务 SpringBoot可以离开SpringCloud独立使用开发项目, 但是SpringCloud离不开SpringBoot ,属于依赖的关系 SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。

5. SpringCloud由什么组成

SpringCloud目前只要有两套:SpringCloud Netflix和SpringCloud Alibaba

  • SpringCloud Netflix
  1. Spring Cloud Eureka:服务注册与发现
  2. Spring Cloud Zuul:服务网关
  3. Spring Cloud Ribbon:客户端负载均衡
  4. Spring Cloud Feign:声明性的Web服务客户端
  5. Spring Cloud Hystrix:断路器
  6. Spring Cloud Confifig:分布式统一配置管理
  7. zipkin:分布式链路追踪
  • SpringCloud Alibaba
  1. nacos:注册中心、配置中心
  2. gateway:服务网关
  3. Spring Cloud Ribbon:客户端负载均衡
  4. Spring Cloud Feign:声明性的Web服务客户端
  5. Sentinel:服务容错(限流、降级、熔断)
  6. Sleuth:调用链监控
  7. Seata:分布式事务

6. Spring Cloud 和dubbo区别?

  1. 服务调用方式:

  • dubbo是RPC

  • springcloud是Rest Api

  1. 注册中心:

  • dubbo 是zookeeper

  • springcloud是eureka,也可以是zookeeper

最大区别:SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式。

总体来说,两者各有优势。虽说后者服务调用的功能,但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的依赖,这在强调快速演化的微服务环境下,显得更加合适。

SpringCloud比dubbo的功能更强大,覆盖面更广,而且能够与SpringFramework、SpringBoot、SpringData、SpringBatch等其他Spring项目完美融合,这些对于微服务至关重要。

使用Dubbo构建的微服务架构各环节我们选择自由度高,而SpringCloud在Spring Source的整合下,做了大量的兼容性测试,保证了机器拥有更高的稳定性。

二、Eureka

1. 什么是Eureka

Eureka是SpringCloud的主要组件,是服务注册发现的组件。Spring Cloud Eureka分为Server端和Client端,Server端作为应用的注册中心,Client端会向Server端注册服务消费服务。Eureka Server和Eureka Client都是采用Java编写的,所以,Eureka主要适用于通过Java实现的分布式系统,但是Eureka Server的服务治理机制提供了完备的RESTful API,所以它也支持将非Java语言构建的微服务应用纳入Eureka的服务治理体系中来。

2. Eureka有哪些功能?

  1. 服务注册

Eureka Client会启动时通过发送REST请求的方式向Eureka Server注册自己的服务,提供自身的元数据,比如ip地址、端口、运行状况指标的url、主页地址等信息。Eureka Server接收到注册请求后就会把这些元数据信息存储在一个双层的ConcurrentHashMap中。

服务上线:http://192.168.1.1:8810/eureka/apps/USER-SERVICE/192.168.1.9:user-service:8086/status?value=UP

  1. 服务续约

服务注册后,Eureka Client会维护一个心跳来持续通知Eureka Server,告知注册中心服务一直处于可用状态,防止被剔除。Eureka Client在默认的情况下会每隔30秒发送一次心跳来进行服务续约。Eureka Server会有一个定时器定时轮训是否续约,连续90s没收到心跳就会触发服务剔除。 服务续约任务的调用间隔时间,默认为30秒 eureka.instance.lease-renewal-interval-in-seconds=30 服务失效的时间,默认为90秒。 eureka.instance.lease-expiration-duration-in-seconds=90

  1. 服务剔除

有时候,服务实例可能会因为网络故障等原因导致不能提供服务,而此时该实例也没有发送请求给Eureka Server来进行服务下线,所以,还需要有服务剔除的机制。Eureka Server在启动的时候会创建一个定时任务,每隔一段时间(默认60秒),从当前服务清单中把超时没有续约(默认90秒)的服务剔除。

  1. 服务下线

当Eureka Client需要关闭或重启时,就不希望在这个时间段内再有请求进来,所以,就需要提前先发送REST请求给Eureka Server,告诉Eureka Server自己要下线了,Eureka Server在收到请求后,就会把该服务状态置为下线(DOWN),并把该下线事件传播出去。

服务下线:http://192.168.1.1:8810/eureka/apps/USER-SERVICE/192.168.1.9:user-service:8086/status?value=OUT_OF_SERVICE

  1. 服务同步

Eureka Server之间会互相进行注册,构建Eureka Server集群,不同Eureka Server之间会进行服务同步,用来保证服务信息的一致性

  1. 获取服务

Eureka Client会定时向服务器拉取注册服务列表,分为全量拉取和增量拉取。拉取使用到了缓存ResponseCache实现,有两层缓存实现。服务消费者(Eureka Client)在启动的时候,会发送一个REST请求给Eureka Server,获取上面注册的服务清单,并且缓存在Eureka Client本地,默认缓存30秒,。同时,为了性能考虑,Eureka Server也会维护一份只读的服务清单缓存,该缓存每隔30秒更新一次。 RegistryFetchIntervalSeconds

  1. 服务调用

服务消费者在获取到服务清单后,就可以根据清单中的服务列表信息,查找到其他服务的地址,从而进行远程调用。Eureka有Region和Zone的概念,一个Region可以包含多个Zone,在进行服务调用时,优先访问处于同一个Zone中的服务提供者。

  1. 自我保护

既然Eureka Server会定时剔除超时没有续约的服务,那就有可能出现一种场景,网络一段时间内发生了异常,所有的服务都没能够进行续约,Eureka Server就把所有的服务都剔除了,这样显然不太合理。所以,就有了自我保护机制,当短时间内,统计续约失败的比例,如果达到一定阈值,则会触发自我保护的机制,在该机制下,Eureka Server不会剔除任何的微服务,等到正常后,再退出自我保护机制。

  1. 远程调用

当 Eureka Client 从注册中心获取到服务提供者信息后,就可以通过 Http 请求调用对应的服务;服务提供者有多个时,Eureka Client 客户端会通过 Ribbon 自动进行负载均衡。

3. Eureka怎么实现高可用

可以搭建Eureka Server集群,多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点,从而实现数据同步。因此,无论客户端访问到Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。

4. 什么是Eureka的自我保护模式,

Eureka Server会定时剔除超时没有续约的服务,那就有可能出现一种场景,网络一段时间内发生了异常,所有的服务都没能够进行续约,Eureka Server就把所有的服务都剔除了,这样显然不太合理。所以,就有了自我保护机制,当短时间内,统计续约失败的比例,如果达到一定阈值,则会触发自我保护的机制,在该机制下,Eureka Server不会剔除任何的微服务,等到正常后,再退出自我保护机制。

5. DiscoveryClient的作用

可以从注册中心中根据服务别名获取注册的服务器信息。

6. Eureka和ZooKeeper都可以提供服务注册与发现的功能,请说说两个的区别

Zookeeper保证了CP(C:一致性,P:分区容错性),Eureka保证了AP(A:高可用)

  1. 当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的信息,但不能容忍直接down掉不可用。也就是说,服务注册功能对高可用性要求比较高,但zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新选leader。问题在于,选取leader时间过长,30 ~ 120s,且选取期间zk集群都不可用,这样就会导致选取期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够恢复,但是漫长的选取时间导致的注册长期不可用是不能容忍的。

  2. Eureka保证了可用性,Eureka各个节点是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点仍然可以提供注册和查询服务。而Eureka的客户端向某个Eureka注册或发现是发生连接失败,则会自动切换到其他节点,只要有一台Eureka还在,就能保证注册服务可用,只是查到的信息可能不是最新的。除此之外,Eureka还有自我保护机制,如果在15分钟内超过85%的节点没有正常的心跳,那么Eureka就认为客户端与注册中心发生了网络故障,此时会出现以下几种情况:

    ​ ①、Eureka不在从注册列表中移除因为长时间没有收到心跳而应该过期的服务。

    ​ ②、Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点仍然可用)

    ​ ③、当网络稳定时,当前实例新的注册信息会被同步到其他节点。

    因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个微服务瘫痪

三、Zuul

1. 网关的作用是什么

统一管理微服务请求,权限控制、负载均衡、路由转发、监控、安全控制黑名单和白名单等

2. 网关与过滤器有什么区别

网关是对所有服务的请求进行分析过滤,过滤器是对单个服务而言。

3. 常用网关框架有那些?

Nginx、Zuul、Gateway

4. Zuul与Nginx有什么区别?

在这里插入图片描述
  1. 首先 , Nginx是C语言开发,而 Zuul 是Java语言开发
  2. Nginx负载均衡实现,采用服务器实现负载均衡,而Zuul负载均衡的实现是采用 Ribbon + Eureka 来实现本地负载均衡。
  3. Nginx适合于服务器端负载均衡,Zuul适合微服务中实现网关
  4. Nginx相比Zuul功能会更加强大,因为Nginx可以整合一些脚本语言( Nginx + lua )
  5. Nginx 是一个高性能的HTTP 和反向代理服务器,也可以作为静态服务器。Zuul是 Spring Cloud Netflix 中的开源的一个API Gateway 服务器,本质上是一个web servlet 应用,提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和Netflix 流应用的Web 网站后端所有请求的前门

5. 既然Nginx可以实现网关?为什么还需要使用Zuul框架

Zuul是SpringCloud集成的网关,使用Java语言编写,可以对SpringCloud架构提供更灵活的服务。比如统一管理微服务请求,权限控制、负载均衡、路由转发、监控、安全控制黑名单和白名单等

6. 如何设计一套API接口

考虑到API接口的分类可以将API接口分为开发API接口和内网API接口,内网API接口用于局域网,为内部服务器提供服务。开放API接口用于对外部合作单位提供接口调用,需要遵循Oauth2.0权限认证协议。同时还需要考虑安全性、幂等性等问题。

7. 如何实现动态Zuul网关路由转发

通过path配置拦截请求,通过ServiceId到配置中心获取转发的服务列表,Zuul内部使用Ribbon实现本地负载均衡和转发。

8. Zuul网关如何搭建集群

使用Nginx的upstream设置Zuul服务集群,通过location拦截请求并转发到upstream,默认使用轮询机制对Zuul集群发送请求。

四、Ribbon

1. Ribbon是什么?

  • Ribbon是Netfix发布的开源项目,主要功能是提供客户端的软件负载均衡算法

  • Ribbon客户端组件提供一系列完善的配置项,如连接超时,重试等。简单的说,就是在配置文件中列出后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。(有点类似Nginx)

2.Nginx与Ribbon的区别

Nginx是反向代理同时可以实现负载均衡,nginx拦截客户端请求采用负载均衡策略根据upstream配置进行转发,相当于请求通过nginx服务器进行转发。Ribbon是客户端负载均衡, 从注册中心读取目标服务器信息,然后客户端采用轮询策略对服务直接访问,全程在客户端操作。

3. Ribbon底层实现原理

Ribbon使用discoveryClient从注册中心读取目标服务信息,对同一接口请求进行计数,使用%取余算法获取目标服务集群索引,返回获取到的目标服务信息。

五、Hystrix

1. 什么是Hystrix?

Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程隔离、信号量隔离、降级策略、熔断技术。

2. 什么情况下会触发Hystrix降级?

  • 线程池已满
  • 请求超时
  • 服务异常

2. 什么是服务熔断?什么是服务降级?

  • 熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务降级,进而熔断该节点微服务的调用,快速返回“错误”的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现,Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,默认5秒内 20次失败 且失败比例大于50%,如果失败,就会启动熔断机制。熔断机制的注解是@HystrixCommand

  • 服务降级,一般是从整体负荷考虑。就是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个默认值。这样做,虽然水平下降,但好歹可用,比直接挂掉强。

  • 服务降级分为提供方降级和消费方降级:当访问的目标服务发生异常时,服务提供方进行降级;当访问的目标服务不可达时,可以执行消费方降级。

  • 服务熔断通常适与服务降级配合使用。在服务发生熔断后,一般会让请求走事先配置的处理方法,这个处理方法就是一个降级逻辑。

3. Hystrix有哪三种状态?

  1. **关闭状态:**熔断器默认关闭状态, 所有请求都正常可以访问;

  2. 打开状态: 当失败次数达到一定的阈值时,熔断器自动打开;(默认5秒内 20次失败 且失败比例大于50%) 此时,所有请求都进行服务降级;

  3. **半开状态:**熔断5s后,进入半开状态 , 半开 会允许一小部分请求去访问服务,判断结果是否成功:

​ 如果还是失败:进入打开状态,继续熔断5s, .....

​ 如果小部分请求成功了,就会继续放更多的请求过去,直至正常后,熔断器进入关闭状态;

关闭 --打开 --半开 --(成功了)关闭...

关闭 --打开 --半开 --(还是失败)打开...

4. Hystrix限流的两种策略?

  1. 线程池隔离模式:使用一个线程池来存储当前请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求先入线程池队列。这种方式要为每个依赖服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)。
  2. 信号量隔离模式:使用一个原子计数器(或信号量)记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃该类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)

六、Feign

1. 微服务之间如何进行通信

  1. **同步通信:**dubbo的rpc远程调用;springcloud的rest调用
  2. 异步通信:消息队列,如:RabbitMq、ActiveM、Kafka等消息队列。

2. 什么是Feign?

Feign是一个http客户端,可以帮助我们更便捷的调用HTTP API

  1. feign采用的是基于接口的注解
  2. feign整合了ribbon,具有负载均衡的能力
  3. 整合了Hystrix,具有熔断的能力

3. SpringCloud有几种调用接口方式

  1. RestTemplate
  2. FeignClient

4. feign和dubbo的区别?

  1. 协议:

  • **Dubbo:**支持多传输协议(Dubbo、Rmi、http等等),默认的Dubbo协议:利用NettyTCP传输

  • **Feign:**基于Http传输协议

  1. 负载均衡

  • Dubbo:

    • 支持4种算法(随机、轮询、活跃度、Hash一致性),而且算法里面引入权重的概念。
    • 配置的形式不仅支持代码配置,还支持Dubbo控制台灵活动态配置。
    • 负载均衡的算法可以精准到某个服务接口的某个方法。
  • Feign:

    • 支持7种策略:轮询、权重、随机、最小连接数等

    • 负载均衡算法是Client级别的。

  1. 容错机制方面:

  • Feign:默认使用Hystix作为服务熔断的组件。Hystix提供了服务降级,服务熔断,依赖隔离,监控(Hystrix Dashboard)等功能。Feign是利用熔断机制来实现容错的,与Dubbo处理的方式不一样。
  • Dubbo:支持多种容错策略,FailOver、FailFast、Failsafe、FailBack、Aviailable、Broadcast、Forking策略等,以及Mock。也引入了retry次数,timeout等配置参数。Dubbo自带了失败重试的功能。

七、Bus

1. 熟悉 Spring Cloud Bus 吗?

spring cloud bus 将分布式的节点用轻量的消息代理连接起来,它可以用于广播配置文件的更改或者服务直接的通讯,也可用于监控。如果修改了配置文件,发送一次请求,所有的客户端便会重新读取配置文件。

八、Spring Cloud Config

1. 了解Spring Cloud Config 吗?

在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件Spring Cloud Config,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。