目录
1 容错策略之超时重试
1.1 什么是超时重试
用户发起请求到达客户端,同一个接口的提供者有3个,当客户端向服务端发起请求时,客户端的请求超时时间阀门时5秒钟,当客户端向服务端发起请求超过了5秒钟服务端没有响应,请求超时了客户端发起重试客户端设置了容错策略,超时重试,优先重试其他提供者,如果服务端没有集群那就只能再次重试该提供者。
1.2 超时重试-引发的问题及解决方案一
超时重试引发的问题:
客户端这一侧,用户端请求并发比较高,请求不断发送,那客户端这一侧接收的请求比较多,也会发出很多次请求到达服务端,当客户端在同一时间段内发送了很多RPC请求,在多个请求中rpc框架怎么检测哪个请求超时了呢
当我们的技术宽度不够的时候,往往遇到一个问题的时候第一反应给出的解决方案往往不是最佳的,要三思而行
解决方案一
我们每发一次RPC请求,就将该请求对象存放到集合中,在写一个定时器每隔一秒钟去扫描该集合中的对象是否有超时的,如果有就进行重试操作。
该种方式存在的问题:
问题:有很多无意义的遍历操作开销,浪费CPU
1.3 超时重试-引发的问题解决方案二时间轮机制
dubbo的请求超时策略就是使用的时间轮算法实现的
可以参考dubbo的HashTimewhile类,该类就是对时间轮算法的实现,解决的就是rpc请求超时的问题
在时钟轮机制中,有时间槽,每个槽位代表一个时间单位,时间指针按照时间单位走动,将任务放到对应的时间槽位上,当时间指针走到该槽位时就可以拿出来执行
也就是说,我们把某一个请求的他的超时封装成一个任务,放到对应的时间槽位下面,时间轮的指针走到这个槽位的时候就把这个任务拿出来进行执行
这个时间槽在实现上可以用一个循环的数组来实现。
1.3.1 时间轮的原理
例如:
我们定义一个长度为10的时间轮,每一个长度代表一秒钟,
当我们发送一次rpc请求的时候,设定的请求超时时间在2秒钟后,那么 我们就将该次请求超时时间的处理逻辑存放到当前时间轮的时间槽的后 两位槽位上,当时间轴到达时间槽时判断该执行槽中的任务,需要执行 则执行该任务,不该执行则不执行
(循环的i可以判断当前的时间轮在哪个槽位上
或者在外面定义一个计数器,存储时间轮指向时间槽,当时间执行到最 后一个节点时,计数器清零)
当并发比较多时一个时间槽可能存在多个任务对象,可以以链表的形式 往后链,
就是将该槽位定义成集合,说链表对方听的比较好理解
这是一种解决方案,具体根据实际的业务场景选取合适数据结构
当一个时间槽位中有多个任务时,我们要怎么确定当前的多个任务是否 在本轮时间转动轴中执行呢一般的办法是在任务上记录圈数,每到一次就减一,减到0就执行
就是说是结合时间轴的长度,在根据任务的超时时长,如果说设置的任 务超时时长大于时间轴的长度,那么就在任务中定义执行的圈数,每到 一个减一,圈数为0时就执行,如果说是超时的时长比时间轮小则不需要 考虑这个问题,当时间轴到达时间槽时执行该时间槽的所有任务即可。
2 熔断,降级的概念及应用场景
消费者端调服务者端,服务端代码出错了此时该怎么解决
服务端不处理,消费者者不处理,将错误返回到用户端这肯定不是我们想要的结果
1,正常给服务做降级处理
降级:
正常返回(备选结果)
正常但不一定正确
降级两种处理方案, 一是服务端做处理,
二是消费者端做处理
比如我们的openfing降级
2,熔断
在一段时间内当多次调用提供者时失败的次数比例大于我们拟定的阀门时 就可以做熔断处理
熔断:对目标有一个冷静期,冷静期内不对目标发起直接调用
熔断总结:
如何判断需要熔断? 基于服务的可用率/失败率
2.1 熔断工作何时开始又何时结束
熔断有三种状态
熔断机制 默认触发熔断机制是20次请求
closed 关闭状态
所有请求都正常访问 默认是关闭的状态
open 打开状态
当一定的时间段内请求的失败达到50%阀门时(20次请求会触发 熔断机制进入open状态
(不一定非要根据请求的失败率来触发熔断机制也可以根据服务 的响应时间等等某一个指标超过阈值了作为我们的熔断机制)
HalfOpen 半开状态
open状态不是永久的 打开后会进入休眠时间 默认5m
随后断路器会自动进入半开状态 会释放一次请求 若请求成功 则关闭熔断机制否则继续进入休眠状态
熔断的启动 与降级的启动方式是一样 都需要加启动注解 与在方法中加指定开启Hystrix的注解
3 限流策略概述及限流的应用场景
有了熔断,降级为何还要限流?
实际生产环境中,服务发生的一系列问题很大可能是由于访问量过大而引起的,
这就需要业务提供方能够进行自我保护,从而保证在高访问量、高并发的场景下,系统依然能够稳定,高效运行。
限流的作用是用来限制其请求的速率,保护后台相应服务,以免服务过载导致服务不可用现象出现。
3.1 常见的限流算法
1,令牌桶算法
原理
就是定义一个固定大小容量的捅,在定义一个生成令牌的组件
按照固定的速率生成令牌往桶里存放,如果捅满了就丢弃掉该令牌
当请求到来之后先从桶里面获取令牌,如果请求成功获取到令牌就
对该次请求放行,如果请求获取不到令牌就拒绝访问
需要注意的点是放行请求的速率,和我们往令牌桶里存放的速率要大致相当
这个速率的鉴定要结合目标对象(服务器)可承载的峰值来决定
令牌桶算法的弊端是对于突发型的并发流量支持不是很好,需要充分考虑到令牌桶的最大容量,及突发型的并发流量目标对象能否抗的住
及突发型的并发流量指的就是,一个时间段内没有任何请求,此时我们的令牌捅已经被放满,突然并发蜂拥而至把令牌获取完,要考虑到我们的目标对象能否抗的住
4 总结
超时重试
时间算法的时间轮特别适合完成超时检测,心跳检测这类的任务,时间任务检测等的业务场景
时间轮就是 时间刻度+循环次数+扫描器组成
RPC 框架中又很多的高级特性,我们就不一一总结了,根据实际场景来够用就好,不需要弄很多杂东西,反而影响性能