微服务篇
Spring Cloud
Spring Cloud组件有哪些?
- 注册中心:Eureka/Nacos。
- 负载均衡:Ribbon。
- 服务熔断:Hystix/Sentinel。
- 远程调用:Feign。
- 服务网关:Zuul/Gateway。
服务注册和发现
eureka
服务注册:服务提供者需要把自己的信息注册到eureka,由eureka来保存这些信息。例如服务名称、IP、端口等。
服务发现:消费者向eureka拉起服务列表的信息,如果服务提供者有集群,则消费者利用负载均衡算法选择一个服务发起调用。
服务监控:服务提供者每隔30秒向eureka发送心跳,报告监控状态,若eureka90秒还没收到心跳,从eureka剔除该服务。
nacos
nacos与eureka大体相同。
不同点
- nacos支持服务端主动监测提供者状态:临时实例采用心跳检查,非临时实例采用主动检测模式。
- 临时实例心跳不正常会被剔除,非临时实例不正常不会被剔除。
- nacos支持服务列表变更的消息推送模式,服务列表更新及时。
- nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式,而eureka只用AP模式。
- nacos还支持配置中心。eureka只有注册中心。
负载均衡
当发起远程调用的时候,feign就会使用Ribbon。
Ribbon会从注册中心获取到服务的信息。然后选择一个服务调用。
Ribbon负载均衡策略
- RoundRobinRule:轮询。
- WeightedResponseTimeRule:按照权重来选择服务器,响应时间越长,权重越小。
- RandomRule:随机。
- ZoneAvoidanceRule:以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器分类,这个Zone可以理解为一个机房、一个机架等。然后对Zone内多个服务做轮询(默认)。
- BestAvailableRule:忽略那些短路的服务器,并选择并发数较低的服务器。
- RetryRule:重试机制的选择逻辑。
- AvailabilityFilteringRule:可用性敏感策略,先过滤掉非健康的,再选择连接数较小的实例。
自定义负载均衡
- 创建一个类实现
IRule接口,然后注入到Spring容器中。全局生效。 - 在客户端yaml中,可以配置某一个服务的负载均衡策略。局部生效。
服务雪崩
一个服务失败,导致整个链路服务都失败。
降级、熔断(解决)
服务降级:服务降级是服务自我保护的一种方式,或者保护下游的一种方式,用于确保服务不会因为请求突增而崩溃。一般和Fegin接口整合,编写降级逻辑。
熔断:默认是关闭的,需要手动打开。当10秒内请求失败率超过50%,就会触发熔断。之后每过5秒请求一下服务,若服务不可用则保存熔断的状态,若服务可用,则关闭熔断状态。
注:服务降级是针对某个服务的某个接口的,而服务熔断是针对整个服务的。
监控
为什么需要服务监控?
- 问题定位。
- 性能分析。
- 服务关系。
- 服务告警。
skywalking
- skywalking主要可以监控接口、服务、物理实例的一些状态。特别是在压测中可以看到众多服务中有哪些服务和接口比较慢,可以针对性的分析和优化。
- 还可以设置告警规则。
业务相关
限流(预防)
为什么要限流?
- 并发大
- 恶意刷接口。
漏桶算法
体现在nginx中。


令牌桶算法
网关限流

分布式事务
分布式理论CAP、BASE
CAP理论
1998年,加州大学的计算机科学家Eric Brewer提出,分布式系统又三个指标:
- Consistency(一致性):所有节点在同一时刻的数据是相同的,即更新操作执行结束并响应用户完成后,所有节点存储的数据会保持相同。
- Availability(可用性):用户访问集群任意节点健康节点,必须能得到响应,而不是超时或拒绝。
- Partition tolerance(分区容错性):Partition,因为网络故障或者其他原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。tolerance,在集群出现区分时,整个系统也要持续对外提供服务。
结论:
- 分布式系统节点之间肯定是需要网络连接的,分区(P)是必须存在的。
- CAP的理论:一旦P发生了,此时需要在CAP中进行权衡,要么CP,要么AP。大部分时间,P是不会发生的,CAP理论用于指导系统设计时需要衡量的因素,而非是绝对的选择。
- 如果保证访问的高可用性(A),就要放弃强一致性(C) -> AP。
- 如果保证访问的强一致性(C),就要放弃高可用性(A) -> CP。
PACELC理论
PACELC是一个用于描述分布式系统中的一致性和可用性之间权衡关系的概念。
PACELC是由Eric Brewer在2012年提出的,它基于CAP定理的思想,进一步深化了对于分布式系统中的一致性和可用性的理解
- P(Partition tolerance,分区容忍性):分布式系统在面对网络分区(网络故障或通信故障)时,仍然能够继续运行,即容忍分区。分区是指系统中的节点之间无法相互通信或通信延迟过高的情况。
- A(Availability,可用性):分布式系统在面对故障时,仍然能够提供服务并保证数据的可访问性。即使部分节点出现故障,系统仍然能够响应客户端的请求。
- C(Consistency,一致性):分布式系统在面对分区时,能够保持数据的一致性。一致性指的是系统中的所有节点在同一时间点上看到的数据是一致性的。
- E(Eventual Consistency,最终一致性):分布式系统在面对分区时,由于网络延迟或异步复制等原因,可能会导致节点之间数据的不一致,但最终会达到一致状态。
- L(Latency,延迟):分布式系统的响应时间。在一些情况下,为了提高系统的响应速度,可能会牺牲一致性或者可用性。
PACELC理论定义:
如果有网络分区发生,系统就必须在A和C之间进行选择。当系统运行在无网络分区的情况下(正常),系统需要在L和C之间取得平衡。
BASE理论
BASE理论的核心思想是最终一致性,即使无法做到强一致性(Strong Consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual Consistency)。
-
Basically Available(基本可用):不追求CAP中的“任何时候,读写都是成功的”,而是系统能够基本运行,一直提供服务。基本可用强调了分布式系统出现不可预知故障的时候,允许损失部分可用性,相比正常的系统,可能是响应时间延长,或者服务被降级。
-
Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态。
软状态可以对应ACID事务中的原子性,在ACID的事务中,实现的是强一致性,即要么全做,要么全都不做,所有用户看到的数据一致。其中的原子性(Atomicity)要求多个节点的数据副本都是一致的,强调数据的一致性。
原子性可以理解为一种“硬状态”,软状态则是允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同的节点的数据副本存在数据延迟。
-
Eventually Consistent(最终一致性):数据不可能一直是软状态,必须在一个时间期限之后达到各个节点的一致性,在期限过后,应当保证所有副本保持数据的一致性,也就是达到数据的最终一致性。
在系统设计中,最终一致性实现的时间取决于网络延迟、系统负载、不同的存储选型、不同数据复制方案设计等因素。
解决分布式事务的思想和模型
- 最终一致性:各分支事务分别执行并提交,如果有不一致的情况,再想办法恢复数据(AP)。
- 强一致性:各分支事务执行完业务不提交,等待彼此结果。而后统一提交或回滚(CP)。
分布式事务解决方案
seata
seata事务管理中有三个重要的角色:
- TC(Transaction Coordinator)- 事务协调者:维护全局事务和分支事务的状态,协调全局事务提交或回滚。
- TM(Transaction Manager)- 事务管理器:定义全局事务的范围、开启全局事务、提交或回滚全局事务。
- RM(Resource Manager)- 资源管理器:管理分支事务处理的资源,与TC交谈以及注册分支事务和报告分支事务。

