Java面试题(14)- Spring Cloud

Java面试题(14)- Spring Cloud

1 Spring Cloud

1.1 你怎么描述Spring Cloud 框架?

  • Spring Cloud是一个微服务框架,将单体的应用程序分成多个应用程序,每个微服务运行在自己的进程中,并使用轻量级的机制通信。
  • Spring Cloud是一系列工具的集合,利用Spring Boot的开发便利性简化了分布式系统基础设施的开发,如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。

1.2 说说微服务架构的优缺点?

  • 优点

(1)易于开发和维护:微服务的粒度较小,可能一个或者几个模块就是一个微服务。我们就只需关心这个模块的逻辑即可,降低了代码量和逻辑复杂度。
(2)启动较快:相比于单体架构的整个项目,启动某个模块的服务速度明显快很多。
(3)容易部署:只要任何改动,单体架构都要重新发布整个项目,非常耗时间。但是微服务不同,只需要改动对应模块的服务即可,部署相对简单,不必重启整个项目。
(4)技术栈不受限:开发微服务只要遵循接口规范实现业务逻辑,不受任何语言限制,因此技术更换的成本小很多。

  • 缺点

(1)运维要求较高:单体架构的项目很少,维护难度较低。微服务架构项目由许多个微服务构成的,日志数量更大,消耗的机器也更多。项目之间互相调用,一旦某个项目出了问题,排查故障难度也更大。
(2)分布式的复杂性:微服务架构一定是分布式的。由于分布式本身的复杂性,微服务架构也变得复杂起来,需要用到服务注册、服务监控、熔断降级等许多组件。
(3)接口调整成本高:微服务之间互相调用,一旦某个微服务接口发生大的变动,所有依赖它的微服务都要做相应的调整。微服务可能非常多,那么调整接口所造成的成本会较高。

1.3 Spring Cloud有哪些重要组件?

(1)Spring Cloud Eureka:服务注册与发现
(2)Spring Cloud Gateway:服务网关
(3)Spring Cloud Ribbon:客户端负载均衡
(4)Spring Cloud Feign:声明性的Web服务客户端
(5)Spring Cloud Hystrix:断路器
(6)Spring Cloud Confifig:分布式配置管理

2 Eureka

2.1 Eureka的作用是什么?

Eureka是微服务中的注册中心,它有两个角色,一个服务端和客户端。服务端就是Eureka本身,客户端就是服务提供者和消费者,当服务提供者启动会将自己的信息注册到Eureka去,消费者启动会去注册中心拉取服务列表缓存到本地,消费者就可以远程调用服务提供者。客户端会与注册中心保持心跳来证明自己存活,每隔30s客户端会发送心跳给注册中心,默认情况下,每隔90s注册中心会检查是否有收到心跳,如果没有收到心跳会将客户端从服务列表剔除。

2.2 Eureka怎么实现高可用?

搭建至少3台Eureka服务,所有的微服务都注册在这些Eureka实例中。

2.3 什么是Eureka的自我保护模式?

如果Eureka Service在一定时间内没有接收到某个微服务的心跳,会进入自我保护模式。在该模式下Eureka Service会保护服务注册表中的信息,不在删除注册表中的数据,当网络故障恢复后,Eureka Servic 节点会自动退出自我保护模式。

2.4 Eureka和ZooKeeper都提供服务注册与发现的功能,区别是什么?

(1)ZooKeeper保证的是CP(一致性),Eureka保证的是AP(可用性)。
(2)Zookeeper在选举期间注册服务瘫痪不可用,而Eureka各个节点平等,只要一台就能保证服务可以,但查询到的数据不一定是最新的,可以很好的应对网络故障导致的部分节点失联。
(3)Zookeeper有header和follower角色,当header挂掉,会从剩下的follower里面选举一个header,Eureka各个节点平等。
(4)Zookeeper采用半数存活原则,Eureka采用自我保护机制来解决分区问题。

3 Gateway

3.1 Spring Cloud Gateway的作用是什么?

Spring Cloud Gateway整个微服务API请求的入口,负责拦截所有请求,分发到服务上去。可以实现日志拦截、权限控制、解决跨域问题、限流、熔断、负载均衡、隐藏服务端的ip、黑名单与白名单拦截、授权等功能。

3.2 网关与过滤器有什么区别?

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

3.3 你还了解其他网关吗,有什么区别?

