【Java】面试常问知识点(Java基础—springboot框架)

Spring Boot

启动流程

springboot启动流程主要分为三个部分:

第一部分进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器,

第二部分实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块,

第三部分是自动化配置模块,该模块作为springboot自动配置核心,在后面的分析中会详细讨论。在下面的启动程序中我们会串联起结构中的主要功能。

具体如下:

每个SpringBoot程序都有一个主入口,也就是main方法,main里面调用SpringApplication.run()启动整个spring-boot程序,该方法所在类需要使用@SpringBootApplication注解,以及@ImportResource注解(if need),

@SpringBootApplication包括三个注解,功能如下:

@EnableAutoConfiguration:SpringBoot根据应用所声明的依赖来对Spring框架进行自动配置

@SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的XML配置文件中(applicationContext.xml),装配所有bean事务,提供了一个spring的上下文环境

@ComponentScan:组件扫描,可自动发现和装配Bean,默认扫描SpringApplication的run方法里的Booter.class所在的包路径下文件,所以最好将该启动类放到根包路径下

springboot自动装配原理

1、main方法中SpringApplication.run(HelloBoot.class,args)的执行流程中有refreshContext(context)。

2、而这个refreshContext(context)内部会解析,配置类上自动装配功能的注解@EnableAutoConfiguration中的,@EnableAutoConfiguration中的,引入类AutoConfigurationImportSelector。

3、AutoConfigurationImportSelector这个类中的方法SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()会读取jar包中的/项目中的META-INF/spring.factories文件。

4、spring.factories配置了自动装配的类,最后根据配置类的条件,自动装配Bean。

springboot所有的自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入对应的start,就有对应的启动器,有了启动器,我们的自动配置就会生效,然后配置成功。

run启动流程

1.SpringApplication实例初始化: a)、根据classpath里面是否存在特征类(org.springframework.web.context.ConfigurableWebApplicationCobtext)来决定创建为web应用使用ApplicationContext类型,还是标准Standalone应用使用的ApplicationContext类型。 b)、使用SpringFactoriesLoader在classpath中查找并加载所有可用的ApplicationContextInitiazier c)、使用SpringFactoriesLoader在classpath中查找并加载所有可用的ApplicationListener d)、推断并main方法的定义类

2.SpringApplication实例初始化完成,遍历SpringFactoriesLoader可以找到并加载的SpringApplicationRunListnner,调用他们的start()方法。

3.创建并配置当前SpringBoot应用将要使用的Envrioment(包括配置要使用的PropertySource以及Profile)

4.遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法——即通知【run监听器SpringBoot应用的使用环境已经搭建完成】

5.创建对应类型的ApplicationContext,根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator、ResourceLoader。将之前准备好的Enviroment设置给创建好的ApplicationContext使用

6.完成创建ApplicationContext,通过SpringFactoriesLoader查找并加载classpath中所有可用的ApplicationContextInitializer的Initialize()方法来对ApplicationContext进行进一步的处理

7.遍历所有的SpringApplicationRunListenner的contextPrepared()方法,通知【run监听器】ApplicationContext已经准备好了。

8.将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IOC容器配置加载到已经准备完毕的ApplicationContext

9.遍历所有的SpringApplicationRunListener的contextLoaded()方法,通知【run监听器和ApplicationContext装填完毕】

10.调用ApplicationContext的refresh()——完成填充IOC容器

11.查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。

12.遍历执行SpringApplicationRunListener的finished()。——启动完毕

常用注解

@SpringBootApplication 是一个三合一的注解 @SpringBootConfiguration :该注解功能和@Configuration注解类似,用于修饰一个配置类,以启动基于Java的配置。 @EnableAutoConfiguration :注解用于启用自动配置,以省去繁琐的手动配置。 @ComponentScan :该注解用于启用组件扫描,这样你创建的控制器和其他组件将自动被发现并注册为Spring应用程序上下文中的bean。

创建REST API 需要使用SpringMVC提供的一些注解,包括@PostMapping、@DeleteMapping、@PutMapping、@GetMapping分别对应增删改查

消息队列

消息队列:

点对点模型(Point-to-Point,P2P)

发布/订阅模型(Publish/Subscribe,Pub/Sub)

1.点对点消息传递域的特点如下:

a.每个消息只能有一个消费者

