微服务中常见问题

Spring Cloud 组件

在这里插入图片描述
Spring Cloud五大组件有哪些?

  • Eureka:注册中心

  • Ribbon:负载均衡

  • Feign:远程调用

  • Hystrix:服务熔断

  • Zuul/Gateway:服务网关
    随着SpringCloud Alibaba在国内兴起,我们项目中使用了阿里巴巴的组件

  • 注册中心/配置中心 Nacos

  • 负载均衡 Ribbon

  • 服务调用 Feign

  • 服务保护 Sentinel

  • 服务网关 Gateway

注册中心Eurake和注册中心Nacos

在这里插入图片描述
Eurake工作原理

  1. 首先Eurake中会对所有的服务进行注册,在Eurake中保存服务提供者的基本信息
  2. 服务消费者在需要调用的时候就从Eurake中拉取服务,然后在服务的消费者内部使用负载均衡的方式选取对应的服务
  3. 然后直接去请求对应的服务
  4. Eurake与服务提供者通过心跳的方式保持监测,Eurake会定期监测服务的心跳是否存在,默认是30秒一次。一旦一个服务没有心跳,那么在Eurake中会将这些服务剔除掉。

服务注册和服务发现是什么意思?Spring Cloud如何实现服务注册发现的?

  • 我们当时采用的是Eurake作为注册中心,这个是Spring Cloud体系中的一个核心的组件
  • 服务注册:服务提供者需要把自己的信息注册在Eurake,由Eurake来保存这些信息,比如服务的名称,ip,端口等等。
  • 服务发现:消费者向Eurake拉取服务列表信息,如果服务提供者有集群,则消费者利用负载均衡的算法,选择一个进行调用
  • 服务监控:服务提供者每隔30秒向Eurake发生心跳,报告健康状态,如果Eurake服务90秒没收到心跳,从Eurake剔除当前服务。

Nacos工作原理
在这里插入图片描述
Nacos和Eurake的区别

  • Nacos和Eurake的共同点(注册中心)
    • 都支持服务的注册和服务的拉取
    • 都支持服务提供者心跳的方式做健康检测
  • Nacos和Eurake的区别
    • Nacos支持服务端主动监测提供者的状态:临时实例采用心跳模式,非临时实例采用主动检测模式
    • 临时实例心跳不正常会被剔除,非临时实例则不会剔除
    • Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
    • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式,Eurake采用AP模式
  • Nacos还支持配置中,Eurake则只是注册中心,也是选择使用Nacos的一个重要的原因

Ribbon负载均衡

  • 负载均衡Ribbon,发起远程调用Feign就会使用Ribbon
  • Ribbon的负载均衡策略有哪些?
  • 如果自定义负载均衡如何实现?
    在这里插入图片描述
    负载均衡流程
    当一个服务需要调用另一个服务的时候,发起请求,进入Ribbon,Ribbon再去注册中心区获取调用服务列表,然后使用负载均衡的策略选取一个服务,然后调用对应的服务。

负载均衡的策略有哪些?

  • RoundRobinRule:简单轮询服务列表选择服务器
  • WeightedResponseTimeRule:按照权重来选择服务器,响应时间越长,权重越小
  • RandomRule:随机选择一个可用服务器
  • RestAvailableRule:忽略哪些短路的服务器,并选择并发数较低的服务器
  • RetryRule:重试机制的选择逻辑
  • AvailabilityFilteringRule:可用性敏感策略,先过滤非健康的,再选择连接数较小的实例
  • ZoneAvoidanceRule:以区域可用服务器为基础进行服务器的选择,使用Zone对服务器进行分类,这个Zone可以理解为一个机房,一个机架,而后再对Zone内的多个服务器做轮询。

如何自定义负载均衡策略?
可以自己创建Rule接口,然后通过配置类或者配置文件即可,通过自定义IRule可以实现修改负载均衡规则,有两种方式:
在这里插入图片描述
负载均衡如何实现的?
微服务中的负载均衡使用一个组件叫做Ribbon,比如,我们在使用Feign远程调用的过程,底层的负载均衡使用了Ribbon

