本文是技术人面试系列SpringCloud篇,面试中关于SpringCloud都需要了解哪些基础?一文带你详细了解,欢迎收藏!
Spring cloud 是一系列框架的有序集合。它利用 spring boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如
服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控
等,都可以用 spring boot 的开发风格做到一键启动和部署。
SpringBoot是Spring推出用于解决传统框架配置文件冗余,装配组件繁杂的基于Maven的解决方案,
旨在快速搭建单个微服务
,SpringCloud是依赖于SpringBoot的,而SpringBoot并不是依赖与SpringCloud,甚至还可以和Dubbo进行优秀的整合开发。
MartinFlower 提出的微服务之间是通过RestFulApi进行通信,具体实现:
Spring Boot 通过
简单的步骤
就可以创建一个 Spring 应用。
Spring Boot 为 Spring 整合第三方框架提供了
开箱即用功能
。
Spring Boot 的核心思想是
约定大于配置
。
-
搭建后端框架时需要手动添加 Maven 配置,涉及很多 XML 配置文件,增加了搭建难度和时间成本。
-
将项目编译成 war 包,部署到 Tomcat 中,项目部署依赖 Tomcat,这样非常不方便。
-
应用监控做的比较简单,通常都是通过一个没有任何逻辑的接口来判断应用的存活状态。
自动装配:
Spring Boot 会根据某些规则对所有配置的 Bean 进行初始化。可以减少了很多重复性的工作。
比如使用 MongoDB 时,只需加入 MongoDB 的 Starter 包,然后配置 的连接信息,就可以直接使用 MongoTemplate 自动装配来操作数据库了。简化了 Maven Jar 包的依赖,降低了烦琐配置的出错几率。
内嵌容器:
Spring Boot 应用程序可以不用部署到外部容器中,比如 Tomcat。
应用程序可以直接通过 Maven 命令编译成可执行的 jar 包,通过 java-jar 命令启动即可,非常方便。
应用监控:
Spring Boot 中自带监控功能 Actuator,可以实现对程序内部运行情况进行监控。
比如 Bean 加载情况、环境变量、日志信息、线程信息等。当然也可以自定义跟业务相关的监控,通过Actuator 的端点信息进行暴露。
spring-boot-starter-web //用于快速构建基于 Spring MVC 的 Web 项目。spring-boot-starter-data-redis //用于快速整合并操作 Redis。spring-boot-starter-data-mongodb //用于对 MongoDB 的集成。spring-boot-starter-data-jpa //用于操作 MySQL。
-
创建 Starter 项目,定义 Starter 需要的配置(Properties)类,比如数据库的连接信息;
-
编写自动配置类,自动配置类就是获取配置,根据配置来自动装配 Bean;
-
编写 spring.factories 文件加载自动配置类,Spring 启动的时候会扫描 spring.factories 文件;
-
编写配置提示文件 spring-configuration-metadata.json(不是必须的),在添加配置的时候,我们想要知道具体的配置项是什么作用,可以通过编写提示文件来提示;
-
在项目中引入自定义 Starter 的 Maven 依赖,增加配置值后即可使用。
Spring Boot Admin
(将 actuator 提供的数据进行可视化)
-
显示应用程序的监控状态、查看 JVM 和线程信息
-
应用程序上下线监控
-
可视化的查看日志、动态切换日志级别
-
HTTP 请求信息跟踪等实用功能
GateWay⽬标是取代Netflflix Zuul,它基于Spring5.0+SpringBoot2.0+WebFlux等技术开发,提供
统⼀的路由
⽅式(反向代理)并且基于
Filter
(定义过滤器对请求过滤,完成⼀些功能) 链的⽅式提供了⽹关基本的功能,例如:鉴权、流量控制、熔断、路径重写、⽇志监控。
-
路由route:
⽹关最基础的⼯作单元。路由由⼀个ID、⼀个⽬标URL、⼀系列的断⾔(匹配条件判断)和Filter过滤器组成。如果断⾔为true,则匹配该路由。
-
断⾔predicates:
参考了Java8中的断⾔Predicate,匹配Http请求中的所有内容(类似于nginx中的location匹配⼀样),如果断⾔与请求相匹配则路由。
-
过滤器filter:
标准的Spring webFilter,使⽤过滤器在请求之前或者之后执⾏业务逻辑。
请求前
pre
类型过滤器:做
参数校验、权限校验、流量监控、⽇志输出、协议转换等;
请求前
post
类型的过滤器:做
响应内容、响应头
的修改、
⽇志的输出、流量监控
等。
GateWayFilter
应⽤到单个路由路由上 、
GlobalFilter
应⽤到所有的路由上。
服务注册中⼼本质上是为了解耦服务提供者和服务消费者,为了⽀持弹性扩缩容特性,⼀个微服务的提供者的数量和分布往往是动态变化的。
Eureka
通过
⼼跳检测、健康检查
和
客户端缓存
等机制,提⾼系统的灵活性、可伸缩性和可⽤性。
-
us-east-1c、us-east-1d,us-east-1e代表不同的机房,
每⼀个Eureka Server都是⼀个集群;
-
Service作为服务提供者向Eureka中注册服务,Eureka接受到注册事件会在
集群和分区中进⾏数据同步
,Client作为消费端(服务消费者)可以从Eureka中获取到服务注册信息,进⾏服务调⽤;
-
微服务启动后,会周期性地向Eureka
发送⼼跳
(默认周期为30秒)以续约⾃⼰的信息;
-
Eureka在⼀定时间内
(默认90秒)没有接收到
某个微服务节点的⼼跳,Eureka将会注销该微服务节点;
-
Eureka Client
会缓存Eureka Server中的信息
。即使所有的Eureka Server节点都宕掉,服务消费者依然可以使⽤缓存中的信息找到服务提供者;
新服务上线后,服务消费者不能立即访问到刚上线的新服务,需要过⼀段时间后才能访问?或是将服务下线后,服务还是会被调⽤到,⼀段时候后才彻底停⽌服务,访问前期会导致频繁报错!
服务注册到注册中⼼后,服务实例信息是
存储在Registry表
中的,也就是内存中。但Eureka为了提⾼响应速度,在内部做了优化,加⼊了两层的缓存结构,将Client需要的实例信息,直接缓存起来,获取的时候直接从缓存中拿数据然后响应给 Client。
-
第⼀层缓存是
readOnlyCacheMap
,采⽤
ConcurrentHashMap
来存储数据的,主要负责定时与readWriteCacheMap进⾏数据同步,默认同步时间为
30
秒⼀次。
-
第⼆层缓存是
readWriteCacheMap
,采⽤
Guava
来实现缓存。缓存过期时间默认为
180
秒,当服务
下线、过期、注册、状态变更
等操作都会清除此缓存中的数据。
-
如果两级缓存都无法查询,会
触发缓存的加载
,从存储层拉取数据到缓存中,然后再返回给 Client。
Eureka之所以设计⼆级缓存机制,也是为了
提⾼ Eureka Server 的响应速度,缺点是缓存会导致 Client获取不到最新的服务实例信息
,然后导致⽆法快速发现新的服务和已下线的服务。
-
期望最小每分钟能够续租的次数(实例* 频率 * 比例==10* 2 *0.85)
-
期望的服务实例数量(10)
-
Feign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡;
-
Feign 可以与 Hystrix 组合使用,支持熔断回退;
-
Feign 可以与ProtoBuf实现快速的RPC调用;
-
InvocationHandlerFactory 代理
采用 JDK 的动态代理方式生成代理对象,当我们调用这个接口,实际上是要去调用远程的 HTTP API;
-
Contract 契约组件
比如请求类型是 GET 还是 POST,请求的 URI 是什么;
-
Encoder 编码组件 \ Decoder 解码组件
通过该组件我们可以将请求信息采用指定的编码方式进行编解码后传输;
-
Logger 日志记录
负责 Feign 中记录日志的,可以指定 Logger 的级别以及自定义日志的输出;
-
Client 请求执行组件
负责 HTTP 请求执行的组件,Feign 中默认的 Client 是通过 JDK 的 HttpURLConnection 来发起请求的,在每次发送请求的时候,都会创建新的 HttpURLConnection 链接,Feign 的性能会很差,可以通过扩展该接口,使用 Apache HttpClient 等基于连接池的高性能 HTTP 客户端。
-
Retryer 重试组件
负责重试的组件,Feign 内置了重试器,当 HTTP 请求出现 IO 异常时,Feign 会限定一个最大重试次数来进行重试操作。
-
RequestInterceptor 请求拦截器
可以为 Feign 添加多个拦截器,在请求执行前设置一些扩展的参数信息。
-
继承特性
-
拦截器
比如添加指定的请求头信息,这个可以用在服务间传递某些信息的时候。
-
GET 请求多参数传递
-
日志配置
FULL 会输出全部完整的请求信息。
-
异常解码器
异常解码器中可以获取异常信息,而不是简单的一个code,然后转换成对应的异常对象返回。
-
源码查看是如何继承Hystrix
HystrixFeign.builder 中可以看到继承了 Feign 的 Builder,增加了 Hystrix的SetterFactory, build 方法里,对 invocationHandlerFactory 进行了重写, create 的时候
返回HystrixInvocationHandler
, 在 invoke 的时候
会将请求包装成 HystrixCommand 去执行
,这里就自然的集成了 Hystrix。
-
RoundRobinRule 是
轮询的算法
,A和B轮流选择。
-
RandomRule 是
随机算法
,这个就比较简单了,在服务列表中随机选取。
-
BestAvailableRule 选择一个
最小的并发请求 server。
-
灰度发布
灰度发布是能够平滑过渡的一种发布方式,在发布过程中,先发布一部分应用,让指定的用户使用刚发布的应用,等到测试没有问题后,再将其他的全部应用发布。如果新发布的有问题,只需要将这部分恢复即可,不用恢复所有的应用。
-
多版本隔离
多版本隔离跟灰度发布类似,为了兼容或者过度,某些应用会有多个版本,这个时候如何保证 1.0 版本的客户端不会调用到 1.1 版本的服务,就是我们需要考虑的问题。
-
故障隔离
当线上某个实例发生故障后,为了不影响用户,我们一般都会先留存证据,比如:线程信息、JVM 信息等,然后将这个实例重启或直接停止。然后线下根据一些信息分析故障原因,如果我能做到故障隔离,就可以直接将出问题的实例隔离,不让正常的用户请求访问到这个出问题的实例,只让指定的用户访问,这样就可以单独用特定的用户来对这个出问题的实例进行测试、故障分析等。
自己即是服务消费者,同时也是服务提供者,同步调用等待结果导致资源耗尽。
消费方:使用Hystrix资源隔离,熔断降级,快速失败;
-
封装请求
会将用户的操作进行统一封装,统一封装的目的在于进行统一控制。
-
资源隔离限流
会将对应的资源按照指定的类型进行隔离,比如
线程池
和
信号量
。
-
计数器限流,例如5秒内技术1000请求,超数后限流,未超数重新计数;
-
滑动窗口限流,解决计数器不够精确的问题,把一个窗口拆分多滚动窗口;
-
令牌桶限流,类似景区售票,售票的速度是固定的,拿到令牌才能去处理请求;
-
漏桶限流,生产者消费者模型,实现了恒定速度处理请求,能够绝对防止突发流量;
-
失败回退
其实是一个备用的方案,就是说当请求失败后,有没有备用方案来满足这个请求的需求。
-
断路器
这个是
最核心
的,,如果断路器处于打开的状态,那么所有请求都将失败,执行回退逻辑。如果断路器处于关闭状态,那么请求将会被正常执行。有些场景我们需要手动打开断路器强制降级。
-
指标监控
会对请求的
生命周期进行监控
,请求成功、失败、超时、拒绝等状态,都会被监控起来。
-
配置可以对接
配置中心
进行动态调整
Hystrix 的配置项非常多,如果不对接配置中心,所有的配置只能在代码里修改,在集群部署的难以应对紧急情况,我们项目只设置一个 CommandKey,其他的都在配置中心进行指定,紧急情况如需隔离部分请求时,只需在配置中心进行修改以后,强制更新即可。
-
回退逻辑中可以
手动埋点
或者通过
输出日志
进行告警
当请求失败或者超时,会执行回退逻辑,如果有大量的回退,则证明某些服务出问题了,这个时候我们可以在回退的逻辑中进行埋点操作,上报数据给监控系统,也可以输出回退的日志,统一由日志收集的程序去进行处理,这些方式都可以将问题暴露出去,然后通过实时数据分析进行告警操作。
-
用
ThreadLocal
配合
线程池隔离
模式需当心
当我们用了线程池隔离模式的时候,被隔离的方法会包装成一个 Command 丢入到独立的线程池中进行执行,这个时候就是从 A 线程切换到了 B 线程,ThreadLocal 的数据就会丢失。
-
Gateway中
多用信号量隔离
网关是所有请求的入口,路由的服务数量会很多,几十个到上百个都有可能,如果用线程池隔离,那么需要创建上百个独立的线程池,开销太大,用信号量隔离开销就小很多,还能起到限流的作用。
[^常见问题]: Hystrix的超时时间要⼤于Ribbon的超时时间,因为Hystrix将请求包装了起来,特别需要注意的是,如果Ribbon开启了重试机制,⽐如重试3 次,Ribbon 的超时为 1 秒,那么Hystrix 的超时时间应该⼤于 3 秒,否则就会出现 Ribbon 还在重试中,⽽ Hystrix 已经超时的现象。
Sentinel是⼀个⾯向云原⽣微服务的流量控制、熔断降级组件。
替代Hystrix,针对问题:服务雪崩、服务降级、服务熔断、服务限流
丰富的应⽤场景:
Sentinel 承接了阿⾥巴巴近 10 年的双⼗⼀⼤促流量的核⼼场景,例如秒杀、消息削峰填⾕、集群流量控制、实时熔断下游不可⽤应⽤等。
完备的实时监控:
可以看到500 台以下规模的集群的汇总也可以看到单机的秒级数据。
⼴泛的开源⽣态:
与 SpringCloud、Dubbo的整合。您只需要引⼊相应的依赖并进⾏简单的配置即可快速地接⼊ Sentinel。
Nacos是阿⾥巴巴开源的⼀个针对微服务架构中
服务发现、配置管理
和
服务管理平台
。
Nacos就是
注册中⼼+配置中⼼
的组合(Nacos=Eureka+Confifig+Bus)
当服务A健康实例数/总实例数 < 保护阈值 的时候,说明健康实例真的不多了,这个时候保护阈值会被触发(状态true),nacos将会把该服务所有的实例信息(健康的+不健康的)全部提供给消费者,消费者可能访问到不健康的实例,请求失败,但这样也⽐造成雪崩要好,牺牲了⼀些请求,保证了整个系统的⼀个可⽤。
-
Namespace
代表不同的环境,如开发dev、测试test、⽣产环境prod
-
-
-
DataId
某个项⽬中具体的xxx配置⽂件
可以通过 Spring Cloud 原⽣注解
@RefreshScope
实现配置⾃动更新。
Spring Cloud Stream 消息驱动组件帮助我们更快速,更⽅便的去构建
消息驱动
微服务的;
本质:屏蔽掉了底层不同
MQ
消息中间件之间的差异,统⼀了
MQ
的编程模型,降低了学习、开发、维护
MQ
的成本,⽬前⽀持Rabbit、Kafka两种消息;
Trace ID:
当请求发送到分布式系统的⼊⼝端点时,Sleuth为该请求创建⼀个唯⼀的跟踪标识Trace ID,在分布式系统内部流转的时候,框架始终保持该唯⼀标识,直到返回给请求⽅;
Span ID:
为了统计各处理单元的时间延迟,当请求到达各个服务组件时,也是通过⼀个唯⼀标识SpanID来标记它的开始,具体过程以及结束;
Spring Cloud Sleuth (追踪服务框架)可以追踪服务之间的调⽤,Sleuth可以记录⼀个服务请求经过哪些服务、服务处理时⻓等,根据这些,我们能够理清各微服务间的调⽤关系及进⾏问题追踪分析;
耗时分析:
通过 Sleuth 了解采样请求的耗时,分析服务性能问题(哪些服务调⽤⽐较耗时);