b.消息的生产者和消费者之间没有时间上的相关性。无论消费者在生产者发送消息的时候是否处于运行状态,它都可以提取消息。

2.发布/订阅消息传递域的特点如下:

a.每个消息可以有多个消费者

b.生产者和消费者之间有时间上的相关性。订阅一个主题的消费者只能消费自它订阅之后发布的消息。JMS规范允许客户创建持久订阅,这在一定程度上放松了时间上的相关性要求。持久订阅允许消费者消费它在未处于激活状态时发送的消息。

3.在点对点消息传递域中,目的地被称为队列(queue);在发布/订阅消息传递域中,目的地被称为主题(topic)

执行步骤:

1.启动ActiveMQ服务

2.创建客户端程序

3.添加ActiveMQ启动依赖

4.配置ActiveMQ属性

5.编写消息发送程序

6.编写消息接收程序

7.测试发送和接收消息

怎么解决重复消息问题

一般解决重复消息的办法是,在消费端,让我们消费消息的操作具备幂等性。所谓幂等性,就是数据无论操作多少次,所产生的影响跟执行一次是一样的,比如对于读操作来说,无论读取多少次数据,都跟读取一次的数据是一样的,所以读操作是一个幂等性操作,而添加操作,添加多次会有多条记录,因而写操作则是非幂等性操作。因而对于以上场景,只要保证消息消费的幂等性,就能解决重复消费的问题。

几种常用的设计幂等操作的方法:

  1. 利用数据库的唯一约束实现幂等
  2. 为更新的数据设置前置条件,给数据变更设置一个前置条件,如果满足条件就更新数据,否则拒绝更新数据,在更新数据的时候,同时变更前置条件中需要判断的数据。这样,重复执行这个操作时,由于第一次更新数据的时候已经变更了前置条件中需要判断的数据,不满足前置条件,则不会重复执行更新数据操作。
  3. 记录并检查操作(通用性最强,适用范围最广的实现幂等性方法):记录并检查操作,也称为“Token 机制或者 GUID(全局唯一 ID)机制”,实现的思路特别简单:在执行数据更新操作之前,先检查一下是否执行过这个更新操作。

具体的实现方法是,在发送消息时,给每条消息指定一个全局唯一的 ID,消费时,先根据这个 ID 检查这条消息是否有被消费过,如果没有消费过,才更新数据,然后将消费状态置为已消费。弊端:在分布式系统中,这个方法其实是非常难实现的。首先,给每个消息指定一个全局唯一的 ID ,方法有很多,但都不太好同时满足简单、高可用和高性能,或多或少都要有些牺牲。更加麻烦的是,在“检查消费状态,然后更新数据并且设置消费状态”中,三个操作必须作为一组操作保证原子性,才能真正实现幂等,否则就会出现 Bug。

具体实现幂等旭根据当下业务来过相关的处理,根据实际业务确认需要那种场景来实现幂等。

接口幂等性

接口幂等性就是用户对同一操作发起了一次或多次请求的对数据的影响是一致不变的,不会因为多次的请求而产生副作用。

副作用:可以认为多次请求操作,每一次对数据状态都会产生影响 。 注意这里并没有要求接口返回结果是一致的。

例如:update order set moeny = 100 where orderId = 2029282312 该操作无论执行多少次,对数据的影响都是一致的,不变的。

token+redis 机制

比如订单支付场景:

该支付分为两个步骤:

1.1 获取全局唯一token

  接口处理生成唯一标识(token) 存储到redis中,并返回给调用客户端。

1.2 发起支付操作并附带token

  接口处理:

  1.2.1 获得分布式锁(处理并发情况)

  1.2.2 判断redis中是否存在token

  1.2.3 存在 执行支付业务逻辑,否则返回该订单已经支付

  1.2.4 释放分布式锁

思考:为什么要加分布式锁?

原因1:在高并发请求中 ,token判断是否存在是非线程安全的,所以要加分布式锁来保证 该条件的判断为线程安全

注释:也可redis用删除操作来判断token,删除成功代表token校验通过 这个删除是原子操作的

原因2:在支付业务中,判断支付订单是否已经存在,存在说明该订单已经支付过了,不存在就执行扣款操作,如果相同操作并发两个请求来到判断条件可能两个请求都能判断支付订单不存在,造成重复扣款。 所以也要加分布式锁保证线程的安全。

