Spring Cloud
○ 是一套规范,而非框架
○ 规范应该要有哪些功能组件,各组件间如何配合,共同完成什么事情
微服务规范
一、核心目标
- 简化分布式系统【基础设施】的开发 - 将经得起考验的服务框架组合起来,透过 Spring Boot 风格封装,屏蔽底层 复杂配置 与原理
二、概念
-
服务注册 : 服务提供者 将 IP、端口、访问协议 登记到 注册中心
-
服务发现 : 服务消费者 从 注册中心 获取到较为实时的服务列表,根据访问策略进行访问
-
负载均衡 : 将请求压力分散到多个服务器,以提高服务的性能、可靠性
-
雪崩效应 : 服务的扇出链路上,某个服务响应时间过长或不可用,导致该服务占用越来越多系统资源,进而引起系统崩溃
○ 扇入 : 服务被调用的次数。扇入大,该服务复用性高,好事
○ 扇出 : 服务调用其他服务的个数。扇出大,该服务业务逻辑复杂,不一定是好事
-
限流 : 限制请求服务提供者的数量 - 问题发生前
-
熔断 : 上游服务为了保护下游服务,暂时切断对下游服务的调用 - 问题发生后
-
降级 : 返回兜底数据(默认值) - 问题发生后
熔断、降级 通常一起使用
-
链路追踪 : 对一次请求涉及到的多个服务链路进行 日志纪录、性能监控
三、应用架构演进
1. 单体 应用架构
- 将所有功能模块都放在一个工程中
- 优点
- 开发快
- 架构简单
- 易测试
- 易布署
- 缺点
- 对海量用户处理能力有限
- 程序复杂度越高,开发效率越低
- 生产环境发生重大 BUG,或单一功能负载过重,将导致服务全数停摆
- 代码量增加,编译、启动 效率下降
2. 垂直 应用架构
-
对应用模块做垂直划分 - 【划分目标】业务之间尽量互不影响
-
优点
-
实现 流量分担
-
可以针对不同功能模块进行优化
-
方便 水平扩展
○ 水平扩展 : 增加服务器数量,扩充系统性能
○ 垂直扩展 : 提升单机处理能力
-
提高 容错率
-
提高 功能迭代效率
-
不同服务可采用不同的编程语言
-
-
缺点
- 当服务 IP 或 端口 改变,调用方需手动更新
- 服务间调用 方式、协议 不统一 - HttpClient、WebService
- 服务监控不到位 - 服务状态、调用成功率、调用失败率、调用耗时
3. SOA 应用架构(微服务)
Service-Oriented Architecture 面向服务架构
-
根据实际业务,将系统 水平、垂直 拆分成各自 独立布署 的模块,模块间相互独立
-
优点
- 拥有 垂直应用架构 的优点
- 耦合度更低
- 底层模块可重用
- 适合敏捷开发
-
缺点
- 对架构师能力要求高
- 服务管理困难
- 程序调试、链路追踪困难
四、核心组件
-
注册中心 - Eureka - Nacos
-
客户端负载均衡 - Ribbon - Spring Cloud Loadbalancer
-
熔断器 - Hystrix - Sentinel
-
网关 - Zuul - Spring Cloud Gateway
-
配置中心 - Spring Cloud Config - Nacos
-
服务调用 - Feign - Dubbo RPC
-
消息驱动 - Spring Cloud Stream
-
链路追踪 - Spring Cloud Sleuth/Zipkin
-
分布式事务 - Seata
五、Eureka 注册中心
基于 AP 模式设计,使用二级缓存机制提高响应速度,可能导致服务发现缓慢问题,Eureka Server 30秒、Eureka Client 30 秒、Ribbon 30 秒
1. 功能
- 解偶服务 提供者 与 消费者
- 动态管理 服务提供者 数量、状态、地址
2. 角色
- Eureka Server
- 保存 服务提供者 数量、状态、地址
- 定时将失效服务进行剃除 - 【默认】60 秒
- 一定时间内没收到 Eureka Client 的心跳,则认为该服务失效 - 【默认】90 秒
- Eureka Server 之间透过复制方式完成 服务注册列表 同步
- 当 15 分钟内,有超过 85% 的 Client 没有正常发送心跳,则进入自我保护模式
- Eureka Client
- 服务启动时,向 Eureka Server 注册自己
- 定时向 Eureka Server 发送心跳 - 【默认】30 秒
- 定时向 Eureka Server 获取 服务注册列表 - 【默认】30 秒
- 会缓存 服务提供者 信息,来保证即使 Eureka Server 皆当机,也能正常调用服务提供者
- 当服务正常关闭时,会发送服务下线的 REST 请求给 Eureka Server
3. 元数据
- 标准元数据
- 发布在服务注册表中,用于服务间调用
- 主机名
- IP 地址
- 端口号
- 自定义元数据
- 可以在 Client 端中访问
- 符合 Key / Value 的存储格式,使用 eureka.instance.metadata-map 定义
4. 自我保护模式
- 不会剔除任何服务实例
- 接受新服务的 注册、查找 请求,但不会同步到其他节点上
- 使用 eureka.server.enable-self-preservation 设置
- 【默认】开启
- 【建议】开启
六、Ribbon 客户端负载均衡
【原理】给 RestTemplate 添加拦截器,将服务名替换成 IP 地址
1. 概念
-
服务端负载均衡
- 请求到达负载均衡器,根据算法将请求路由到目标服务器
- 负载均衡算法在 服务端 运行
- Nginx、F5
-
客户端负载均衡
-
客户端拥有服务器地址列表,请求在客户端根据负载均衡算法选择一个服务器进行访问,注册中心仅负责
提供服务端地址
-
负载均衡算法在 客户端 运行
-
Ribbon
-
2. 负载均衡策略
- 【默认】RoundRobinRule 轮询 - 默认超过 10 次获取到的 Server 都不可用,将返回一个空 Server
- RandomRule 随机 - 如果随机到的 Server 为 null 或 不可用,则不断循环选取
- RetryRule 重试 - 时限内轮询重试
- BestAvailableRule 最小连接数 - 选取可用且连接数最小的
- AvailabilityFilteringRule 可用过滤 - 轮询 Server,并判断是否超时、连接数是否超限
- ZoneAvoidanceRule 区域权衡 - 轮询 Server,并判断是否超时、连接数是否超限、区域是否符合
七、Hystrix 熔断器
1. 功能
-
资源隔离 : 对每个管理的资源都维护一个小型的线程池(舱壁模式),如果该资源对应的线程池已满,则发往该资源的请求立刻被拒绝,而非排队,以加速失败判定
-
回退机制 : 当请求 失败、超时、被拒绝、断路器启动 时,运行回退逻辑
回退逻辑由开发人员定义,如 : 返回缺省值
-
跳闸机制 : 当某服务的错误率超过阈值,则停止请求该服务一段时间,之后进入自我修复阶段
超时时间应大于 Ribbon 的超时时间,避免 Ribbon 还在重试,但 Hystrix 已超时
-
自我修复 : 当断路器启动一段时间后,会自动进入半开状态(少量测试服务是否正常)
-
监控 : 近乎实时地监控运行指针与配置变化 - 成功、失败、超时、拒绝
八、Feign 远程调用组件
Fegin = RestTemplate (简化HTTP请求发送) + Ribbon (客户端负载均衡) + Hystrix (熔断器)
- 【默认】请求超时处理时长 1 秒
- 只要达到 Feign 或 Hystrix 其中一个超时时长,将会进行熔断
- 可以自定义降级处理类,返回默认值
- 可以设置超时时间,但如果 Ribbon 已配置则以 Ribbon 为准,故建议设置 Ribbon、Hystrix 超时时间即可
- 请求日志
- 【默认】NONE : 不显示任何日志,性能最佳
- BASIC : 仅记录 请求方法、URL、响应状态码、运行时间 - 生产问题追踪
- HEADERS : 在 BASIC 级别上,纪录请求和响应的 Header
- FULL : 在 HEADERS 级别上,纪录 Body 和 元数据
九、GateWay 网关组件
○ 异步非阻塞,基于 Reactor 模型
○ 高可用 : 透过 Nginx 实现
1. 功能
-
反向代理
- 路径重写
- 动态路由 - 从注册中心获取服务列表并访问
-
过滤器
-
鉴权
-
流量控制
-
日志输出
-
2. 角色
- 路由 Route
- 网关基础的工作单元,将请求转发到对应的服务上
- 由 ID、断言、过滤器 组成
- 如果 断言 为 true 则匹配该路由
- 断言 Predicates
- 是否符合路由的判断条件
- 匹配条件
- 路径
- 时间
- Cookie
- Header
- Host
- Method
- 请求参数
- 远程地址
- 过滤器 Filter
- 在 请求前 或 请求后 运行业务逻辑
- 范围
- GateWayFilter : 应用到单个路由上
- GlobalFilter : 应用到所有路由上 - 黑名单
- 类型
- Pre
- 参数校验
- 权限校验
- 流量监控
- 日志输出
- 协议转换
- Post
- 响应头、响应内容 修改
- 日志输出
- 流量监控
- Pre
十、Spring Cloud Config 配置中心
1. 功能
- 集中配置管理 - 让配置一次更改,处处生效
- 为不同环境提供不同配置 - 开发、测试、生产
- 运行期间动态调整配置 - 连接池大小
2. 概念
-
【默认】使用 Git 存储配置文档内容
-
配置文档命名规则
-
{application}-{profile}.yml
-
{application}-{profile}.properties
○ application 为应用名称
○ profile 为环境 - 开发、测试、生产
-
-
刷新
- 手动刷新
- 自动刷新
十一、Spring Cloud Stream 消息驱动组件
○ 屏蔽底层不同 MQ 间的差异,降低学习、开发、维护 成本
○ 支持 RabbitMQ、Kafka
1. 概念
- 内置信道默认名称为 input、output,可以透过自定义信道方式扩展
- 消费分组 : 一个消息只能被组内的其中一个成员消费 - 可以避免重复消费
2. 注解
- @Output 生产者 : 输出信道,消息将透过该信道 离开 应用进程
- @Input 消费者 : 输入信道,消息将透过该信道 进入 应用进程
- @StreamListener 消费者监听器 : 监听消费者队列的消息
- @EnableBinding 绑定 : 将 Exchange 与 Channel 进行绑定
十二、Spring Cloud Sleuth + Zipkin 链路追踪
1. 功能
- 了解各个服务之间的调用关系
- 纪录 链路、处理单元 时间,用于分析瓶颈节点
- 进行故障发现
2. 概念
- Trace : 请求 从抵达系统边界 到 离开系统边界 的过程 - 由多个 Span 组成
- Trace ID : 整个请求链路的 ID
- Span ID : 处理单元的 ID
- Parent ID : 上游处理单元的 ID
十三、Spring Cloud OAuth2 + JWT 统一认证方案
1. 认证方案
- Session 共享
- 缺点 - 基于 Cookie,移动端不能有效使用
- Token
- 优点
- 服务端不用存储数据
- 扩展性强
- Web、App 皆可使用
- 缺点
- 占用带宽
- 验签操作增加 CPU 负担
- 优点
2. OAuth2
允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息
角色
- 资源拥有者 Resource Owner : 用户自己
- 客户端 Client : 公司网站
- 认证服务器 Authorization Server : Google 公司
- 资源服务器 Resource Server : Google 公司
运行流程
- 客户端 向 资源拥有者 请求授权 (弹出授权登录页面)
- 资源拥有者 确认授权 (输入帐号密码)
- 认证服务器 收到授权许可
- 认证服务器 向 客户端 颁发 Access Token(访问令牌)
- 客户端携带 Access Token 访问 资源服务器
- 资源服务器 向 认证服务器 验证 Access Token 的有效性
- 资源服务器 返回 受保护资源 给 客户端
授权模式
- 授权码 authorization-code - 用于 第三方登录,使用起来最麻烦
- 密码 password
- 提供 帐号、密码 换取 令牌
- 用于 单点登录
- 隐藏式 implicit
- 客户端凭证 client credentials
3. 类
认证服务器
- 授权配置类
- @EnableAuthorizationServer : 开启认证服务器功能
- extends AuthorizationServerConfigurerAdapter : 继承授权配置类适配器
- configure(AuthorizationServerSecurityConfigurer security) : 设置接口访问权限
- configure(ClientDetailsServiceConfigurer clients) : 设置客户端相关信息
- configure(AuthorizationServerEndpointsConfigurer endpoints) : 设置令牌相关信息
- 令牌存储方式
- 【默认】InMemoryTokenStore : 存储在内存中
- JdbcTokenStore : 存储在关系型数据库
- JwtTokenStore : 使用 JWT 令牌,服务端不存储
- 用户配置类
- extends WebSecurityConfigurerAdapter : 继承用户配置类适配器
- configure(AuthenticationManagerBuilder auth) : 验证用户帐号密码
- PasswordEncoder : 用户密码统一加密方式
资源服务器
- 配置类
- @EnableWebSecurity : 开启资源服务器功能
- extends ResourceServerConfigurerAdapter : 继承配置类适配器
- configure(ResourceServerSecurityConfigurer resources) : 配置认证服务器信息
- configure(HttpSecurity http) : 设置不同接口是否需要验证
4. JWT
○ Json Web Token
○【核心目的】防止窜改
结构
中间使用 "." 分割
- Header
- 令牌类型
- 加密算法
- Payload
- 将有效信息进行 Base64 编码 - 不建议存放敏感信息
- Signature
- 将 Header、Payload 进行加密,作为签名
十四、Nacos 注册中心 + 配置中心
可选择使用 AP 模式 或 CP 模式
1. 功能
- 服务发现、健康检查
- 动态配置管理 - @RefreshScope
- 动态 DNS 管理
- 服务、元数据 管理
2. 概念
-
保护域值 : 健康实例数 / 总实例数
当保护域值低于设置时,说明健康实例不多,将把所有的实例(健康 + 不健康) 都返回给消费者
-
临时实例 : 由客户端发送心跳
-
持久实例 : 由 Nacos 发送心跳,且不会下线,仅做健康检测 - MySQL
-
领域模型
- Namespace 命名空间
- 环境 : 开发、测试、生产
- 不同命名空间不能互相访问
- Group 组
- 项目
- Service 服务 / DataId 配置文档
- Namespace 命名空间
-
配置文档格式
- ${prefix}-${spring.profile.active}.${file-extension}
- prefix : 默认为 spring.application.name 的值
- spring.profile.active : 为当前对应环境的 profile
- file-extension : 数据格式 - yaml、properties
十五、Sentinel 流量防卫兵
可利用 Nacos 持久化数据
1. 组成
- 核心库 : Java 客户端,不依赖任何 框架/库,对 Dubbo、Spring Cloud 有较好的支持
- 控制台 : 基于 Spring Boot 开发,可以直接运行
2. 限流方式
- 按照 资源名称
- 按照 URL
3. 阈值类型
-
QPS : 当调用该资源的 QPS 达到阈值时,进行限流
QPS : 每秒钟请求量
-
线程数 : 当调用该资源的 线程数 达到阈值时,进行限流 - 适用业务运行时间长的情况
4. 流控模式
- 直接 : 当资源达到限流条件,直接限流
- 关联 : 当关联资源调用达到阈值时,限流自己,两资源间无调用关系
- 链路 : 只针对特定的上游链路流量,限流自己,两资源间有调用关系
5. 流控效果
- 快速失败
- 直接失败,抛出异常
- 用于 一般场景
- Warm Up
- 从 阈值 / 冷加载因子(默认 3),经过预热时长,才达到设置的 QPS
- 用于 秒杀场景
- 排队等待
- 让请求匀速通过,阈值必须设置为 QPS - QPS 为 5,200 ms 放行一个请求
- 用于 削峰填谷
6. 降级规则
只有当 QPS >= 5,才会触发降级规则,时间窗口内拒绝请求,时间窗口后直接恢复
- RT 平均响应时间 - 上限 4900 ms
- 异常比例
- 异常数 - 以分钟级别统计