微服务框架之SpringClound

SpringClound体系介绍

 

                 

Spring Cloud其实是⼀套⽤于构建微服务架构的规范,⽽不是⼀个可以拿来即⽤的框架。

在这个规范之下:Netflix公司 开发了⼀些组件Spring官⽅开发了⼀些框架/组件阿⾥巴巴开发了 ⼀套框架/组件集合Spring Cloud Alibaba,这些才是Spring Cloud规范的实现。

Spring Cloud中的各组件协同⼯作,才能够⽀持⼀个完整的微服务架构。⽐如

  • 注册中⼼负责服务的注册与发现,很好将各服务连接起来
  • API⽹关负责转发所有外来的请求
  • 断路器负责监控服务之间的调⽤情况,连续多次失败进⾏熔断保护。
  • 配置中⼼提供了统⼀的配置信息管理服务,可以实时的通知各个服务获取最新的 配置信息

一、注册中心


1.Eureka基本介绍

1.1服务注册

  • 注册服务提供方、服务消费方会将自己的信息放到到注册中心上;

1.2服务发现

  • 服务消费方可以从注册中心拉取到服务提供方的地址;

1.3心跳检测

  • 服务会给注册中心发送心跳,发现一段时间无响应的服务进行剔除,
  • 注册中心还可以进行自保一旦自保开启,则注册中心就不会进行服务剔除操作,只能保证使用一种;
  • 心跳检测
    • eureka.instance.lease-renewal-interval-in-seconds=10 决定了每隔多久向服务器发送一次续约心跳包
    • eureka.instance.lease-expiration-duration-in-seconds=20 如果在20秒内都没有心跳/失败响应,那就代表挂了,EurekaServer定时会将服务从列表移除(默认90秒)
      • 失效剔除:Eureka Server会定时(间隔值是eureka.server.eviction-interval-timer-in-ms,默 认60s)进⾏检查,如果发现实例在⼀定时间(此值由客户端设置的 eureka.instance.lease-expiration-duration-in-seconds定义,默认值为90s内没有收到⼼跳,则会注销此实例
  • 心跳检测的实现
    • 服务给注册中心发送心跳请求,注册中心处理续约心跳请求,会进行update时间一系列的校验(最后一次同步注册的时间lastDirtyTimeStamp),来判断是否续约成功,如果失败就需要服务重新注册;
  • 服务自保
    • 自动触发开关,简单来说,服务自保机制会检查过去15分钟以内,所有成功续约的节点,占所有注册节点的比例如果低于一个限定值(比如85%)就开启服务自保模式。
      • 1)不会剔除任何服务实例
      • 2)Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它 节点上
    • 手动开关,强制关闭服务自保,即便上面的自动开关被触发,也不能开启自保功能  eureka.server.enable-self-preservation=false ;
    • 服务自保模式往往是为了应对短暂的网络环境问题,在理想情况下服务节点的续约成功率应该接近100%,如果突然发生网络问题,比如一部分机房无法连接到注册中心,这时候续约成功率有可能大幅降低。
    • 所以,考虑到Eureka采用客户端的服务发现模式,客户端手里有所有节点的地址,如果服务节点只是因为网络分区原因无法续约,但其自身服务是可用的,那么客户端仍然可以成功发起调用请求。这样就避免了被服务剔除给错杀。

1.4Eureka注册中心高可用

  • 配置集群模式,每台机器都可以提供服务,机器之间可以进行数据同步;
  • 客户端进行心跳等网络通讯的时候,会对整个集群的所有节点进行尝试请求,节点够多总会保证有一个可以进行访问;

2.Eureka基本架构