分布式锁实现方法

一、基于数据库实现分布式锁

1、悲观锁

利用select … where … for update 排他锁。

注意:其他附加功能与实现一基本一致,这里需要注意的是“where name=lock ”,name字段必须要走索引,否则会锁表。有些情况下,比如表不大,mysql优化器会不走这个索引,导致锁表问题。

2、乐观锁

所谓乐观锁与前边最大区别在于基于CAS思想,是不具有互斥性,不会产生锁等待而消耗资源,操作过程中认为不存在并发冲突,只有update version失败后才能觉察到,抢购和秒杀就是用了这种实现以防止超卖,通过增加递增的版本号字段实现乐观锁。

二、基于缓存(Redis等)实现分布式锁

1、使用命令介绍:

(1)SETNX

SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。

(2)expire

expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。

(3)delete

delete key:删除key

在使用Redis实现分布式锁的时候,主要就会使用到这三个命令。

2、实现思想:

(1)获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。

(2)获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。

(3)释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放。

三、基于Zookeeper实现分布式锁

ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名。

基于ZooKeeper实现分布式锁的步骤如下:

(1)创建一个目录mylock。

(2)线程A想获取锁就在mylock目录下创建临时顺序节点。

(3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁。

(4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点。

(5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。

SpringCloud

分布式的CAP原则

CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。

CAP原则是NOSQL数据库的基石。

一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本) 可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性) 分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。

Eureka(保证AP),Zookeeper(保证CP)

Eureka和zookeeper的对比

作为分布式服务注册中心,Eureka比Zookeeper好在哪里?

著名的CAP理论指出,一个分布式系统不可能同时满足C (一致性) 、A (可用性) 、P (容错性),由于分区容错性P再分布式系统中是必须要保证的,因此我们只能再A和C之间进行权衡。

Zookeeper 保证的是 CP —> 满足一致性,分区容错的系统,通常性能不是特别高 Eureka 保证的是 AP —> 满足可用性,分区容错的系统,通常可能对一致性要求低一些 Zookeeper保证的是CP

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

Eureka保证的是AP

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

Eureka不在从注册列表中移除因为长时间没收到心跳而应该过期的服务 Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上 (即保证当前节点依然可用) 当网络稳定时,当前实例新的注册信息会被同步到其他节点中 因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪

restful和rpc

RPC框架包含4个核心的组件,分别是Client ,Server,Client Stub以及Server Stub,这个Stub大家可以理解为存根

客户端(Client),服务的调用方。 服务端(Server),真正的服务提供者。 客户端存根,存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。 服务端存根,接收客户端发送过来的消息,将消息解包,并调用本地的方法 RPC框架要做到最基本的3件事情:

1)服务端如何确定客户端要调用的函数;

在远程调用中,客户端和服务端分别维护一个【ID->函数】的对应表, ID在所有进程中都是唯一确定的。客户端在做远程过程调用时,附上这个ID,服务端通过查表,来确定客户端需要调用的函数,然后执行相应函数的代码。

2)如何进行序列化和反序列化;

客户端和服务端交互时将参数或结果转化为字节流在网络中传输,那么数据转化为字节流的或者将字节流转换成能读取的固定格式时就需要进行序列化和反序列化,序列化和反序列化的速度也会影响远程调用的效率。

3)如何进行网络传输

多数RPC框架选择TCP作为传输协议,也有部分选择HTTP。如gRPC使用HTTP2。不同的协议各有利弊。TCP更加高效,而HTTP在实际应用中更加的灵活

rest和rpc对比

比较 rest rpc 通行协议 http tcp/udp 性能 低 高 灵活度 高 低 REST与RPC应用场景

REST和RPC都常用于微服务架构中。

1)HTTP相对更规范,更标准,更通用,无论哪种语言都支持http协议。如果你是对外开放API,例如开放平台,外部的编程语言多种多样,你无法拒绝对每种语言的支持,现在开源中间件,基本最先支持的几个协议都包含RESTful。

2)RPC 框架作为架构微服务化的基础组件,它能大大降低架构微服务化的成本,提高调用方与服务提供方的研发效率,屏蔽跨进程调用函数(服务)的各类复杂细节。让调用方感觉就像调用本地函数一样调用远端函数、让服务提供方感觉就像实现一个本地函数一样来实现服务