XA模式
RM第一阶段的工作:
- 注册分支事务到TC。
- 执行分支业务SQL,但不提交。
- 报告执行结果到TC。
TC第二阶段的工作:
- 检测各分支事务执行状态。
- 全成功,通知所有RM提交事务。
- 有失败,通知所有RM回滚事务。
TM第二阶段的工作:
- 接受TC指令,提交或回滚。

AT模式
RM第一阶段的工作:
- 注册分支事务。
- 记录undo-log(数据快照)
- 执行业务SQL并提交。
- 报告事务状态
RM第二阶段的工作:
- 提交:删除undo-log。
- 回滚:根据undo-log恢复数据到更新前。

TCC模式
- Try:资源的检查和预留。
- Confirm:完成资源操作业务;要求Try成功Confirm一定要成功。
- Cancel:预留资源释放。
以上三步需要编写代码

MQ分布式事务
幂等
幂等:多次调用方法或接口不会改变业务状态,可以保证重复调用和单次调用结果一致。
需要幂等场景:
- 用户重复点击
- MQ消息重复
- 应用使用失败或超时重试机制
分布式服务接口
Restful API的角度来看。
| 请求方式 | 说明 |
|---|---|
| GET | 查询,天然幂等。 |
| POST | 新增,不是幂等。 |
| PUT | 更新,如果是绝对值更新,则是幂等。若是增量更新,而不是幂等。 |
| DELETE | 删除,根据唯一值删除,是幂等。 |
解决
数据库唯一索引
只可以解决新增操作。
token+redis
可以解决新增,修改。性能较好。
- 第一次请求,生成一个唯一token存储redis并返回给前端。
- 第二次请求,业务处理,携带之前的token,到redis进行验证,如果存在,可以执行业务并删除token。若不存在,则之间返回,不处理业务。

分布式锁
可以解决新增,修改。性能较低。
使用Redission加一个锁。
使用关键点:
- 快速失败(抢不到锁的线程)。
- 控制锁的粒度,越小越好。
分布式任务调度
xxl-job
解决的问题:
- 解决集群任务的重复执行。
- cron表达式定义灵活,在页面上。
- 定时任务失败了,重试和统计。
- 任务量大,分片执行。
路由策略有哪些?
找机器执行的方式就是路由策略。
- ROUND(轮询)。
- FAILOVER(故障转移):按照顺序依次进行心跳监测,选择第一个心跳检测成功的机器发起调度。
- SHARDING_BROADCAST(分片广播):广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数;可以根据分片参数开发分片任务。
- FIRST(第一个):固定选择第一个机器。
- LAST(最后一个):固定选择最后一个机器。
- RANDOM(随机):随机选择在线的机器。
- CONSISTENT_HASH(一致性HASH):每个任务按照Hash算法固定选择某一台机器,且所有任务均匀散列在不同机器上。
- LEAST_FREQUENTLY_USED(最不经常使用):使用频率最低的机器优先选举。
- LEAST_RECENTLY_USED(最近最久未使用):最久未使用的机器优先被选举。
- BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,选择第一个空闲检测成功的机器发起调度。
任务执行失败怎么解决?
故障转移+失败重试,查看日志分析+设置邮件告警。
有大量任务需要同时执行,怎么解决。
让多个实例一块去执行(部署集群),路由策略选择分片广播。
分片参数
- index:当前分片序号(0),执行器集群列表当前执行器的序号。
- total:总分片数,执行器集群的总机器数量。