2.1服务注册到注册中⼼,利用了两层缓存

  • 第⼀层缓存是readOnlyCacheMap,采⽤ ConcurrentHashMap来存储数据的,主要负责定时与readWriteCacheMap进⾏数据同步,默认同步时间为 30 秒⼀次
  • 第⼆层缓存是readWriteCacheMap,采⽤Guava来实现缓存。缓存过期时间默认为180秒,当服务下线、过期、注册、状态变更等操作都会清除此缓存中的数据。(Eureka Server 中会有定时任务去检测失效的服务

2.2客户端缓存主要分为两块内容,⼀块是 Eureka Client 缓存,⼀块是 Ribbon 缓存

  • Eureka Client 缓存,自身初始化了⼀ 个 CacheRefreshThread 30秒定时任务⽤来拉取 Eureka Server 的实例信息到本地。
  • Ribbon 缓存,Ribbon会从EurekaClient中获取服务信息,Ribbon中通过线程 30秒定时去更新实例信息。

2.3客户端读取数据流程

  • Client获取服务实例数据时,会先从⼀级缓存中获取,如果⼀级缓存中不存在,再从 ⼆级缓存中获取,如果⼆级缓存也不存在,从存储层拉取数据,并会触发缓存的加载,然后再返回给 Client。

二、负载均衡


0.客户端和服务端的负载均衡

  • 服务端负载均衡:
    • 客户端发送请求,服务端进行负载均衡
    • 一般用于部署Tomcat、JBoss、网关等应用,通常不依赖注册中心;
  • 客户端负载均衡:
    • 客户端负载均衡Ribbon从注册中心Eureka Server中获取服务列表,然后根据负载均衡算法选出机器,负载均衡在客户端实现
    • 一般用于部署微服务框架,强依赖注册中心;

1.Ribbon基本介绍

  • 基于客户端的负载均衡
    • 先从注册中心Eureka Server中获取服务列表,然后根据负载均衡算法分发请求

  • 负载策略
    • RandomRule,随机选择;
      • 通过ThreadLocalRandom高性能的生成随机数(根据老的seed生成新的seed,由新的seed生成随机数);
    • RoundRobinRule,轮询策略;
    • WeightedResponseTimeRule,权重策略;
    • RetryRule,给其他负载均衡策略增加重试机制;
    • BestAvailableRule,并发量最低的节点;
    • AvailabilityFilteringRule,随机选择+可用性过滤+重新选取,最多10次重试,
      • 会过滤掉当前并发量较大(配置请求数),或者处于熔断状态的服务节点;
    • ZoneAvoidanceRule,组合过滤,包含了Zone过滤和可用性过滤;
      • Zone 过滤:一个服务节点有Zone, Region和URL三个身份信息,Zone指代机房,针对该机房下面区域的服务节点的健康情况去过滤。
      • 可用性过滤︰过滤掉当前并发量较大,或者处于熔断状态的服务节点。
  • 超时配置
    • Hystrix的超时时间要⼤于Ribbon的超时时间,因为 Hystrix将请求包装了起来。

2.Ribbon架构

负载均衡管理器LoadBalancer(总的协调者,相当于⼤脑,为了做事 情,协调四肢),围绕它周围的多有IRule、IPing等

  • IRule:是在选择实例的时候的负载均衡策略对象
  • IPing:是⽤来向服务发起心跳检测的,通过⼼跳检测来判断该服务是否可⽤
    • Ribbon通过该组件来判断所持有的服务实例列表中各服务可用情况,如果检测到某服务实例不存在/一定时间未响应,则会从持有服务列表中及时移除。
  • ServerListFilter:根据⼀些规则过滤传⼊的服务实例列表
    • 该组件会对原始服务列表使用一定策略进行过滤返回有效可用的服务器列表给客户端负载均衡器使用
    • ZoneAffinityServerListFilter:基于区域感知的方式,实现对服务实例的过滤,仅返回与本身所处区域一致的服务提供者实例列表
  • ServerListUpdater:定义了⼀系列的对服务列表的更新操作

添加了注解的RestTemplate对象会被添加⼀个拦截器 LoadBalancerInterceptor,该拦截器处理后续 拦截请求 进⾏负载。


三、服务稳定性——监控、熔断、降级


1.Hystrix熔断

  • 服务熔断:
    • 服务熔断引入了"“断路器/熔断器”的机制,当断路器打开的时候,对服务的调用请求不会发送到目标服务节点,而是直接转向fallback逻辑
    • 服务熔断的状态切换:
      • 熔断器open状态:服务在一定时间内不得发起外部调用,请求走fallback;
        • 在一定时间窗口内,发生异常的请求数量达到临界值
        • 在一定时间窗口内,发生异常的请求数量占请求总数量达到一定比例
        • 熔断器打开;
      • 熔断器half-open状态:
        • 发送一个正常请求,如果成功就会关闭熔断器,如果失败就会继续打开熔断器;
      • 熔断器closed状态:
        • 正常调用的情况 / 半开状态下请求成功一次,会进入断开状态;
    • 1)当调⽤出现问题时,开启⼀个时间窗(10s)
    • 2)在这个时间窗内,统计调⽤次数是否达到最⼩请求数?
      • 如果没有达到,则重置统计信息,回到第1步
      • 如果达到了,则统计失败的请求数占所有请求数的百分⽐,是否达到阈值? 如果达到,则跳闸(不再请求对应服务) 如果没有达到,则重置统计信息,回到第1步
    • 3)如果跳闸,则会开启⼀个活动窗⼝(默认5s),每隔5s,Hystrix会让⼀个请求到达那个问题服务,看 是否调⽤成功,如果成功,重置断路器回到第1步,如果失败,回到第3步
  • 服务降级:
    • 全局超时配置,hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000;
      • @Feignclient(name = "feign-service-provider", fallback= Fallback.class)  基于该类所有接口的降级
    • 方法级别的超时控制:需要基于方法签名进行配置
      • @HystrixCommand ( commandKey = "myKey",fallbackMethod ="fallback")
      • hystrix.command.myKey.execution.isolation.thread.timeoutInMilliseconds=1000
    • 服务降级需要等待请求从服务节点返回异常或超时,再转向fallback逻辑。
    • 服务降级的实现:
      • Hystrix使用线程隔离的方案,将执行服务调用的代码与容器本身的线程池(Tomcat thread pool)进行隔离,我们可以配置每个服务所需线程的最大数量,这样一来,即便一个服务的线程池被吃满,也不会影响其他服务。
    • 线程池和信号量对比:
      • 线程池技术:Hystrix自己内建的线程池去执行方法调用,而不是使用Tomcat的容器线程。
        • Hystrix自建线程可以直接自己设置超时时间,直接对“执行阶段”的超时进行判定,而信号量无法自己去设置超时时间,只能等待诸如网络请求超时等“被动超时”的情况。
        • 但涉及到线程的创建、销毁和任务调度、线程之间的切换都会耗费CPU,从资源利用率和效率的角度来看,线程池技术会比信号量慢。
      • 信号量技术:只能使用Tomcat的容器线程去执行方法,不会另外创建新的线程,信号量只充当开关和计数器的作用。获取到信号量的线程就可以执行方法,没获取到的就转到fallback。
        • 信号量只是充当一个计数器的作用,没有额外的系统资源消费,所以在性能方面具有明显的优势
        • 使用信号量的场景,通常用来应对非网络请求不需要调用外部服务时),比如:当出现大量的数据传输,就需要做一些流量传输控制。
  • Hystrix的实现:
    • 以AOP动态代理的方式给对应的方法进行拦截,进行增强,
    • 利用Rxjava异步编程的方式实现异常/超时触发服务降级的功能;