流行的rpc框架和rest框架

rpc:dubbo+zookeeper(注册中心)

rest:Eureka是Netflix的一个子模块,也是核心模块之一。 Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了。 功能类似于dubbo的注册中心,比如Zookeeper。

nacos

nacos和eureka都是注册中心,都具有各自的负载均衡策略,eureka分为Eureka Server(Eureka服务)和Eureka Client(Eureka客户端),所有Eureka Server 通过Replicate进行数据同步。无论Eureka Client向哪个Eureka Server中注册信息,最终所有Eureka Server中都会存储注册的信息,这些信息都缓存到Eureka Server的本地。 Eureka Client向Eureka Server注册信息的时候我们称它为服务提供者,当获取注册的信息时称为服务消费者,所以很多Eureka Client既是服务提供者,又是服务消费者。 服务提供者在启动后,每隔30秒向Eureka Server发送一次心跳,以证明自己的可用。当Eureka Server超过90秒没有收到提供者的心跳后,会认为这个提供者已经宕机,销毁实例。Nacos有自己的配置中心,Eureka需要配合config实现配置中心,且不提供管理界面,nacos是动态刷新的,它采用Netty保持长连接实时推送,eureka需要配合MQ实现配置动态刷新 阿里的nacos : 性能最好 他同时支持AP和CP模式,他根据服务注册选择临时和永久来决定走AP模式还是CP模式 eureka: 可以做注册中心,完全AP,支持注册中心之间的节点复制,同时支持服务端同时注册多个注册中心节点,所以不存节点信息不一致的情况

gateway(网关)

特点:

基于 Spring Framework 5、Project Reactor 和 Spring Boot 2.0 构建

能够匹配任何请求属性的路由。

谓词和过滤器特定于路由。

断路器集成。

Spring Cloud Discovery客户端集成

易于编写谓词和过滤器

请求速率限制

路径重写

作用:路由和过滤

service registry(服务注册中心)

常用的:Eureka,zookeeper还有现在的nacos,

eureka用的主要ap,zookeeper则是cp,nacos同时支持ap和cp

config(配置)

Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可以在所有环境中管理应用程序的外部属性。客户端和服务器上的概念映射与Spring Environment和PropertySource抽象相同,因此它们与Spring应用程序非常契合,但可以与任何以任何语言运行的应用程序一起使用。随着应用程序通过从开发人员到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。很容易添加替代实现,并使用Spring配置将其插入。

@EnableConfigServer //开启配置

这里注意,bootstrap.yml 是系统级别的配置,application.yml 是用户级别的配置

作用:

集中式管理配置文件 不同环境,不同配置,动态化的配置更新,分环境部署,比如 /dev /test /prod /beta /release 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息 当配置发生变动时,服务不需要重启,即可感知到配置的变化,并应用新的配置 将配置信息以REST接口的形式暴露

Hystrix(熔断器)

复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免失败!

多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用响应时间过长,或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几十秒内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以达到单个依赖关系的失败而不影响整个应用程序或系统运行。

我们需要,弃车保帅!

Hystrix是一个应用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix 能够保证在一个依赖出问题的情况下,不会导致整个体系服务失败,避免级联故障,以提高分布式系统的弹性。

“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控 (类似熔断保险丝) ,向调用方返回一个服务预期的,可处理的备选响应 (FallBack) ,而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

Hystrix能干嘛?

服务降级 服务熔断 服务限流 接近实时的监控 服务降级、服务熔断和监控

熔断机制是赌赢雪崩效应的一种微服务链路保护机制。

当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阀值缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是:@HystrixCommand。

服务熔断解决如下问题:

当所依赖的对象不稳定时,能够起到快速失败的目的;

快速失败后,能够根据一定的算法动态试探所依赖对象是否恢复。

因此,为了避免因某个微服务后台出现异常或错误而导致整个应用或网页报错,使用熔断是必要的

服务降级

什么是服务降级?

服务降级是指 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理,或换种简单的方式处理,从而释放服务器资源以保证核心业务正常运作或高效运作。说白了,就是尽可能的把系统资源让给优先级高的服务。

资源有限,而请求是无限的。如果在并发高峰期,不做服务降级处理,一方面肯定会影响整体服务的性能,严重的话可能会导致宕机某些重要的服务不可用。所以,一般在高峰期,为了保证核心功能服务的可用性,都要对某些服务降级处理。比如当双11活动时,把交易无关的服务统统降级,如查看蚂蚁深林,查看历史订单等等。

