编辑推荐: |
本文主要介绍微服务架构中常见概念,Spring Cloud 综述、第一代Spring Cloud核心组件、Spring Cloud高级进阶、第二代Spring Cloud核心组件,希望对您的学习有所帮助。
本文来自于
今日头条 ,由Alice编辑、推荐。 |
|
一、微服务架构中常见概念
服务注册与服务发现
- 服务注册: 服务提供者将所提供服务的信息(服务器IP和端口、服务访问协议等) 注册/登记到注册中心。
- 服务发现: 服务消费者能够从注册中心获取到较为实时的服务列表,然后根究一定 的策略选择一个服务访问。
负载均衡
负载均衡即将请求压力分配到多个服务器(应用服务器、数据库服务器等),以此来提高服务的性能、可靠性。
熔断
即断路保护。微服务架构中,如果下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。
链路追踪
微服务架构越发流行,一个项目往往拆分成很多个服务,那么一次请求就需要涉及到很多个服务。不同的微服务可能是由不同的团队开发、可能使用不同的编程语言实现、整个项目也有可能部署在了很多服务器上(甚至百台、千台)横跨多个不同的数据中心。所谓链路追踪,就是对一次请求涉及的很多个服务链路进行日志记录、性能监控。
API 网关
API请求调用统一接入API网关层, 由网关转发请求。API网关更专注在安全、路由、流量等问题的处理上(微服务团队 专注于处理业务逻辑即可),它的功能:
- 统一接入(路由)
- 安全防护(统一鉴权,负责网关访问身份认证验证,与“访问认证中心”通信,实际认证业务逻辑交移“访问认证中心”处理)
- 黑白名单(实现通过IP地址控制禁止访问网关功能,控制访问)
- 协议适配(实现通信协议校验、适配转换的功能)
- 流量管控(限流)
- ⻓短链接支持
- 容错能力(负载均衡)
二、Spring Cloud 综述
Spring Cloud是一系列框架的有序集合(Spring Cloud是一个规范)开发服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等 利用Spring Boot的开发便利性简化了微服务架构的开发(自动装配)。
Spring Cloud 核心组件
Spring Cloud 生态圈中的组件,按照发展可以分为第一代 Spring Cloud组件和第二代 Spring Cloud组件。
Spring Cloud 体系结构
Spring Cloud中的各组件协同工作,才能够支持一个完整的微服务架构。比如
- 注册中心负责服务的注册与发现,很好将各服务连接起来
- API网关负责转发所有外来的请求
- 断路器负责监控服务之间的调用情况,连续多次失败进行熔断保护
- 配置中心提供了统一的配置信息管理服务,可以实时的通知各个服务获取最新的配置信息
三、第一代Spring Cloud核心组件
1、服务注册中心组件 Eureka
Eureka 交互流程及原理
Eureka 包含两个组件:Eureka Server 和 Eureka Client,Eureka Client是一个 Java客户端,用于简化与Eureka Server的交互;Eureka Server提供服务发现的能力,各个微服务启动时,会通过Eureka Client向Eureka Server 进行注册自己 的信息(例如网络信息),Eureka Server会存储该服务的信息。
- 图中us-east-1c、us-east-1d,us-east-1e代表不同的区也就是不同的机房
- 图中每一个Eureka Server都是一个集群。
- 图中Application Service作为服务提供者向Eureka Server中注册服务, Eureka Server接受到注册事件会在集群和分区中进行数据同步,Application Client作为消费端(服务消费者)可以从Eureka Server中获取到服务注册信 息,进行服务调用。
- 微服务启动后,会周期性地向Eureka Server发送心跳(默认周期为30秒) 以续约自己的信息
- Eureka Server在一定时间内没有接收到某个微服务节点的心跳,Eureka Server将会注销该微服务节点(默认90秒)
- 每个Eureka Server同时也是Eureka Client,多个Eureka Server之间通过复 制的方式完成服务注册列表的同步
- Eureka Client会缓存Eureka Server中的信息。即使所有的Eureka Server节 点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者
Eureka通过心跳检测、健康检查和客户端缓存等机制,提高系统的灵活性、可 伸缩性和可用性。
Eureka集群:
Eureka的 元数据 有两种:标准元数据和自定义元数据。
标准元数据: 主机名、IP地址、端口号等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。
自定义元数据: 可以使用eureka.instance.metadata-map配置,符合KEY/VALUE的 存储格式。这 些元数据可以在远程客户端中访问。
2、Ribbon负载均衡
负载均衡一般分为服务器端负载均衡和客户端负载均衡 所谓服务器端负载均衡,比如Nginx、F5这些,请求到达服务器之后由这些负载均衡器根据一定的算法将请求路由到目标服务器处理。
所谓客户端负载均衡,比如我们要说的Ribbon,服务消费者客户端会有一个服务器 地址列表,调用方在请求前通过一定的负载均衡算法选择一个服务器进行访问,负载均衡算法的执行是在请求客户端进行。
Ribbon是Netflix发布的负载均衡器。Eureka一般配合Ribbon进行使用,Ribbon利 用从Eureka中读取到服务信息,在调用服务提供者提供的服务时,会根据一定的算法进行负载。
Ribbon工作原理:
3、Hystrix熔断器
Hystrix(豪猪),宣言“defend your app”是由Netflix开源的一个 延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而 提升系统的可用性与容错性。Hystrix主要通过以下几点实现延迟和容错。
- 包裹请求:使用HystrixCommand包裹对依赖的调用逻辑。
- 跳闸机制:当某服务的错误率超过一定的阈值时,Hystrix可以跳闸,停止请求 该服务一段时间。
- 资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(舱壁模式)(或者信号 量)。如果该线程池已满, 发往该依赖的请求就被立即拒绝,而不是排队等待,从而加速失败判定。
- 监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、 超时、以及被拒绝 的请求等。
- 回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑由开发人员自行提供,例如返回一个缺省值。
- 自我修复:断路器打开一段时间后,会自动进入“半开”状态。
扇入、扇出概念:
扇入: 代表着该微服务被调用的次数,扇入大,说明该模块复用性好。
扇出: 该微服务调用其他微服务的个数,扇出大,说明业务逻辑复杂。
扇入大是一个好事,扇出大不一定是好事。
微服务架构中,一个应用可能会有多个微服务组成,微服务之间的数据交互通过 远程过程调用完成。这就带来一个问题,假设微服务A调用微服务B和微服务C,微 服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某 个微服务的调用响应时间过⻓或者不可用,对微服务A的调用就会占用越来越多的系 统资源,进而引起系统崩溃,所谓的“雪崩效应”。
Hystrix舱壁模式:
Hystrix工作流程:
4、Feign远程调用组件
Feign是Netflix开发的一个轻量级RESTful的HTTP服务客户端(用它来发起请求, 远程调用的),是以Java接口注解的方式调用Http请求,而不用像Java中通过封装 HTTP请求报文的方式直接调用,Feign被广泛应用在Spring Cloud 的解决方案中。
类似于Dubbo,服务消费者拿到服务提供者的接口,然后像调用本地接口方法一样 去调用,实际发出的是远程的请求。
- Feign可帮助我们更加便捷,优雅的调用HTTP API:不需要我们去拼接url调用restTemplate的api,在SpringCloud中,使用Feign非常简单,创建一个接口(在消费者服务调用方这一端),并在接口上添加一些注解,代码就完成了
- SpringCloud对Feign进行了增强,使Feign支持了SpringMVC注解 (OpenFeign)
本质:封装了Http调用流程,更符合面向接口化的编程习惯,类似于Dubbo的服务调用。
Feign调用流程:
5、GateWay网关组件
pring Cloud GateWay是Spring Cloud的一个全新项目,目标是取代Netflix Zuul, 它基于Spring5.0+SpringBoot2.0+WebFlux(基于高性能的Reactor模式响应式通信 框架Netty,异步非阻塞模型)等技术开发,性能高于Zuul,官方测试,GateWay是 Zuul的1.6倍,旨在为微服务架构提供一种简单有效的统一的API路由管理方式。
Spring Cloud GateWay不仅提供统一的路由方式(反向代理)并且基于 Filter(定义 过滤器对请求过滤,完成一些功能) 链的方式提供了网关基本的功能,例如:鉴权、 流量控制、熔断、路径重写、日志监控等。
GateWay核心概念:
Zuul1.x 阻塞式IO 2.x 基于Netty
Spring Cloud GateWay天生就是异步非阻塞的,基于Reactor模型
一个请求到达网关根据一定的条件匹配—匹配成功之后可以将请求转发到指定的服务 地址;而在这个过程中,我们可以进行一些比较具体的控制(限流、日志、黑白名 单)
- 路由(route): 网关最基础的部分,也是网关比较基础的工作单元。路由由一 个ID、一个目标URL(最终路由到的地址)、一系列的断言(匹配条件判断)和 Filter过滤器(精细化控制)组成。如果断言为true,则匹配该路由。
- 断言(predicates):参考了Java8中的断言java.util.function.Predicate,开发 人员可以匹配Http请求中的所有内容(包括请求头、请求参数等)(类似于 nginx中的location匹配一样),如果断言与请求相匹配则路由。
- 过滤器(filter):一个标准的Spring webFilter,使用过滤器,可以在请求之前或者之后执行业务逻辑。
其中,Predicates断言就是我们的匹配条件,而Filter就可以理解为一个无所不能的拦截器,有了这两个元素,结合目标URL,就可以实现一个具体的路由转发。
GateWay工作过程:
客户端向Spring Cloud GateWay发出请求,然后在GateWay Handler Mapping中 找到与请求相匹配的路由,将其发送到GateWay Web Handler;Handler再通过指 定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之 间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或者之后(post)执 行业务逻辑。
Filter在“pre”类型过滤器中可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改、日志的输出、流 量监控等。
核心逻辑: 路由转发+执行过滤器链。
GateWay路由规则详解:
GateWay过滤器:
主要有两个pre和post:
- pre:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份 验证、在集群中选择 请求的微服务、记录调试信息等。
- post:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加 标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给 客户端等。
从过滤器类型的⻆度,Spring Cloud GateWay的过滤器分为GateWayFilter和 GlobalFilter两种:
- GateWayFilter:应用到单个路由路由上
- GlobalFilter:应用到所有的路由上
6、Spring Cloud Config 分布式配置中心
Spring Cloud Config是一个分布式配置管理方案,包含了 Server端和 Client端两个部分。
- Server 端:提供配置文件的存储、以接口的形式将配置文件的内容提供出去, 通过使用@EnableConfigServer注解在 Spring boot 应用中非常简单的嵌入
- Client 端:通过接口获取配置数据并初始化自己的应用
Spring Cloud Bus(基于MQ的,支持RabbitMq/Kafka) 是Spring Cloud中的消息 总线方案,Spring Cloud Config + Spring Cloud Bus 结合可以实现配置信息的自动更新。
7、Spring Cloud Stream消息驱动组件
Spring Cloud Stream 消息驱动组件帮助我们更快速,更方便,更友好的去构建消息 驱动微服务的。
当时定时任务和消息驱动的一个对比。(消息驱动:基于消息机制做一些事情) MQ:消息队列/消息中间件/消息代理,产品有很多,ActiveMQ、RabbitMQ、RocketMQ、Kafka。
本质:屏蔽掉了底层不同MQ消息中间件之间的差异,统一了MQ的编程模型,降低了学习、开发、维护MQ的成本。
Spring Cloud Stream 是一个构建消息驱动微服务的框架。应用程序通过inputs(相 当于消息消费者consumer)或者outputs(相当于消息生产者producer)来与 Spring Cloud Stream中的binder对象交互,而Binder对象是用来屏蔽底层MQ细节 的,它负责与具体的消息中间件交互。
Binder绑定器是Spring Cloud Stream 中非常核心的概念,就是通过它来屏蔽底层 不同MQ消息中间件的细节差异,当需要更换为其他消息中间件时,我们需要做的就 是更换对应的Binder绑定器而不需要修改任何应用逻辑(Binder绑定器的实现是框架内置的,Spring Cloud Stream目前支持Rabbit、Kafka两种消息队列)。
8、其它:常⻅问题及解决方案
Eureka 服务发现慢的原因
Eureka 服务发现慢的原因主要有两个,一部分是因为服务缓存导致的,另一部分是 因为客户端缓存导致的。
服务端缓存
- 服务注册到注册中心后,服务实例信息是存储在注册表中的,也就是内存中。但 Eureka为了提高响应速度,在内部做了优化,加入了两层的缓存结构,将Client需要 的实例信息,直接缓存起来,获取的时候直接从缓存中拿数据然后响应给 Client。 第一层缓存是readOnlyCacheMap,readOnlyCacheMap是采用 ConcurrentHashMap来存储数据的,主要负责定时与readWriteCacheMap进行数 据同步,默认同步时间为 30 秒一次。
- 第二层缓存是readWriteCacheMap,readWriteCacheMap采用Guava来实现缓 存。缓存过期时间默认为180秒,当服务下线、过期、注册、状态变更等操作都会清除此缓存中的数据。
- Client获取服务实例数据时,会先从一级缓存中获取,如果一级缓存中不存在,再从二级缓存中获取,如果二级缓存也不存在,会触发缓存的加载,从存储层拉取数据 到缓存中,然后再返回给 Client。
- Eureka 之所以设计二级缓存机制,也是为了提高 Eureka Server 的响应速度,缺点是缓存会导致 Client 获取不到最新的服务实例信息,然后导致无法快速发现新的服 务和已下线的服务。
- 了解了服务端的实现后,想要解决这个问题就变得很简单了,我们可以缩短只读缓 存的更新时间(eureka.server.response-cache-update-interval-ms)让服务发现 变得更加及时,或者直接将只读缓存关闭(eureka.server.use-read-only- response-cache=false),多级缓存也导致C层面(数据一致性)很薄弱。Eureka Server 中会有定时任务去检测失效的服务,将服务实例信息从注册表中移 除,也可以将这个失效检测的时间缩短,这样服务下线后就能够及时从注册表中清除。
客户端缓存 :客户端缓存主要分为两块内容,一块是 Eureka Client 缓存,一块是 Ribbon 缓存。
Eureka Client 缓存
EurekaClient负责跟EurekaServer进行交互,在EurekaClient中的 com.netflix.discovery.DiscoveryClient.initScheduledTasks() 方法中,初始化了一 个 CacheRefreshThread 定时任务专⻔用来拉取 Eureka Server 的实例信息到本 地。
所以我们需要缩短这个定时拉取服务信息的时间间隔(eureka.client.registryFetchIntervalSeconds)来快速发现新的服务。
Ribbon 缓存
Ribbon会从EurekaClient中获取服务信息,ServerListUpdater是 Ribbon中负责服务实例更新的组件,默认的实现是PollingServerListUpdater,通过 线程定时去更新实例信息。定时刷新的时间间隔默认是30秒,当服务停止或者上线 后,这边最快也需要30秒才能将实例信息更新成最新的。我们可以将这个时间调短一点,比如3秒。
刷新间隔的参数是通过 getRefreshIntervalMs 方法来获取的,方法中的逻辑也是从 Ribbon 的配置中进行取值的。
将这些服务端缓存和客户端缓存的时间全部缩短后,跟默认的配置时间相比,快了 很多。我们通过调整参数的方式来尽量加快服务发现的速度,但是还是不能完全解 决报错的问题,间隔时间设置为3秒,也还是会有间隔。所以我们一般都会开启重试功能,当路由的服务出现问题时,可以重试到另一个服务来保证这次请求的成功。
Spring Cloud 各组件超时
Ribbon
如果采用的是服务发现方式,就可以通过服务名去进行转发,需要配置 Ribbon的超时。Rbbon的超时可以配置全局的ribbon.ReadTimeout和 ribbon.ConnectTimeout。也可以在前面指定服务名,为每个服务单独配置,比如 user-service.ribbon.ReadTimeout。其次是Hystrix的超时配置,Hystrix的超时时间要大于Ribbon的超时时间,因为 Hystrix将请求包装了起来,特别需要注意的是,如果Ribbon开启了重试机制,比如 重试3 次,Ribbon 的超时为 1 秒,那么 Hystrix 的超时时间应该大于 3 秒,否则就 会出现 Ribbon 还在重试中,而 Hystrix 已经超时的现象。
Hystrix
Hystrix全局超时配置就可以用default来代替具体的command名称。 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=30 00 如果想对具体的 command 进行配置,那么就需要知道 command 名称的生成规则,才能准确的配置。
如果我们使用 @HystrixCommand 的话,可以自定义 commandKey。如果使用 FeignClient的话,可以为FeignClient来指定超时时间: hystrix.command.UserRemoteClient.execution.isolation.thread.timeoutInMillis econds = 3000
如果想对FeignClient中的某个接口设置单独的超时,可以在FeignClient名称后加上 具体的方法: hystrix.command.UserRemoteClient#getUser(Long).execution.isolation.thread. timeoutInMilliseconds = 3000
Feign
Feign本身也有超时时间的设置,如果此时设置了Ribbon的时间就以Ribbon 的时间为准,如果没设置Ribbon的时间但配置了Feign的时间,就以Feign的时间为 准。Feign的时间同样也配置了连接超时时间(feign.client.config.服务名 称.connectTimeout)和读取超时时间(feign.client.config.服务名 称.readTimeout)。
建议,我们配置Ribbon超时时间和Hystrix超时时间即可。
四、Spring Cloud高级进阶
1、分布式链路追踪技术 Sleuth + Zipkin
分布式链路追踪技术核心思想:
记录日志,作为一个完整的技术,分布式链路追踪也有自己的理论和概念微服务架构中,针对请求处理的调用链可以展现为一棵树,示意如下:
上图标识一个请求链路,一条链路通过TraceId唯一标识,span标识发起的请求信 息,各span通过parrentId关联起来 Trace:服务追踪的追踪单元是从客户发起请求(request)抵达被追踪系统的边界开始,到被追踪系统向客户返回响应(response)为止的过程。
Trace ID: 为了实现请求跟踪,当请求发送到分布式系统的入口端点时,只需要服 务跟踪框架为该请求创建一个唯一的跟踪标识Trace ID,同时在分布式系统内部流转 的时候,框架失踪保持该唯一标识,直到返回给请求方。一个Trace由一个或者多个Span组成,每一个Span都有一个SpanId,Span中会记录 TraceId,同时还有一个叫做ParentId,指向了另外一个Span的SpanId,表明父子 关系,其实本质表达了依赖关系。
Span ID: 为了统计各处理单元的时间延迟,当请求到达各个服务组件时,也是通过 一个唯一标识Span ID来标记它的开始,具体过程以及结束。对每一个Span来说, 它必须有开始和结束两个节点,通过记录开始Span和结束Span的时间戳,就能统计 出该Span的时间延迟,除了时间戳记录之外,它还可以包含一些其他元数据,比如 时间名称、请求信息等。
每一个Span都会有一个唯一跟踪标识 Span ID,若干个有序的 span 就组成了一个 trace。Span可以认为是一个日志数据结构,在一些特殊的时机点会记录了一些日志信息, 比如有时间戳、spanId、TraceId,parentIde等,Span中也抽象出了另外一个概 念,叫做事件,核心事件如下
- CS :client send/start 客户端/消费者发出一个请求,描述的是一个span开始
- SR: server received/start 服务端/生产者接收请求 SR-CS属于请求发送的网络延 迟
- SS: server send/finish 服务端/生产者发送应答 SS-SR属于服务端消耗时间
- CR:client received/finished 客户端/消费者接收应答 CR-SS表示回复需要的时 间(响应的网络延迟)
Spring Cloud Sleuth (追踪服务框架)可以追踪服务之间的调用,Sleuth可以记录 一个服务请求经过哪些服务、服务处理时⻓等,根据这些,我们能够理清各微服务 间的调用关系及进行问题追踪分析。
- 耗时分析:通过 Sleuth 了解采样请求的耗时,分析服务性能问题(哪些服务调 用比较耗时)
- 链路优化:发现频繁调用的服务,针对性优化等 Sleuth就是通过记录日志的方式来记录踪迹数据的
我们往往把Spring Cloud Sleuth 和 Zipkin 一起使用,把 Sleuth 的数据信 息发送给 Zipkin 进行聚合,利用 Zipkin 存储并展示数据。
2、统一认证方案 Spring Cloud OAuth2 + JWT
微服务架构下统一认证思路
- 基于Session的认证方式: 在分布式的环境下,基于session的认证会出现一个问题,每个应用服务都需要 在session中存储用户身份信息,通过负载均衡将本地的请求分配到另一个应用 服务需要将session信息带过去,否则会重新认证。我们可以使用Session共享、 Session黏贴等方案。Session方案也有缺点,比如基于cookie,移动端不能有效使用等
- 基于token的认证方式: 服务端不用存储认证数据,易维护扩展性强, 客户端可 以把token 存在任意地方,并且可以实现web和app统一认证机制。其缺点也很 明显,token由于自包含信息,因此一般数据量较大,而且每次请求 都需要传 递,因此比较占带宽。另外,token的签名验签操作也会给cpu带来额外的处理 负担。
OAuth2开放授权协议/标准
OAuth(开放授权)是一个开放协议/标准,OAuth 2.0 的标准是 RFC 6749 文件。允许用户授权第三方应用访问他们存储 在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享 他们数据的所有内容。
允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容
角色:
- 资源所有者(Resource Owner):可以理解为用户自己
- 客户端(Client):我们想登陆的网站或应用
- 认证服务器(Authorization Server):可以理解为微信或者QQ
- 资源服务器(Resource Server):可以理解为微信或者QQ
Resource Owner在Authorization Server注册Client信息,通过Client去访问Authorization Server拿到token凭证,通过token凭证去Resource Server获取自己的资源
OAuth2的颁发Token授权方式
授权码(authorization-code) :授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
密码式(password):如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。
隐藏式(implicit):有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。
客户端凭证(client credentials):最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。
JWT令牌
JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简介 的、自包含的协议格式,用于 在通信双方传递json对象,传递的信息经过数字签名 可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公 钥/私钥对来签名,防止被篡改。
JWT令牌结构:
JWT令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz
Header:头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或 RSA),例如
{ "alg" : "HS256" , "typ" : "JWT" }
将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。 Payload
第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存 放jwt提供的现成字段,比 如:iss(签发者),exp(过期时间戳), sub(面向的 用户)等,也可自定义字段。 此部分不建议存放敏感信息,因为此部分可以解 码还原原始内容。 最后将第二部分负载使用Base64Url编码,得到一个字符串 就是JWT令牌的第二部分。 一个例子:
{ "sub" : "1234567890" , "name" : "John Doe" , "iat" : 1516239022 }
Signature
第三部分是签名,此部分用于防止jwt内容被篡改。 这个部分使用base64url将 前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声 明 签名算法进行签名。
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
base64UrlEncode(header):jwt令牌的第一部分。
base64UrlEncode(payload):jwt令牌的第二部分。
secret:签名所使用的密钥。
五、第二代Spring Cloud核心组件
第一代 Spring Cloud (主要是 SCN)很多组件已经进入停更维护模式。 Spring Cloud:Netflix,Spring官方,SCA(被Spring官方认可) 注意:市场上主要使用的还是SCN,SCA一套框架的集合
Alibaba 更进一步,搞出了Spring Cloud Alibaba(SCA),SCA 是由一些阿里巴巴 的开源组件和云产品组成的,2018年,Spring Cloud Alibaba 正式入住了 Spring Cloud 官方孵化器。
Nacos(服务注册中心、配置中心) Sentinel哨兵(服务的熔断、限流等) Dubbo RPC/LB Seata分布式事务解决方案
1、SCA Nacos 服务注册和配置中心
Nacos (Dynamic Naming and Configuration Service)是阿里巴巴开源的一个针 对微服务架构中服务发现、配置管理和服务管理平台。
Nacos就是注册中心+配置中心的组合
Nacos功能特性
- 服务发现与健康检查
- 动态配置管理
- 动态DNS服务
- 服务和元数据管理(管理平台的⻆度,nacos也有一个ui⻚面,可以看到注册的 服务及其实例信息(元数据信息)等),动态的服务权重调整、动态服务优雅下线
服务 (Service)
服务是指一个或一组软件功能(例如特定信息的检索或一组操作的执行),其目的是不同的客户端可以为不同的目的重用(例如通过跨进程的网络调用)。Nacos 支持主流的服务生态,如 Kubernetes Service、gRPC|Dubbo RPC Service 或者 Spring Cloud RESTful Service。
服务注册中心 (Service Registry)
服务注册中心,它是服务,其实例及元数据的数据库。服务实例在启动时注册到服务注册表,并在关闭时注销。服务和路由器的客户端查询服务注册表以查找服务的可用实例。服务注册中心可能会调用服务实例的健康检查 API 来验证它是否能够处理请求。
服务元数据 (Service Metadata)
服务元数据是指包括服务端点(endpoints)、服务标签、服务版本号、服务实例权重、路由规则、安全策略等描述服务的数据。
服务提供方 (Service Provider)
是指提供可复用和可调用服务的应用方。
服务消费方 (Service Consumer)
是指会发起对某个服务调用的应用方。
配置 (Configuration)
在系统开发过程中通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如 WAR,JAR 包等)更好地和实际的物理运行环境进行适配。配置管理一般包含在系统部署的过程中,由系统管理员或者运维人员完成这个步骤。配置变更是调整系统运行时的行为的有效手段之一。
配置管理 (Configuration Management)
在数据中心中,系统中所有配置的编辑、存储、分发、变更管理、历史版本管理、变更审计等所有与配置相关的活动统称为配置管理。
名字服务 (Naming Service)
提供分布式系统中所有对象(Object)、实体(Entity)的“名字”到关联的元数据之间的映射管理服务,例如 ServiceName -> Endpoints Info, Distributed Lock Name -> Lock Owner/Status Info, DNS Domain Name -> IP List, 服务发现和 DNS 就是名字服务的2大场景。
配置服务 (Configuration Service)
在服务或者应用运行过程中,提供动态配置或者元数据以及配置管理的服务提供者。
2、领域模型
数据模型
Nacos 数据模型 Key 由三元组唯一确定, Namespace默认是空串,公共命名空间(public),分组默认是 DEFAULT_GROUP。
服务领域模型:
Namespace + Group + Service 如同 Maven 中的GAV坐标,GAV坐标是为了锁定Jar,二这里是为了锁定服务。
配置领域模型:
Namespace + Group + DataId 如同 Maven 中的GAV坐标,GAV坐标是为了锁定Jar,二这里是为了锁定配置文件。
2、Sentinel 分布式系统的流量防卫兵
Sentinel 具有以下特征:
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场 景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、 集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到 接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例 如与 Spring Cloud、Dubbo的整合。您只需要引入相应的依赖并进行简单的配 置即可快速地接入 Sentinel。
- 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过 实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
Sentinel 的主要特性:
Sentinel 关键概念
概念名称 概念描述
资 源 |
它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或 由应用程序调用的其它应用提供的服务,甚至可以是一段代码。我们请求 的API接口就是资源 |
规 则 |
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。 |
Sentinel 流量规则模块:
系统并发能力有限,比如系统A的QPS支持1个,如果太多请求过来,那么A就应该进行流量控制了,比如其他请求直接拒绝。
资源名:默认请求路径
针对来源:Sentinel可以针对调用者进行限流,填写微服务名称,默认default(不 区分来源)
阈值类型/单机阈值
- QPS:(每秒钟请求数量)当调用该资源的QPS达到阈值时进行限流
- 线程数:当调用该资源的线程数达到阈值的时候进行限流(线程处理请求的时候,如果说业务逻辑执行时间很⻓,流量洪峰来临时,会耗费很多线程资源,这些线程资源会堆积,最终可能造成服务不可用,进一步上游服务不可用,最终可能服务雪崩)
是否集群:是否集群限流
流控模式:
- 直接:资源调用达到限流条件时,直接限流
- 关联:关联的资源调用达到阈值时候限流自己
- 链路:只记录指定链路上的流量
流控效果:
- 快速失败:直接失败,抛出异常Warm Up:根据冷加载因子(默认3)的值,从阈值/冷加载因子,经过预热时⻓, 才达到设置的QPS阈值
- 排队等待:匀速排队,让请求匀速通过,阈值类型必须设置为QPS,否则无效
流控模式之关联限流
关联的资源调用达到阈值时候限流自己,比如用户注册接口,需要调用身份证校验接口(往往身份证校验接口),如果身份证校验接口请求达到阈值,使用关联,可以对用户注册接口进行限流。
Sentinel 降级规则模块:
流控是对外部来的大流量进行控制,熔断降级的视⻆是对内部问题进行处理。Sentinel 降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比 例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源 而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调 用都自动熔断.
策略
Sentinel不会像Hystrix那样放过一个请求尝试自我修复,就是明明确确按照时间窗 口来,熔断触发后,时间窗口内拒绝请求,时间窗口后就恢复。
RT(平均响应时间)
当 1s 内持续进入 >=5 个请求,平均响应时间超过阈值(以 ms 为单位),那么 在接下的时间窗口(以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛 出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出 此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 - Dcsp.sentinel.statistic.max.rt=xxx 来配置。
异常比例
当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值之后, 资源进入降级状态,即在接下的时间窗口(以 s 为单位)之内,对这个方法的调 用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0] ,代表 0% - 100%。
异常数
当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口 是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔 断状态。
时间窗口 >= 60s
Sentinel 自定义兜底逻辑
- @SentinelResource注解类似于Hystrix中的@HystrixCommand注解
- @SentinelResource注解中有两个属性需要我们进行区分,blockHandler属性用来 指定不满足Sentinel规则的降级兜底方法,fallback属性用于指定Java运行时异常兜底方法
|