2.服务调用链路追踪-Sleuth

  • 分布式链路追踪:
    • ⽤微服务架构设计我们的系统,使得我们的系统不仅能够通过集群部署抵挡流量的冲击,⼜能根据业务进⾏灵活的扩展。
    • 那么,在微服务架构下,⼀次请求很可能经过十几次服务调⽤才能完成,当出现问题是很难定位的,如果可以将当前请求的整个链路打印出来那么可以很快地定位问题
  • Sleuth基本介绍:
    • Trace:服务追踪的追踪单元是从客户发起请求(request)抵达被追踪系统的边界 开始,到被追踪系统向客户返回响应(response)为⽌的过程
      • Trace ID:为了实现请求跟踪,当请求发送到分布式系统的⼊⼝端点时,只需要服 务跟踪框架为该请求创建⼀个唯⼀的跟踪标识Trace ID,同时在分布式系统内部流转 的时候,框架失踪保持该唯⼀标识,直到返回给请求⽅
      • ⼀个Trace由⼀个或者多个Span组成,每⼀个Span都有⼀个SpanId,Span中会记录 TraceId,同时还有⼀个叫做ParentId,指向了另外⼀个Span的SpanId,表明⽗⼦关系;
    • Span:可以认为是⼀个⽇志数据结构,在⼀些特殊的时机点会记录了⼀些⽇志信息, ⽐如有时间戳、spanId、TraceId,parentIde等,Span中也抽象出了另外⼀个概 念,叫做事件,核⼼事件如下
      • Span ID:为了统计各处理单元的时间延迟,当请求到达各个服务组件时,也是通过 ⼀个唯⼀标识Span ID来标记它的开始,具体过程以及结束。对每⼀个Span来说, 它必须有开始和结束两个节点,通过记录开始Span和结束Span的时间戳,就能统计出该Span的时间延迟,除了时间戳记录之外它还可以包含⼀些其他元数据,⽐如 时间名称、请求信息等
      • Event:Span中也抽象出了另外⼀个概 念,叫做事件
        • CS Client Sent,客户端发送了一个调用请求;描述的是⼀个span开始
        • SR Server Received,服务端收到了来自客户端的调用;SR-CS属于请求发送的⽹络延迟
        • SS Server Sent,服务端将Response发送给客户端;SS-SR属于服务端消耗时间
        • CR Client Received,客户端收到了服务端发来的Response;CR-SS表示回复需要的时 间(响应的⽹络延迟),CR-CS表示Span的总耗时
  • 链路追踪的实现:
    • Sleuth正是通过Filter向Header中添加追踪信息;
    • Sleuth采用集成底层Log系统的方式实现业务埋点,每一个微服务都有自己的Log组件 (slf4j,lockback等各不相同),当我们集成了Sleuth之后,它便会将链路信息传递给底层Log组件,同时Log组件会在每行Log的头部输出这些数据;
      • 当我们使用"log.info"打印日志的时候,Log组件会将“写入”动作封装成一个LogEvent事件,而这个事件的具体表现形式由Log Format和MDC共同控制,Format决定了Log的输出格式,而MDC决定了输出什么内容
      • Log Format Pattern:
        • Log组件定义了日志输出格式,这和我们平时使用“String.format”的方式差不多,集成了Sleuth后的Log输出格式是下面这个样子:
        • "%5p [sleuth-traceA,%X{X-B3-TraceId:-},%x{X-B3-SpanId :-},%x{X-Span-Export:-}]"
        • 链路ID:当前调用链的唯一ID,在这次调用请求开始到结束的过程中,所有经过的节点都拥有一个相同的链路ID;
        • 单元ID:在一次链路调用中会访问不同服务器节点上的服务,每一次服务调用都相当于一个独立单元,也就是说会有一个独立的单元ID。同时每一个独立单元都要知道调用请求来自哪里 (当前服务发起直接调用的那一方的单元ID,我们记为Parent ID);
      • MDC:
        • MDC是通过InheritableThreadLocal来实现的,它可以携带当前线程的上下文信息。
        • 由于MDC基于InheritableThreadLocal而不是ThreadLocal实现,如果在当前线程中又开启了新的子线程,那么子线程依然会保留父线程的上下文信息。
          • 实际情况并不是当前线程去创建子线程,通常都是使用线程池,所以说在异步调用的时候所有日志打不出来除非可以通过Context把数据传过去
        • Sleuth就是借助Spring的AOP机制,在方法调用的时候配置了切面,将链路追踪数据加入到了MDC中,这样在打印Log的时候,就能从MDC中获取这些值,填入到Log Format中的占位符里。
  • Zipkin基本介绍:
    • Zipkin是一套分布式实时数据追踪系统的数据展示组件,它主要关注的是时间维度的监控数据,比如某个调用链路下各个阶段所花费的时间,并且从可视化的角度帮我们梳理上下游系统之间的依赖关系。
  • Zipkin架构:
    • Zipkin分为服务端和客户端
      • 服务端是一个专门负责收集数据、查找数据的中心,
      • 客户端负责把结构化的Timing数据发送到服务端,供服务端做索引和分析。
      • 通过收集一个调用链上下游所有工作单元,Zipkin就能知道每个环节在服务总用时中所占的比重,再通过图形化界面的形式,快速知道性能瓶颈出在哪里。
    • Zipkin提供了多种维度的查找功能用来检索Span的耗时,最直观的是通过Trace ID查找整个Trace链路上所有Span的前后调用关系和每阶段的用时,还可以根据Service Name或者访问路径等维度进行查找
    • Collector:  负责在Zipkin Server侧一直等待接收客户端数据。用来验证客户端发送来的链路数据,并在存储结构中建立索引。
    • Storage: Zipkin支持ElasticSearch和MySQL等存储介质用来保存链路信息;
    • Search Engine∶提供基于JSON API的接口来查找信息;
    • Dashboard : 一个大盘监控页面,后台调用Search Enginc来获取展示信息。