Zuul:基于servlet实现的阻塞式的API,不支持长连接。Gateway底层是Netty方式实现的,性能比Zuul性能要好。
Nginx:Nginx也能实现对api接口的拦截、负载均衡、反向代理、请求过滤等功能,但是它是服务器级别的,Gateway是应用级别的。Nginx是流量网关,属于用户访问的一个入口。用户请求进来是先过Nginx网关,然后在进入到getway网关中。getway网关属于一个业务网关,通过对应的配置将请求传递到每一个业务微服务中去。

4 Ribbon

4.1 Ribbon的作用是什么?

Spring Cloud Ribbon是一个客户端负载均衡工具。主要功能是提供客户端的软件负载均衡算法和服务调用。简单的说,是在配置文件中列出Load Balancer后面所有的机器,Ribbon自动基于某种规则(如简单轮询、随机连接、权重等)去连接这些机器。

4.2 负载均衡的意义什么?

负载均衡的意义是指将负载的任务进行平衡、分摊到多个操作单元上进行运行,主要是用来避免单一应用由于并发等原因,导致应用宕机从而让系统整体无法使用、多负载同时工作,则使用负载均衡能够解决高并发的问题并实现服务的高可用。

4.3 Ribbon的实现原理是什么?

Ribbon属于客户端负载均衡器,客户端自己维护一份服务器的地址列表。Ribbon 会从 Eureka Server 读取服务信息列表。如果服务器宕机了,Ribbon 会从列表剔除宕机的服务器信息。Ribbon 有多种负载均衡算法,可以自行设定规则从而请求到指定的服务器。Ribbon 提供了几种常见的负载均衡策略:随机 (Random)、轮询 (RoundRobin)、一致性哈希 (ConsistentHash)、哈希 (Hash)、加权(Weighted)。

Ribbon 初始化的过程:
(1)Spring Boot 加载 Ribbon 的自动配置类 LoadBalancerAutoConfiguration。
(2)如果 RestTemplate 或者 AsyncRestTemplate 添加了注解,Ribbon 初始化时会收集加了@LoadBalanced 注解的 RestTemplate 和 AsyncRestTemplate ,把它们放到一个 List 里面。
(3)Ribbon 里面的 RestTemplateCustomizer 会给每个 RestTemplate 进行定制化,也就是加上了拦截器 LoadBalancerInterceptor。
(4)从 Eureka 注册中心获取服务列表,然后存到 Ribbon 中。
(5)加载 YMAL 配置文件,配置好负载均衡配置,创建一个 ILoadbalancer 接口实例。

Ribbon 拦截请求的原理 :
(1)Ribbon 拦截所有标注@loadBalance注解的 RestTemplate。将 默认的拦截器 LoadBalancerInterceptor 添加到 RestTemplate 的执行逻辑中,当 RestTemplate 每次发送 HTTP 请求时,都会被拦截。
(2)拦截后,Ribbon 会创建一个 ILoadBalancer 实例,ILoadBalancer 实例会使用 RibbonClientConfiguration 完成自动配置,就会配置好 IRule、IPing、ServerList三个接口实例。
IRule是负载均衡策略,IPing判定服务可用性,ServerList是可用服务列表。
(3)Ribbon 从服务列表中选择一个服务,按规则将请求转发给这个服务。

5 Hystrix

5.1 Hystrix的作用是什么?

在微服务架构中业务拆分成一个个的服务,服务与服务之间可以相互调用。为了保证其高可用,单个服务必须集群部署。由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟。此时若有大量的请求涌入,可能导致服务瘫痪。某个基础服务不可用造成整个系统不可用的情况, 这种现象被称为服务雪崩效应。Hystrix 用于解决微服务系统交互时超时处理和容错的工具库, 它拥有保护系统的能力。

5.2 服务雪崩的原因有哪些?

(1)机器故障:例如机器的硬驱动引起的错误,或者一些特定的机器上出现一些的bug(如内存中断或者死锁)。
(2)服务器负载发生变化:某些时候服务会因为用户行为造成请求无法及时处理从而导致雪崩,例如促销活动,若没有提前增加机器,可能会造服务器压力骤然增大而宕机。
(3)人为因素:开发人员的代码中出现的BUG。

5.3 在微服务中如何保护服务?