Ribbon负载均衡的策略有哪些?

  • RoundRobbinRule:简单轮询服务器列表选择服务器
  • WeightedResponseTimeRule:按照权重服务器,响应时间越长,权重越小
  • RandomRule:随机选择一个可用的服务器
  • ZoneAvoidanceRule:区域敏感策略,以区域可用的服务器为基础进行服务器的选择,使用Zone对服务进行分类,这个Zone可以理解为一个机房,一个机架等等,而后对Zone内的多个服务器做轮询(默认)

Spring Cloud 服务雪崩 熔断降级

在这里插入图片描述
服务雪崩效应是一种因“服务提供者的不可用”(原因)导致“服务调用者不可用”(结果),并将不可用逐渐放大的现象。

通俗的来说就是在微服务中一个服务提供方挂了之后,那么服务的调用者就会请求就会一直等待响应,然后与此同时别的消费者也同样的来请求这个服务,会导致服务的上游直接全部挂掉进而去影响服务的上上游造成雪崩的问题。

服务降级

服务降级是服务自我保护的一种方式,或者保护下游服务器的一种方式,用于确保服务不能受请求突增影响变得不可用,确保服务不会崩溃。
在这里插入图片描述
降级的逻辑,当前如果服务正常,那么就走服务接口去请求数据,如果服务不同的话,直接去对服务进行降级,访问自顶替的接口,提示“获取数据失败”。

服务熔断
Hystrix熔断机制,用于监控微服务调用的情况,默认是关闭的,如果开启需要再引导类上添加注解:
@EnableCircuitBreaker如果检测到10秒内请求失败率超过50%,就会触发熔断机制,之后每隔5秒重新尝试请求微服务,如果微服务不能响应,继续走熔断机制,如果微服务可达,则关闭熔断机制,恢复正常请求。
在这里插入图片描述
什么是服务雪崩,怎么解决这个问题?

  • 服务雪崩,一个服务失败,导致整条链路的服务都失败的情形
  • 服务降级:服务自我保护的一种方式,或者保护下游服务器的一种方式,用于确保服务不会受请求突增影响变得不可用,确保服务不会崩溃,一般实际开发中与Feign接口整合,编写降级逻辑。
  • 服务熔断:默认关闭,需要手动打开,如果监测到10秒之内请求失败率超过百分之50%,就触发熔断机制,之后间隔每5秒重新尝试请求微服务,如果微服务不能响应,继续走熔断机制,如果微服务可达关闭熔断机制,恢复正常请求。

服务降级是针对某一个接口,并不是某一个服务,而服务熔断针对的是整个服务。

Spring Cloud微服务监控

在这里插入图片描述

第一个问题:问题定位,当spring cloud中某一个微服务挂了之后,我们如何才能快速的定位到是哪一个微服务出现了问题?

第二个问题:性能分析,假如某一条请求响应的异常的慢,那么我们如何可以快速的定位到时那一条服务出现了问题呢?

第三个问题:服务的关系,如果微服务中的服务量过小的话我们可能可以快速的梳理清楚服务之间的关系,但是一旦服务量过大,几百上千个微服务那么关系式很难梳理的

第四个问题:服务告警,假如当前一个服务出现了问题,那么我们如何才能快速的知道哪一个服务出现了问题呢???

性能监控工具

  • Spring-Admin
  • prometheus+Grafana
  • zipkin
  • skywalking

后两者是链路追踪工具

Skywalking
一个分布式系统的应用程序性能检测工具(Applicatio Performance Managment),提供了完善的链路追踪能力,apache的顶级项目(前华为产品经理吴晟主导开源的)
在这里插入图片描述

  • 服务(service):业务资源应用服务器(微服务)
  • 端点(endpoint):应用系统对外暴露的功能接口(接口)
  • 实例(instance):物理机
    在这里插入图片描述
    界面展示

仪表盘主要是展示当前注册的微服务的情况,会按微服务的性能进行排序

服务追踪主要是可以展示每个微服务中的接口在响应的过程中每个步骤请求响应的耗时,可以快速的定位服务的错误

在这里插入图片描述
拓扑图可以直观的展示出服务与服务之间的关联关系,红色的服务表示不健康的服务
在这里插入图片描述
服务的告警会根据预先定义好的告警规则进行告警:

规则如下:

  1. 在过去的10分钟的3分钟内服务的平均响应时间超过1秒3次
  2. 在过去的10分钟呢服务成功率低于80%达到2次
  3. 在过去的10分钟内服务90%响应时间低于1秒达到3次
  4. 在过去10分钟内服务的响应时间超过1秒达2次
  5. 在过去10分钟内断点的响应时间超过1秒达2次

你们的微服务是怎么监控的?

我们项目中采用skywalking进行监控的

  1. skywalking主要可以监控接口,服务,物理实例的一些状态,特别是在压测的时候可以看到众多服务中哪些服务和接口比较慢,我们可以针对性的分析和优化。
  2. 我们还在skywalking设置了告警规则,特别是在项目上线之后,如果报错,我们分别设置了可以给相关负责人发送短信和邮件通知,第一时间知道项目的bug情况,第一时间修复。

微服务限流

你们的项目中有没有做过限流,怎么做的?

为什么需要限流?

并发量太大(突发流量)抢券业务

防止用户恶意刷接口

限流的实现方式

  • Tomcat:可以设置最大连接数
  • Nginx:漏铜算法
  • 网关:令牌桶算法
  • 自定义拦截器
    在这里插入图片描述
    Nginx限流

控制速率(针对突发流量)
在这里插入图片描述

  • 语法:limit_req_zone key zone rate
  • key: 定义限流对象,binary_remote_addr 就是一种key,基于客户端ip限流
  • Zone:定义共享存储区来存储访问信息,10m可以存储16wip地址访问信息
  • Rate:最大访问速率。rate=10r/s 表示每秒最多请求10个请求
  • burst=20:相当于桶的大小
  • Nodelay:快速处理
    在这里插入图片描述
    算法解释(个人)

当大批量的请求突然过来的时候,那么进入桶中算法,就快速的进行执行,响应,

没有进入桶中的算法,直接进行异常抛出处理

控制并发连接数
在这里插入图片描述

  • limit_conn perip 20:对应的key是$binary_remote_addr,表示限制单个IP同时最多能持有20个连接
  • limit_conn perserver 100:对应的key是 $server_name, 表示虚拟主机(server)同时能处理并发连接的总数

网关限流

yml配置文件中,微服务路由设置添加局部过滤器RequestRateLimiter
在这里插入图片描述
令牌桶算法
在这里插入图片描述
key-resolver:定义限流对象(ip,路径,参数),需代码实现,使用spel表达式获取

replenishRate:令牌桶每秒填充平均速率

urstCapacity:令牌桶总容量

你们的项目中有没有做过限流,怎么做的

  • 首先当时有一个活动,到了假期抢购物券优惠券,QPS最高可以达到2000,平时10-50之间,为了应对突发流量,需要做限流
  • 常规的限流手段,为了防止恶意攻击,保证系统的正常运行,我们当时系统能承受的最大的QPS是多少(压测结果)
  • nginx限流
  • 控制速率(突发流量),使用的漏桶算法来实现过滤,让请求以固定的速率处理请求,可以应对突发流量
  • 控制并发数,限制单个ip的链接数和并发链接的总数
  • 网关限流
  • 在Spring cloud gateway中支持局部过滤器RequestRateLimiter来做限流,使用的是令牌桶算法
  • 可以根据ip或路径进行限流,可以设置每秒填充的平均速率,和令牌桶总容量

分布式系统理论

解释下CAP和BASE

CAP定理

1998年,加州大学计算机科学家Eric Brewer提出,分布式系统的三个指标:

  • Consistency(一致性)
  • Availability(可用性)
  • Partiton tolerance(分区容错性)

Eric Brewer 说,分布式系统无法同时满足这三个指标

这个结论叫做CAP定理

CAP定理–Consistency

Consistency(一致性):用户访问分布式系统中的任意节点,得到的数据必须一致
在这里插入图片描述

CAP定理–Availability

Availability(可用性):用户访问集群中的任意健康节点,必须能够得到响应,而不是超时或者拒绝

CAP定理–Partition tolerance

Partition(分区):因为网络故障或其他原因导致分布式系统中的部分节点与其他节点失去连接,形成独立的分区

Tolerance(容错):在集群出现分区时,整个系统也要持续对外提供服务
在这里插入图片描述