四、服务网关


  • Gateway基本介绍
    • ⼀个请求—>⽹关,根据⼀定的条件匹配,成功之后可以将请求转发到指定的服务地址;⽽在这个过程中,我们可以进⾏⼀些⽐较具体的控制(限流、日志、黑白名单) 
    •  
    • 其中,Predicates断⾔就是我们的匹配条件,⽽Filter就可以理解为⼀个⽆所不 能的拦截器,有了这两个元素,结合⽬标URL,就可以实现⼀个具体的路由转 发
    • 路由(route)
      • ⽹关最基础的部分,也是⽹关⽐较基础的⼯作单元。
      • 路由由⼀个ID、⼀个⽬标URL(最终路由到的地址)⼀系列的断⾔(匹配条件判断)Filter过滤器(精细化控制)组成。如果断⾔为true,则匹配该路由
    • 断⾔(predicates)
      • 参考了Java8中的断⾔java.util.function.Predicate,开发 ⼈员可以匹配Http请求中的所有内容(包括请求头、请求参数等)(类似于 nginx中的location匹配---正则、精准匹配等),如果断⾔与请求相匹配则路由。
      • 常用的断言:Path断言;Method断言;RequestParam断言,验证QueryString;Header断言;Cookie断言;时间片匹配;自定义断言;
    • 过滤器(filter)
      • ⼀个标准的Spring webFilter,使⽤过滤器,可以在请求之前 或者之后执⾏业务逻辑。
      • Filter在“pre”类型过滤器中可以做参数校验、权限校验、流量监控、⽇志输出、协议 转换等。
      • 在“post”类型的过滤器中可以做响应内容、响应头的修改、⽇志的输出、流 量监控等。
      • Header过滤器;
      • StripPrefix过滤器,去掉部分url路径;
      • PrefixPath过滤器,会在请求路径的前面加入前缀,;
      • RedirectTo过滤器,可以把收到特定状态码的请求重定向到一个指定网址;
      • SaveSession,在调用服务之前都会强制保存session;
  •  网关的高级:
    • URI转发:
      • 如果请求顺利通过过滤器的处理,接下来就到了最后一步,那就是转发请求。
    • 负载均衡:依靠Ribbon实现;
      • 对最后一步寻址来说,如果采用基于Eureka的服务发现机制,那么在Gateway的转发过程中可以采用服务注册名的方式来调用,后台会借助Ribbon实现负载均衡(可以为某个服务指定具体的负载均衡策略),如:lb: //FEIGN-SERVICE-PROVIDER/,前面的lb就是指代Ribbon作为LoadBalancer。
    • 限流:通过Redis+Lua实现分布式限流,Hystrix限流;
  • Gateway网关架构
    • Client发起请求到服务网关之后,由NettyRoutingFilter底层的HttpClient (也是Netty组件)向服务发起调用,调用结束后的Response由NettyResponseFilter再回传给客户端。
    • 有了Netty的加持,网络请求效率大幅提升(Zuul 1.x还是使用Servlet,在2.x版本才移步到Netty)由此可见,Netty贯穿了从Request发起到Responsc结束的过程,承担了所有和网络调用相关的任务。
  • 网关的权限认证:
    • 用户登陆认证方式
      • 基于session+cookie的方案来解决的,单机方案session保存在Tomcat服务器中,分布式方案session保存在redis中,cookie中保存的是sessionID同一个域名/子域名下都可以传输该ID;
        • 安全性不够,token不需要服务端存储(底层是通过用户信息等生成toke)
        • 兼容性不够,移动端没有cookie这一套维护机制
          • HTTP协议无状态
          • PC端能支持Cookie方式验证,是因为浏览器维护了一套Cookie的适用规则和生命周期
          • APP端是没有的,客户端本地里有localStorage和sessionStorage两个地方可以存,每次请求都是需要显示带上token的
        • 所以说目前急需一种可以解决掉安全性、兼容性问题的一套新的机制。
        • session/token - 简书 (jianshu.com)
      • 基于token的方式,可以很好地处理session+cookie这种方式带来的弊端
    • OAuth2.0认证:
      • OAuth2.0介绍:
        • 这是一个开放的授权标准协议,它允许用户让第三方应用访问该用户在某服务的特定私有资源,但是不提供账号密码信息给第三方应用。
          • ⽤户:我们⾃⼰
          • 第三⽅应⽤:拉勾⽹
          • 服务提供者:QQ
      • OAuth2.0适用场景:
        • 第三⽅授权登录的场景:⽐如,我们经常登录⼀些⽹站或者应⽤的时候,可以选择使⽤第三⽅授权登录的⽅式,⽐如:微信授权登录、QQ授权登录、微博授权登录 等,这是典型的 OAuth2 使⽤场景
        • 单点登录的场景:如果项⽬中有很多微服务或者公司内部有很多服务,可以专⻔做⼀个认证中⼼(充当认证平台⻆⾊),所有的服务都要到这个认证中⼼做认证,只 做⼀次登录,就可以在多个授权范围内的服务中⾃由串⾏。
      • 拿微信登录第三方应用的例子来说:
        • Auth Grant:在这一步Client发起Authorization Request到微信系统(比如:通过微信内扫码授权),当身份验证成功后获取Auth Grant;
          • 1)拉勾⽹——登记——>QQ平台
          • 2)QQ 平台会颁发⼀些参数给拉勾⽹,后续上线进⾏授权登录的时候(刚才打开授权⻚⾯)需要携带这些参数
          • Auth Grant包含一些账号信息
        • Get Token:客户端拿着从微信获取到的Auth Grant,发给第三方引用的鉴权服务,换取一个Token,这个Token就是访问第三方应用资源所需要的令牌;
        • 访问资源:最后一步,客户端在请求资源的时候带上Token令牌,服务端验证令牌真实有效后即返回指定资源;
    • JWT(JSON Web Token)鉴权:
      • JWT介绍:
        • JSON Web Token(JWT)是⼀个开放的⾏业标准(RFC 7519),它定义了⼀种简介 的、⾃包含的协议格式,⽤于 在通信双⽅传递json对象,传递的信息经过数字签名 可以被验证和信任
        • JWT可以使⽤HMAC算法或使⽤RSA的公钥/私钥对来签名防⽌信息被篡改
      • 鉴权流程:
        • 用户名+密码访问鉴权服务
          • 验证通过:服务器返回一个Access Token给客户端,并将token保存在服务端某个地方用于后面的访问控制(Redis中)
          • 验证失败:不生成Token
        • 客户端使用令牌访问资源,服务器验证令牌有效性
          • 令牌错误或过期:拦截请求,让客户端重新申请令牌
          • 令牌正确︰允许放行
      • Access Token
        • JWT令牌由三部分组成,每部分中间使⽤点(.)分隔,⽐如:xxxx.yyyy.zzzz
        • Header头部声明了Token的类型(比如:JWT类型)和采用的加密算法(比如:HS256)。
        • Payload这一段包含的信息相当丰富,你可以定义Token签发者、签发和过期时间、生效时间等一系列属性还可以添加自定义属性。服务端收到Token的时候也同样可以对Payload中包含的信息做验证,假如某个接口只能允许“Gateway-APT”签发的Token,那么在做鉴权服务时就可以加入Issuer的判断逻辑。
        • Signature它会使用Header和Payload以及一个密钥用来生成签证信息,这一步会使用Header里我们指定的加密算法进行加密(先进行哈希,然后进行加密,形成签名信息)。
      • JWT优势:
        • 我们访问资源服务器时会携带token,资源服务器会请求认证服务器验证token有效性,如果资源服务器有很多,那么认证服务器压⼒会很⼤
          • 资源服务器向认证服务器check_token,获取的是⽤户信息 UserInfo,如果能把⽤户信息存储到令牌中,让客户端⼀直持有这个令牌,令牌的验证也在资源服务器进⾏,这样避免和认证服务器频繁的交互
        • JWT令牌中已经包括了⽤户相关的信息,客户端只需要携带JWT访问资源服务,资源服务根据事先约定的算法⾃⾏完成令牌校验,⽆需每次都请求认证服务完成授权
    • OAuth2 + JWT 实现用户鉴权:
      • OAuth2只是第三方授权协议,真正的鉴权实现还是基于JWT来实现的;