服务降级主要用于什么场景呢?当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。

降级的方式可以根据业务来,可以延迟服务,比如延迟给用户增加积分,只是放到一个缓存中,等服务平稳之后再执行 ;或者在粒度范围内关闭服务,比如关闭相关文章的推荐。

服务降级需要考虑的问题

1)那些服务是核心服务,哪些服务是非核心服务 2)那些服务可以支持降级,那些服务不能支持降级,降级策略是什么 3)除服务降级之外是否存在更复杂的业务放通场景,策略是什么? 自动降级分类

1)超时降级:主要配置好超时时间和超时重试次数和机制,并使用异步机制探测回复情况

2)失败次数降级:主要是一些不稳定的api,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况

3)故障降级:比如要调用的远程服务挂掉了(网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常),则可以直接降级。降级后的处理方案有:默认值(比如库存服务挂了,返回默认现货)、兜底数据(比如广告挂了,返回提前准备好的一些静态页面)、缓存(之前暂存的一些缓存数据)

4)限流降级:秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。

服务熔断和降级的区别

服务熔断—>服务端:某个服务超时或异常,引起熔断~,类似于保险丝(自我熔断) 服务降级—>客户端:从整体网站请求负载考虑,当某个服务熔断或者关闭之后,服务将不再被调用,此时在客户端,我们可以准备一个 FallBackFactory ,返回一个默认的值(缺省值)。会导致整体的服务下降,但是好歹能用,比直接挂掉强。 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始) 实现方式不太一样,服务降级具有代码侵入性(由控制器完成/或自动降级),熔断一般称为自我熔断。 熔断,降级,限流:

限流:限制并发的请求访问量,超过阈值则拒绝;

降级:服务分优先级,牺牲非核心服务(不可用),保证核心服务稳定;从整体负荷考虑;

熔断:依赖的下游服务故障触发熔断,避免引发本系统崩溃;系统自动执行和恢复

Dashboard 流监控

负载均衡(ribbon和feign)

ribbon

Spring Cloud Ribbon 是基于Netflix Ribbon 实现的一套客户端负载均衡的工具。 简单的说,Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon 的客户端组件提供一系列完整的配置项,如:连接超时、重试等。简单的说,就是在配置文件中列出 LoadBalancer (简称LB:负载均衡) 后面所有的及其,Ribbon 会自动的帮助你基于某种规则 (如简单轮询,随机连接等等) 去连接这些机器。我们也容易使用 Ribbon 实现自定义的负载均衡算法! ribbon能干什么?

LB,即负载均衡 (LoadBalancer) ,在微服务或分布式集群中经常用的一种应用。 负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA (高用)。 常见的负载均衡软件有 Nginx、Lvs 等等。 Dubbo、SpringCloud 中均给我们提供了负载均衡,SpringCloud 的负载均衡算法可以自定义。 负载均衡简单分类:

集中式LB

即在服务的提供方和消费方之间使用独立的LB设施,如Nginx(反向代理服务器),由该设施负责把访问请求通过某种策略转发至服务的提供方! 进程式 LB

将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选出一个合适的服务器。 Ribbon 就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址! Feign简介

Feign是声明式Web Service客户端,它让微服务之间的调用变得更简单,类似controller调用service。SpringCloud集成了Ribbon和Eureka,可以使用Feigin提供负载均衡的http客户端

只需要创建一个接口,然后添加注解即可~

Feign,主要是社区版,大家都习惯面向接口编程。这个是很多开发人员的规范。调用微服务访问两种方法

微服务名字 【ribbon】 接口和注解 【feign】 Feign能干什么?

Feign旨在使编写Java Http客户端变得更容易 前面在使用Ribbon + RestTemplate时,利用RestTemplate对Http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一个客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步的封装,由他来帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它 (类似以前Dao接口上标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解),即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon 时,自动封装服务调用客户端的开发量。 Feign默认集成了Ribbon

利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。 Feign和Ribbon如何选择?

根据个人习惯而定,如果喜欢REST风格使用Ribbon;如果喜欢社区版的面向接口风格使用Feign.

你可能感兴趣的:(java,spring,boot,面试)