结论:

  • 分布式系统节点之间肯定需要网络连接的,分区(P)是必然存在的
  • 如果保证高可用性行(A),可以持续对外提供服务,但是不能保证数据的强一致性 —>AP
  • 如果保证数据强一致性(C),就要放弃高可用性 —>CP

例如zookeeper就是AP模式的,nacos做了cp和ap模式的切换

BASE理论

BASE理论是对CAP的一种解决思路,主要包含了3个思想:

  • Basically Available(基本可用):分布式系统出现故障时,允许损失部分可用性,即保证核心可用
  • Soft State(软状态):在一定时间内,允许出现中间状态,比如临时不一致状态。
  • Eventually Consistent(最终一致性):索然无法保留强一致性,但是在软状态结束后,最终达到数据一致。

在这里插入图片描述

当三个事务执行完成之后,将三个事务提交到事务协调者中,如果三个事务都成功,那么就直接通过,如果其中一个失败,那么就逆向恢复剩下的两个事务。

解释一下CAP和BASE

  • CAP定理(一致性,可用性,分区容错性)
    1. 分布式系统节点通过网络连接,一定会出现分区问题(P)
    2. 当分区问题出现时,系统的一致性(C)和可用性(A)就无法同时满足
  • BASE理论
    1. 基本可用
    2. 软状态
    3. 最终一致
  • 解决分布式事务的思想和模型
    1. 最终一致思想:各分支事务分别执行并提交,如果有不一致的情况,再想办法恢复数据(AP)
    2. 强一致思想:各个分支事务执行完业务不要提交,等待彼此的结果,而后统一提交或回滚(CP)

分布式事务解决方案

Seata架构