五、服务调用


1.Feign服务调用

  • Feign介绍:
    • 服务间调用,简化远程调用,提供了使用接口的方式调用,集成了RestTemplateRibbonHystrix
    • 之前调用的方式:
      • Eureka,在Eureka上获取到Server的Ip和Port
      • Ribbon,根据Servername的信息
      • 拼接出Url使用RestTemplate进行调用
  • Feign基本原理:
    • 基于动态代理,通过接口调用的方式实现远程调用,
      • Spring加载bean实现动态代理,构造FeignClientFactoryBean的BeanDefinition信息,通过FeignClientFactoryBean的getObject方法返回最终的代理类,代理类实现调用对应的方法就会转发到对应的服务上;
      • 使用HTTP协议实现的通讯协议,服务提供方提供出来地址到Eureka,服务消费方获取到地址,通过HttpClient实现调用;
  • Feign超时时间:
    • Ribbon的优先级大于Feign,如果此时设置了Ribbon的时间就以Ribbon 的时间为准,如果没设置Ribbon的时间但配置了Feign的时间,就以Feign的时间为准。

六、配置中心


  • 只要支持发布-订阅模型,可以实现实时推送,就可以实现。比如:Zookeeper、Nacos
  • Spring Cloud Config是⼀个分布式配置管理⽅案,包含了 Server端和 Client端两个
    • 客户端使⽤post去触发refresh,获取最新数据

