常见的服务容错方案包括:服务限流,服务隔离,服务超时,服务熔断和服务降级等。
服务限流
服务限流就是防止系统的流量过大而压垮系统,保护服务节点或者服务后面的数据节点,防止造成服务或数据崩溃,还可以用于平滑请求。
服务隔离
类似于系统的垂直拆分,按照一定的规则将系统划分为多个服务模块,每个服务模块之间相互独立,减少强依赖关系,如果某个服务发生错误之后,不会向其他服务发生扩散,不会对系统产生整体的影响。
常用的服务隔离方式包括:线程池隔离和信号量隔离。
服务超时
服务超时就是在上游服务调用下游服务的时候,设置一个最大响应时间,如果超过最大的响应时间,则断开服务的请求链接,释放资源。
服务熔断
上游服务调用下有服务如果调用失败或者调用超时的时候,会自动断开与下游服务的链接,这就是熔断,服务熔断一般有三种状态:
服务降级
就是服务的托底方案,上面服务熔断中所提到的开启状态下,返回的上游服务的预定方法。
丰富的应用场景、完备的实时监控,广泛的开原生态,完善的spi机制。
Sentinel分为两个部分:
核心库(Java客户端)
控制台(基于SpringBoot开发,打包直接运行),下载地址:https://github.com/alibaba/Sentinel/releases,通过java -jar的方式启动。默认端口号是8080,自己的启动命令java -Dserver.port=8888 -Dcsp.sentinel.dashboard.server=localhost:8888 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar
,默认用户名/密码:sentinel/sentinel
流量控制
对流量进行控制,使得流量均摊,可控的方式进入系统
熔断降级
当调用链路上的某个节点出现故障,比如超时、宕机或者异常的情况,对故障节点的调用频率进行限制,或者直接不调用出现故障的节点。主要是通过限制并发线程数和响应时间进行降级。
系统负载保护
当系统的压力和负载比较高的时候,会出现系统宕机的风险,Sentinel会在集群情况下,将本来由A服务承担的流量,转移到B服务上,如果B服务也是高负载状态,则会提供相应的保护功能,让流量和系统负载达到均衡,最大限度保证处理请求。
需要引入类库
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
涉及到的yml配置文件:
spring:
cloud:
sentinel:
transport:
port: 9999 #指定和Sentinel控制台交互的端口,任意指定一个未使用的端口
dashboard: 127.0.0.1:8888 #Sentinel控制台服务地址
启动对应的服务。当启动服务之后,需要请求一下服务的任意一个接口,因为Sentinel是懒加载机制,访问一下接口,就可以让Sentinel的控制台获取到数据了。
资源名
:唯一名称,默认请求路径。
针对来源
:Sentinel可以对针对调用者进行限流,填写的是微服务的名称,默认是default,也就是没有来源,对所有来源进行限制。
阈值类型/单机阈值
:
QPS:每秒请求数量,当调用达到这个阈值时,进行限流。
并发线程数:当调用这个接口的线程数达到阈值的时候,进行限流。
阈值就是指单机阈值填写的值,当勾选上是否集群的时候,还会出现单机均摊和总体阈值的选项。
流控模式
:
直连:就是当请求达到阈值时候,直接限流自己。
关联:当关联的资源达到阈值时,限制当前资源,填写资源名,表示当资源B达到阈值的时候,限制当前资源的请求。
链路:从某个接口请求过来的资源达到限流条件时候,开启限流。
流控效果
:
快速失败:达到阈值,直接返回失败结果。
warm up:会增加一个预热时长的选项,填写一个数字,单位是秒,作用就是在n秒内,将将阈值增加到指定的值,比如阈值为10,默认是从threshold/3,比如填写的是5秒,那么就是当阈值达到3的时候,开始执行限流,然后在5秒内,将限流从3增加到10。
排队等待:让请求均匀通过,达到阈值后其余的请求会排队等待,可以设置一个超时时间,超过之后,没有被处理会被丢弃。
熔断策略分为三个:
慢调用比例:最大RT即最大的响应时间,请求大于该值的时候被统计为慢调用。当单位统计时长内的请求数目大于设定的最小请求数目,并且慢调用比例大于阈值时候,则触发熔断,经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
异常比例:异常比例超过了阈值。
异常数:如果满足最小请求数的情况下,如果异常数量达到了设定的值,则触发限流。
比如说有一个接口:其中资源名对应的就是@SentinelResource的值。
参数的索引就是方法里面的的a和b,a索引是0,b索引是1;
对于请求:
http://localhost:8080/order/request_sentinel4?a=1
如果这个请求中总是存在a=1,那么就会被统计进去,达到阈值之后就会被限流。
下面的参数例外项的作用就是当参数索引为某个值的时候,按照新的规则来进行限流,比如上面的单机阈值设置为10,下面的参数值设置为100,限流阈值设置为100,那么当a=1
的时候,就会按照下面的100来进行限流。
还有一个选项是参数类型
只有当这个参数类型匹配一致的时候才会生效,int对应的就是int,long类型不能包含int类型。
资源名就是唯一名称。
授权规则需要配合RequestOriginParser接口使用:
@Component
public class MyRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest httpServletRequest) {
return httpServletRequest.getParameter("serverName");
}
}
parseOrigin方法返回的就是获取流控应用的值,比如请求的是http://localhost:8080/order/request_sentinel5?serverName=test,那么流控应用的值就是test
如果授权类型是白名单,那么就是说serverName的值为test的时候才允许通用,但是如果没有serverName的参数,就不受授权规则
的限制也会通过,如果是黑名单,那么当serverName的值为test的时候,就不会通过,同样的如果没有serverName参数也不受授权规则
限制
也叫系统自适应限流,对系统的整体流量进行限制。
系统规则支持以下的模式:
Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 **load1(1分钟平均负载 ,load1 解释:https://blog.csdn.net/wufaliang003/article/details/80400385 )**作为启发指标,进行自适应系统保护。 当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt
估算得出。设定参考值一般是 CPU cores * 2.5
。
CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。