(1)熔断模式:这种模式主要是参考电路熔断,如果一条线路电压过高,保险丝会熔断,防止火灾。放到我们的系统中,如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。
(2)隔离模式:这种模式就像对系统请求按类型划分成一个个小岛的一样,当某个小岛被火烧光了,不会影响到其他的小岛。例如可以对不同类型的请求使用线程池来资源隔离,每种类型的请求互不影响,如果一种类型的请求线程资源耗尽,则对后续的该类型请求直接返回,不再调用后续资源。这种模式使用场景非常多,例如将一个服务拆开,对于重要的服务使用单独服务器来部署,再或者公司最近推广的多中心。
(3)限流模式:上述的熔断模式和隔离模式都属于出错后的容错处理机制,而限流模式则可以称为预防模式。限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。这种模式不能解决服务依赖的问题,只能解决系统整体资源分配问题,因为没有被限流的请求依然有可能造成雪崩效应。

5.4 通过Hystrix如何实现服务降级?

重写HystrixCommand中的getFallback()方法,当Hystrix的run方法或construct执行发生错误时转而执行getFallback()方法。

6 Feign

6.1 Feign的作用是什么?

Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端,用于实现微服务之间的声明式调用。

6.2 Spring Cloud有几种调用接口方式

  • RestTemplate调用

首先在入口函数里注入RestTemplate:

@SpringBootApplication
public class TestRestTemplateApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestRestTemplateApplication.class, args);
    }

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

在 test case里传入参数,调用RestTemplate:

@Autowired
private RestTemplate restTemplate;
@Test
public void queryOrder() {
    String orderId = "202212121221";
    String url = "http://micro_service_1/find?orderId=" + orderId;
    Order order = restTemplate.getForObject(url, List.class);
    System.out.println(order.toString());
  }
}
  • Feign调用

配置maven依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在调用者服务里定义 FeignClient 接口:

@FeignClient("micro_service_1")
public interface QueryOrderFeign {
    @RequestMapping(value = "/queryOrder", method = RequestMethod.GET)
    public Order queryOrder(@RequestParam String orderId);
}

在 test case里传入参数,调用 FeignClient:

@Autowired
private QueryOrderFeign queryOrderFeign;

@Test
public void queryOrder(String orderId) {
    String orderId = "202212121221";
    Order order = queryOrderFeign.queryOrder(orderId);
    System.out.println(order.toString());
}

6.3 Ribbon和Feign调用服务的区别?

(1)启动类注解不同,Ribbon使用的注解是@RibbonClient,而Feign使用注解是@EnableFeignClients。
(2)服务的指定位置不同,Ribbon的服务实在注解@RibbonClient中声明的,而Feign是在注解@FeignClient中声明的。
(3)调用方式不同,Ribbon需要自己构建HTTP请求来,使用RestTemplate将该请求发送出去。Feign在Ribbon的基础上进行封装,采用的是接口的方式,无需自己构建HTTP请求,只需将其他服务的方法定义成抽象方法即可。
(4)依赖不同,Ribbon的Maven依赖是spring-cloud-starter-netflix-ribbon;Feign的Maven依赖是spring-cloud-starter-openfeign。

7 Bus

7.1 什么是 Spring Cloud Bus?

Spring Cloud Bus Spring Cloud Bus 被称为消息总线,使用轻量级的消息代理来连接微服务架构中的各个服务,可以将其用于广播状态更改(例如配置中心配置更改)或其他管理指令。例如,Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。目前 Spring Cloud Bus 支持两种消息代理:RabbitMQ 和 Kafka。

7.2 Spring Cloud Bus 如何刷新配置?

Spring Cloud Bus提供了一个http接口 /bus/refresh。将这个接口配置到git的webhook上,当git上的内容发生改变时,就会自动调用/bus/refresh接口。Spring Cloud Bus就会通知Config Server发布更新消息到消息总线的消息队列,其他服务订阅到该消息就会信息刷新,从而实现整个微服务进行自动刷新。

8 Config

8.1 Spring Cloud Config有什么用处?

Spring Cloud Config 为微服务架构中的应用提供集中化的外部配置支持,它分为服务端和客户端两个部分。服务端被称为分布式配置中心,它是个独立的应用,可以从配置仓库获取配置信息并提供给客户端使用。客户端可以通过配置中心来获取配置信息,在启动时加载配置。配置中心默认采用Git来存储配置信息,可以使用Git客户端来方便地管理和访问配置信息。

8.2 还有哪些成熟的分布式配置中心?

携程Apollo、百度Disconf、Alibaba Nacos。

参考(摘抄的文字版权属于原作者)
https://zhuanlan.zhihu.com/p/574974504
https://zhuanlan.zhihu.com/p/406311277
https://www.cnblogs.com/dingpeng9055/p/16404777.html
https://www.cnblogs.com/xyhero/p/53852cf0245c229fe3e22756a220508b.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注