七、Spring Cloud Stream消息驱动组件


  • 消息驱动组件:
    • 不同的MQ消息中间件内部机制包括使⽤⽅式都会有所不同,⽐如RabbitMQ中有 Exchange(交换机/交换器)这⼀概念,kafka有Topic、Partition分区这些概念, MQ消息中间件的差异性不利于我们上层的开发应⽤,当我们的系统希望从原有的 RabbitMQ切换到Kafka时,我们会发现⽐较困难,很多要操作可能重来(因为应用程序和具体的某⼀款MQ消息中间件耦合在⼀起了)。
    • Spring Cloud Stream进⾏了很好的上层抽象,可以让我们与具体消息中间件解耦 合,屏蔽掉了底层具体MQ消息中间件的细节差异,就像Hibernate屏蔽掉了具体数 据库(Mysql/Oracle⼀样)。如此⼀来,我们学习、开发、维护MQ都会变得轻松。 ⽬前Spring Cloud Stream⽀持RabbitMQ和Kafka。
    • 本质:屏蔽掉了底层不同MQ消息中间件之间的差异,统⼀了MQ的编程模型,降低了学习、开发、维护MQ的成本
  • 应用场景:
    • 配置变更通知;
    • 清空缓存︰通知所有服务监听者清空某项业务的本地缓存信息,我们也可以在自定义的消息体中加业务属性,事件监听逻辑可以根据这些属性来定点清除某个特定业务对象的缓存;
    • 数据同步:子系统依赖实时的数据库记录变动触发相应的业务逻辑,我们这里就可以将数据库的binlog抓取出来,通过广播功能同步到所有监听器,起到数据同步的作用;
  • Stream体系架构:
    • Input通道:
      • 输入通道,它的作用是将消息组件中获取到的Message传递给消费者进行消费。在Stream里我们可以借助@Input注解轻松定义一个输入通道;
    • Output通道:
      • 输出通道,用来将生产者创建的新消息发送到对应的Topic中去,在Stream中我们可以借助@Output标签定义一个输出通道,@Output和@Input可以放在一个接口中声明;
    • Binder抽象层 :
      • Stream提供了一个Binder抽象层,作为连接外部消息中间件(指RabbitMQ,Kafka)的桥梁;
      • Binder它作为一个适配层,对上层应用程序和底层消息组件之间做了一层屏障,我们的应用程序不用关注底层究竟是使用了Kafka还是RabbitMQ,只管用注解开启响应的消息通道,剩下的事通通交给Binder来搞定。
      • 当我们需要替换底层中间件的时候,只要变更Binder的依赖项,然后修改一些配置文件就好了,对我们的应用程序几乎是无感知的;

