目录
总览
什么是SpringCloud
SpringCloud是一系列框架的有序集合,它利用了SpringBoot的开发便利性简化了分布式系统的开发,提供与外部系统的集成。 如服务注册与发现、配置中心、负载均衡、断路器、消息总线、数据监控等;换句话说:SpringCloud 提供了构建分布式系统所需的“全家桶”。
SpringCloud的优缺点
- 优点
- 采用去中心化的思想,服务之间采用Restful等轻量级通信,比ESB更清量
- 利于扩展模块
- 每个节点之间不会互相影响
- 缺点
- 配置复杂,节点多,成本高
SpringBoot和SpringCloud的区别
- SpringBoot是单体开发,SpringCloud是分布式开发;
- SpringCloud需要依赖SpringBoot进行开发;
- SpringBoot专注快速开发单个服务,SpringClou关注全局的服务治理。
服务注册中心
Eureka
客户端启动时如何注册到服务端
Eureka客户端在启动时,首先会创建一个心跳的定时任务,定时向服务端发送心跳信息,服务端会对客户端心跳做出响应,如果响应状态码为404时,表示服务端没有该客户端的服务信息,那么客户端则会向服务端发送注册请求,注册信息包括服务名、ip、端口、唯一实例ID等信息。
服务端如何保存客户端服务信息
客户端通过Jersey框架(亚马逊的一个http框架)将服务实例信息发送到服务端,服务端将客户端信息放在一个ConcurrentHashMap对象中。
客户端如何拉取服务端已保存的服务信息
客户端拉取服务端服务信息是通过一个定时任务定时拉取的,每次拉取后刷新本地已保存的信息,需要使用时直接从本地直接获取。
如何构建高可用的Eureka集群
搭建高可用的Eureka集群,只需要在注册中心的配置文件中配置其他注册中心的地址,配置属性如下:
eureka.client.service-url.defaultZone
注册中心收到注册信息后会判断是否是其他注册中心同步的信息还是客户端注册的信息,如果是客户端注册的信息,那么他将会将该客户端信息同步到其他注册中心去;否则收到信息后不作任何操作。通过此机制避免集群中信息同步的死循环。
心跳和服务剔除机制是什么
- 心跳机制
- 客户端启动后,就会启动一个定时任务,定时向服务端发送心跳数据,告知服务端自己还活着,默认的心跳时间间隔是30秒。
- 剔除机制
- 如果开启了自我保护机制,那么所有的服务,包括长时间没有收到心跳的服务(即已过期的服务)都不会被剔除;
- 如果未开启自我保护机制,那么将判断最后一分钟收到的心跳数与一分钟收到心跳数临界值比较,如果前者大于后者,且后者大于0的话,则启用服务剔除机制;
- 一旦服务剔除机制开启,则Eureka服务端并不会直接剔除所有已过期的服务,而是通过随机数的方式进行剔除,避免自我保护开启之前将所有的服务(包括正常的服务)给剔除。
Eureka自我保护机制是什么
在分布式系统的CAP理论中,Eureka采用的AP,也就是Eureak保证了服务的可用性(A),而舍弃了数据的一致性(C)。当网络发生分区时,客户端和服务端的通讯将会终止,那么服务端在一定的时间内将收不到大部分的客户端的一个心跳,如果这个时候将这些收不到心跳的服务剔除,那可能会将可用的客户端剔除了,这就不符合AP理论。
ZooKeeper
什么是ZooKeeper
ZooKeeper是一个开放源码的分布式协调服务。它是集群的管理者并监视着各节点的状态以及根据节点的反馈进行下一步操作,最终将简单和性能高效、功能稳定的系统提供给用户。
ZooKeeper能干嘛
分布式应用可以基于ZooKeeper实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁、分布式队列等功能。
ZooKeeper保证的是那些特性
- 顺序一致性;
- 原子性;
- 单一视图;
- 可靠性;
- 数据最终一致性。
ZooKeeper的读写原理
客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了监听器,这个监听器也是由ZooKeeper来处理的。
对于写请求,这些请求会转发给其他ZooKeeper机器并且达成一致后,请求才会返回成功。
因此,随着ZooKeeper的集群机器增多,读的吞吐量会增大,但写的请求吞吐会下降。
ZooKeeper的server工作状态有哪些
①Looking:寻找Leader状态。当服务器处于该状态时,它会认为当前集群中没有Leader,因此需要进入Leader选举状态。
②Following:跟随者状态。表明当前服务器角色是Follower。
③Leading:领导者状态。表明当前服务器角色是Leader。
④Observing:观察者状态。表明当前服务器角色是Observer。
分布式集群中为什么要有Master
在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行。其他机器可以共享这个计算结果,这样就大大减少了重复计算,提高性能。于是就需要进行leader选举,Leader的作用为了给Folower完成数据同步。
ZooKeeper宕机了如何处理
ZooKeeper本身也是集群,推荐配置不少于3个服务器。ZooKeeper自身也要保证当一个节点宕机时,其他节点会继续提供服务。
如果是一个Follower宕机,还有2台服务器提供访问,因为ZooKeeper上的数据是有多个副本的,数据并不会丢失;
如果是一个Leader宕机,ZooKeeper会选举出新的Leader。
ZooKeeper集群的机制是只要超过半数的节点正常,集群就能正常提供服务,即过半可使用原则。只有在ZooKeeper节点挂得太多,只剩一半或不到一半节点能工作,集群才失效。
所以3个节点的Cluster可以挂掉1个节点(Leader可以得到2票>1.5)。
2个节点的Cluster就不能挂掉任何1个节点了(Leader可以得到1票<=1)。
集群最少需要多少台机器,集群规则是怎么样的
2N+1台,N>0,即最少为3台。
集群支持动态添加机器吗
支持
全部重启:关闭所有ZooKeeper服务,修改配置之后启动。不影响之前客户端的会话。
逐个重启:在过半存活即可用的原则下,一台机器重启不影响整个集群对外提供服务。这是比较常用的方式。3.5版本开始支持动态扩容。
ZooKeeper对节点的Watch监听是永久的吗
不是永久监听的。
如果每个客户端对服务器的信息变动是永久监听的,那么当有很多客户端的时候,服务器的数据发生频繁更新时,所有的客户端将会收到通知。那么服务器和网络的压力也因此会变大。
如果客户端没有设置Watch事件,那么服务器的数据发生更新时,不会通知该客户端。
在实际的应用中,客户端不需要了解服务器的内部的数据变更,只需要得到最新的数据即可。
ZooKeeper如何保持数据一致性
在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执行相同的操作序列,那么他们最后能得到一个一致的状态。
如果Master挂了,ZooKeeper会怎么办
Paxos算法通过投票来对写操作进行全局编号,同一时刻,只有一个写操作被批准,同时并发的写操作要去争取选票,只有获得过半数选票的写操作才会被批准(所以永远只会有一个写操作得到批准),其他的写操作竞争失败只好再发起一轮投票,就这样,在不断的投票中,所有写操作都被严格编号排序。编号严格递增,当一个节点接受了一个编号为100的写操作,之后又接受到编号为99的写操作(因为网络延迟等很多不可预见原因),它马上能意识到自己数据不一致了,自动停止对外服务并重启同步过程。任何一个节点挂掉都不会影响整个集群的数据一致性(总2n+1台,除非挂掉大于n台)。
ZooKeeper是如何保证事务的顺序一致性
ZooKeeper采用了全局递增的事务ID来标识,所有的Proposal(提议)都在被提出的时候加上了zxid,zxid实际上是一个64位的数字,高32位是epoch用来标识Leader周期,如果有新的Leader产生出来,epoch会自增,低32位用来递增计数。当新产生proposal的时候,会依据数据库的两阶段过程,首先会向其他的server发出事务执行请求,如果超过半数的机器都能执行并且能够成功,那么就会开始执行。
ZooKeeper的典型应用场景
①数据发布/订阅
②负载均衡
③命名服务
④分布式协调/通知
⑤集群管理
⑥Master选举
⑦分布式锁
⑧分布式队列
Nacos
什么是Nacos
Nacos是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos有什么用
①服务发现和服务健康监测
②动态配置服务
③动态DNS服务
④服务及其元数据管理
服务调用
Ribbon
什么是Ribbon
Ribbo实现的一套客户端负债均衡工具
Ribbon主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项,如连接超时、重试等。简单的说,就是在配置文件中列出LoadBalancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询、随机连接等)去连接这些机器。
Ribbon的原理
底层使用HTTP通信的框架组件,HttpClient,先得使用Ribbon去本地的Eureka注册表的缓存里获取出来对方机器的列表,然后进行负载均衡,选出一台机器,接着针对那台机器发送Http请求。
Ribbon常见的负载均衡算法
API | 说明 |
---|---|
RoundRobinRule | 轮询算法(是Ribbon默认的负载均衡机制) |
RandomRule | 一种随机分配现有流量的负载平衡策略,即随机访问算法 |
RetryRule | 先按照 RoundRobinRule 的策略访问服务,如果访问的服务宕机或者出现异常的情况,则在指定时间内会进行重试,访问其它可用的服务 |
BestAvailableRule | 首先会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务访问 |
ZoneAvoidanceRule | 默认规则,复合判断server所在区域的性能和server的可用性选择服务器 |
AvailabilityFilteringRule | 首先会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问 |
WeightedResponseTimeRule | 根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule |
OpenFeign
OpenFeign原理
OpenFeign通过包扫描将所有被@FeignClient注解注释的接口扫描出来,并为每个接口注册一个FeignClientFactoryBean<T>实例。
FeignClientFactoryBean<T>是一个FactoryBean<T>,当Spring调用FeignClientFactoryBean<T>的getObject方法时,OpenFeign返回一个Feign生成的动态代理对象,拦截接口的方法执行。
Feign会为代理的接口的每个方法Method都生成一个MethodHandler。
当为接口上的@FeignClient注解的url属性配置服务提供者的url时,其实就是不与Ribbon整合,此时由SynchronousMethodHandler实现接口方法远程同步调用,使用默认的Client实现类Default实例发起Http请求。
当接口上的@FeignClient注解的url属性不配置时,且会走负载均衡逻辑,也就是需要与Ribbon整合使用。这时候不再是使用默认的Client调用接口,而是使用LoadBalancerFeignClient调用接口,由LoadBalancerFeignClient实现与Ribbon的整合。
服务降级
Hystrix
为什么要使用断路器Hystrix
在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用。为了保证其高可用,单个服务有必须集群部署。由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务累计,导致服务瘫痪,甚至导致服务“雪崩”。
什么是服务雪崩
多个服务之间调用的时候,假设服务A调用服务B和服务C,服务B和服务C又调用其他的服务,这就是所谓的“扇出”。如果“扇出”的链路上某个服务调用响应时间过长或者不可用,对服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的 “ 雪崩效应 ”。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
所以,通常当你发现一个模块下的某个实例失败后,这时候这个模块依然还会接受流量,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障(雪崩)。
造成服务雪崩的原因
①服务提供者不可用 (硬件故障、程序bug、缓存击穿、用户大量请求))
② 重试加大流量(用户重试、代码逻辑重试)
③服务调用者不可用(同步等待造成的资源耗尽)
最终的结果就是一个服务不可用,导致一系列的服务不可用
如何避免出现级联故障
服务降级、服务熔断
Hystrix的特性
服务降级:在服务限流或者服务熔断的情况下,走服务降级fallback方法,一段时间内不再走业务
服务熔断:接口出现异常或者处理时间过长,直接熔断,走服务降级fallback方法
服务限流:在接口访问超过设置的阈值,走服务降级fallback方法
Sentienl
什么是Sentienl
Sentinel是一个分布式架构的轻量级服务保护框架,主要以流量控制、熔断降级、系统负载保护等多个维度
服务接口保护有哪些方案
①使用服务保护框架Sentinel、Hystrix等进行服务的限流、熔断、降级
②黑白名单限制访问
服务降级的策略
①RT(平均响应时间):一秒内接口的访问响应时间超过指定阈值,则触发服务熔断
②异常比例:一秒内请求出现异常的比例超过指定阈值
③异常次数:一分钟内请求出现异常的次数超过指定阈值
QPS和线程数的区别
QPS:每秒访问次数
线程数:信号量隔离,一个接口的最大访问线程数量
Sentinel规则数据持久化的四种方案
默认情况下Sentinel不对数据持久化,需要自己独立持久化
①Nacos分布式配置中心:有界面,也不用重启服务器
②携程阿波罗:有界面,也不用重启服务器
③ZooKeeper,没有界面
④存放在本地文件:不容易修改配置
服务网关
Zuul
什么是Zuul
Zuul包含了对请求的路由和过滤两个最主要的功能。
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,以后的访问微服务都是通过Zuul跳转后获得。
Zuul的核心架构
Zuul的核心就是:filter、filter流与核心架构
Filter流(生命周期)
①PRE Filters
执行时机:before routing to the origin
这类filter可能做的事:请求身份验证、选择源服务器(选机器)、记录调试信息、限流
②ROUTING Filters
这类filter可能做的事:真正的向service的一台server(这台server是pre filter选出来的)发请求
③POST Filters
执行时机:将请求路由到起点之后
这类filter可能做的事:向响应中添加标准HTTP头、收集统计数据和指标、将响应从源站流式传输到客户端
④ERROR Filters
执行时机:其他三个阶段任一阶段发生错误时执行
⑤CUSTOM Filters
沿着默认的filter流,Zuul允许我们创建一些自定义的FilterType,并且准确的执行
GateWay
为什么要使用微服务网关
不同的微服务一般有不同的网络地址,外部的客户端可能需要调用多个服务的接口才能完成一个业务需求。
例如我之前做的一个用户登录微服务,用户登录成功后需要将token存入cookie中,还需要跳转到首页微服务。这时候就会出现cookie的跨域行为,与域名前后不一致,违背了开发和用户习惯。
如果用户端直接与微服务直接通信会存在什么问题
①多次请求不同的微服务,增加客户端的复杂性;
②存在跨域请求,在一定场景下处理相对复杂,比如cookie需要注意跨域;
③认证复杂,每个微服务都要独立认证;
④难以重构,项目迭代,可能继续划分微服务;
⑤某些微服务使用其它协议,直接访问困难。
GateWay原理
Gateway的客户端向SpringCloudGateway发送请求,请求首先被HttpWebHandlerAdapter进行提取组装成网关上下文,然后网关的上下文会传递到DispatcherHandler。
DispatcherHandler是所有请求的分发处理器,DispatcherHandler主要负责分发请求对应的处理器。
比如请求分发到对应的RoutePredicateHandlerMapping (路由断言处理映射器)。
路由断言处理映射器主要作用用于路由查找,以及找到路由后返回对应的FilterWebHandler。
FilterWebHandler主要负责组装Filter链并调用Filter执行一系列的Filter处理,然后再把请求转到后端对应的代理服务处理,处理完毕之后将Response返回到Gateway客户端。
服务配置
Config
分布式配置中心的作用
动态变更项目配置信息而不必重新部署项目
什么是SpringCloudConfig
SpringCloudConfig为分布式系统中的外部配置提供服务器和客户端支持,可以方便的对微服务各个环境下的配置进行集中式管理。
SpringCloudConfig分为ConfigServer和ConfigClient两部分。
ConfigServer负责读取配置文件,并且暴露HttpAPI接口,ConfigClient通过调用ConfigServer的接口来读取配置文件。
Nacos
加载多个配置文件怎么处理
通过@NacosPropertySource可以注入一个配置文件,如果我们需要将配置分类存储或者某些配置需要共用,这种需求场景下,一个项目中需要加载多个配置文件,可以直接使用多个NacosPropertySource注解,或者使用@NacosPropertySources。
配置修改了如何监听
通过ConfigService添加一个监听器
服务总线
Bus
什么是SpringCloudBus
①SpringCloudBus就像一个分布式执行器,用于扩展的SpringBoot应用程序的配置文件,但也可以用作应用程序之间的通信通道;
②SpringCloudBus不能单独完成通信,需要配合MQ支持;
③SpringCloudBus一般是配合SpringCloudConfig做配置中心的;
④SpringCloudConfig实时刷新也必须采用SpringCloudBus消息总线。