Seata事务管理中分为说那个重要的角色

  • TC(Transaction Coordinator)- 事务协调者:维护全局和分支事务状态,协调全局事务提交或回滚
  • TM(Transaction Manager) - 事务管理器:定义全局事务范围,开始全局事务、提交或回滚全局事务
  • RM(Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或者回滚

在这里插入图片描述

seata的XA模式

RM一阶段的工作:

  1. 注册分支事务到TC
  2. 执行分支业务sql但不提交
  3. 报告执行状态到TC

TC二阶段的工作:

  1. TC检测各分支事务执行状态
  2. 如果事务成功,通知所有RM提交事务
  3. 如果有事务失败,通知所有RM回滚事务

RM二阶段的工作:

  1. 接收TC指令,提交或者回滚事务

在这里插入图片描述

性能相对比较差,因为各个事务需要相互等待,保证数据的一致性

AT模式

AT模式同样是分阶段提交的事务类型,不过缺弥补了XA模型中资源锁定周期过长的缺陷

阶段一RM的工作:

  • 注册分支事务
  • 记录undo-log(数据快照)
  • 执行业务sql并提交
  • 报告事务的状态

阶段二提交RM的工作

  • 删除undo-log即可

阶段二回滚RM的工作:

  • 根据undo-log恢复数据到更新前

在这里插入图片描述

在事务开始之前会将数据缓存在undo-log文件中去,然后开始执行事务,如果事务都成功,那么TC就告诉TM删除之前备份的undo-log文件,如果有一个事务失败,那么就根据undo-log文件恢复数据

TCC模式原理

  1. try:资源的检测和预留
  2. Confirm:完成资源的业务操作,要求Try成功Confirm一定要成功
  3. Cancel预留资源释放,可以理解为try的方向操作。

在这里插入图片描述

AP模式它的性能是比较高的但是有一个问题,就是try和confirm和cancel的阶段的业务必须去使用代码去实现,而前两种是框架中自带的。

MQ分布式事务

在这里插入图片描述

你们采用那种分布式事务解决方案呢?

  • 描述项目中采用那种方案(seata|mq)
  • seata的XA模式,CP,需要互相等待各个分支事务提交,可以保证强一致性,性能差 (银行业务)
  • seata的AT模式,AP,需要底层使用undo-log实现,性能好 (互联网业务)
  • seata的TCC模式,AP,性能较好,不过需要人工编码实现 银行业务
  • MQ模式实现分布式事务,在A服务写数据的时候,需要在同一个事务内发送消息到另一个事务,异步,性能最好 互联网业务

分布式服务的接口幂等性

什么是接口幂等性?

幂等:多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致

需要幂等性场景:

  • 用户重复点击(网络波动)
  • MQ消息重复
  • 应用使用失败或超时重试机制

接口幂等性

基于RESTFUL API的角度对常见类型请求的幂等性特点进行分析

请求方式说明
GET查询操作,天然幂等
POST新增操作,请求一次或请求多次造成的结果不同,不是幂等性
PUT更新操作,如果一绝对值更新,则是幂等的,如果是通过增量的方式更新,则不是幂等的
DELETE删除操作,根据唯一值删除,是幂等的

在这里插入图片描述

保证接口幂等性的方式:

在这里插入图片描述

token+redis

在这里插入图片描述

描述:在访问第一个页面的时候去生成一个token,然后存储在redis中并且返回给前端,等到了第二个支付页面的时候携带token进行请求,如果成功删除token,如果没有token就默认访问不成功

redis分布式锁

在这里插入图片描述

先拿到锁,判断是否响应成功,如果成功说明获取到了锁,快速请求,如果失败就快速失败

控制锁的粒度

分布式服务的接口幂等性如何设计?

  • 幂等:多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用结果一致
  • 如果是新增数据,可以使用数据库的唯一索引
  • 如果新增或修改数据
    • 分布式锁,性能较低
    • 使用token+redis来实现,性能较好
      • 第一次请求生成唯一的token,存在redis,返回给前端
      • 第二次请求过来,业务处理,携带之前的token,到redis进行验证,如果存在,可以执行业务,删除token,如果不存在,则返回,不处理业务。

分布式任务调度

项目中使用的分布式任务调度工具

xxl-job解决的问题

  • 解决集群任务的重复执行的问题
  • cron表达式定义灵活
  • 定时任务失败了,重试和统计
  • 任务量过大,分片执行

xxl-job常见的问题

  1. xxl-job路由策略有哪些
  2. xxl-job任务执行失败怎么解决
  3. 如果有大数据量的任务同时需要执行,怎么解决?

xxl-job的路由策略有哪些?

  1. FIRST(第一个):固定选择第一个机器
  2. LAST(最后一个):固定的选择最后一台机器
  3. ROUND(轮询)
  4. RANDOM(随机):随机选择在线的机器
  5. CONSISTENT_HASH(一致性HASH):每个任务按照Hash算法固定选择某一台机器,且所有任务均匀的散列在不同的机器上。
  6. LEAST_FREQUENTLY_USED(最不经常使用):使用频率最低的机器优先被选举
  7. LEAST_RECENTLY_USED(最近最久未使用):最近最久未使用的机器优先被选举
  8. FAILOVER(故障转移):按照顺序依次进行心跳检测,第一个心跳检测成功的机器被选定为目标执行机器并发起调度
  9. BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,第一个空闲检测成功的机器被选定为目标执行器并发起调度;
  10. SHARDING_BROADCAST(分片广播):广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数,可根据分片参数开发分片任务。
    在这里插入图片描述

xxl-job任务执行失败怎么解决?

首先将任务执行策略修改为故障转移,添加事务失败重试次数,查看日志进行分析 ------> 最后使用邮箱进行警告

在这里插入图片描述

如果大数据量的任务同时需要执行,怎么解决?

执行器集群部署时,任务路由策略选择分片广播的情况下,一次任务调度将会广播触发对应的集群中所有执行器执行一次任务。

在这里插入图片描述

xxl-job路由策略有哪些?

xxl-job提供了很多的路由策略,我们平时用的较多的就是:轮询,故障转移,分片广播

xxl-job任务执行失败怎么解决?

  • 路由策略选择故障转移,使用健康的实例来执行任务
  • 设置重试次数
  • 查看日志+邮件告警来通知相关负责人解决

如果大数据量的任务同时需要执行,怎么解决?

  • 让多个实例一块去执行(部署集群),路由策略分片广播
  • 在任务执行的代码中可以获取分片总数和当前分片,按照取模的方式分摊到各个实例执行。

笔记是对黑马课程中的知识进行的个人总结,图片借鉴了课程视频中的资料,感谢黑马程序员的开源精神,哈哈,如有问题联系我删除!