八、Spring Cloud Alibaba


1、Nacos 配置中心

  • Spring Cloud Config + Bus

    • 1)   Github 上添加配置⽂件
    • 2)创建Config Server 配置中⼼—>从Github上去下载配置信息
    • 3)具体的微服务(最终使⽤配置信息的)中配置Config Client—> ConfigServer获取 配置信息
    • 流程繁琐,甚至需要借助BUS组件MQ的方式来实现
    • 数据不安全,核心数据没有进行自己维护,而是放在外部系统
  • Nacos
    • 1、去Nacos server中添加配置信息
    • 2、改造具体的微服务,使其成为Nacos Config Client,能够从Nacos Server中获取 到配置信息
    • Github不需要了(配置信息直接配置在Nacos server中),Bus也不需要了(依然可以完成动态刷新)

2.Sentinel限流

  • 限流方式:是否集群、链路模式、接口关联模式、直接单台机器模式
    • QPS流量控制:当QPS超过某个阈值的时候,则采取措施进行流量控制。
      • 流量控制的手段包括以下几种: 直接拒绝、Warm Up、匀速排队。
      • 直接:
        • 直接拒绝 (RuleConstant.CONTROL_BEHAVIOR_DEFAULT)方式是默认的方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。
        • 这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。
      • Warm Up:
        • Warm Up (RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。
        • 通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
        • 如果设置预热时间是10秒,count是20个请求,那么到第10秒的时候,系统开始稳定的接受20个请求。
      • 匀速排队:
        • 匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
        • 当count设为10的时候,则代表一秒匀速的通过10个请求,也就是每个请求平均间隔恒定为1000/ 10 = 100 ms。
        • 排队等待模式下,QPS 设置值不要超过 1000(请求间隔 1 ms)
    • 并发线程数实现流量控制:
      • 并发线程数限流用于保护业务线程数不被耗尽。Sentinel并发线程数限流不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目,如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。
  • 熔断方式:
    • Sentinel不会像Hystrix那样放过⼀个请求尝试⾃我修复,就是明明确确按照时间窗⼝来,熔断触发后,时间窗⼝内拒绝请求,时间窗⼝后就恢复。
    • RT(平均响应时间)
      • 当 1s 内持续进⼊ >=5 个请求,平均响应时间超过阈值(以 ms 为单位),那么 在接下的时间窗⼝(以 s 为单位)之内,对这个⽅法的调⽤都会⾃动地熔断
    • 异常⽐例
      • 当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的⽐值超过阈值之后, 资源进⼊降级状态,即在接下的时间窗⼝(以 s 为单位)之内,对这个⽅法的调 ⽤都会⾃动地返回。​​​​​​​
    • 异常数
      • 当资源近 1 分钟的异常数⽬超过阈值之后会进⾏熔断。注意由于统计时间窗⼝是分钟级别的,若 timeWindow ⼩于 60s,则结束熔断状态后仍可能再进⼊熔断状态。
  • Sentinel原理:
    • 核心数据结构:
      • 使用滑动窗口来进行流量控制,以1s为一个周期,设置最大请求为1000,划分为10个小桶,每个窗口间隔100ms并且都有计数,每过100ms都会将尾部的窗口计数减去并将新窗口的计数加上,只要不超过周期内的最大请求量即可;
        • 当然也可以增加每个小窗口的计数限制,避免请求过于集中在一个小窗口内。

3、Dubbo

  • 删除OpenFeign 和 Ribbon,使⽤Dubbo

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值