概述
Sentinel概述
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护等多个维度来帮助您保障微服务的稳定性。
gitee:https://gitee.com/rmlb/Sentinel/
github: https://github.com/alibaba/Sentinel
Sentinel与Hystrix 区别
Sentinel 不支持线程池隔离? 改成 线程数隔离
线程池隔离 每个接口都有自己独立的线程池 相互之间没有任何影响的
但是 最终创建的 线程数 越来越多 会影响到服务器端cpu的资源 cpu飙高的问题。
Hystrix 支持 线程池隔离
1. hystrix具有的功能
线程池隔离/信号量隔离 Sentinel 不支持线程池隔离;信号量隔离对应 Sentinel 中的线程数限流。
熔断器 Sentinel 支持按平均响应时间、异常比率、异常数来进行熔断降级。
Command 创建 直接使用 Sentinel SphU API 定义资源即可,资源定义与规则配置分离。
规则配置 在 Sentinel 中可通过 API 硬编码配置规则,也支持多种动态规则源
注解支持 Sentinel 也提供注解支持
开源框架支持 Sentinel 提供 Servlet、Dubbo、Spring Cloud、gRPC 的适配模块,开箱即用;若之前使用 Spring Cloud Netflix,可迁移至 Spring Cloud Alibaba
为什么Sentinel 不支持线程隔离,因为线程池隔离 每个业务接口单独自己独立的线程池,会引发
CPU飙高的问题。
功能 | Sentinel(阿里巴巴团队研发) | Hystrix | resilience4j |
---|---|---|---|
隔离策略 | 信号量隔离(并发线程数限流) | 线程池隔离/信号量隔离 | 信号量隔离 |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 | 基于异常比率、响应时间 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于 RxJava) | Ring Bit Buffer |
动态规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持 |
扩展性 | 多个扩展点 | 插件的形式 | 接口的形式 |
基于注解的支持 | 支持 | 支持 | 支持 |
限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
流量整形 | 支持预热模式、匀速器模式、预热排队模式(流量规则处可配置) | 不支持 | 简单的 Rate Limiter 模式 |
系统自适应保护 | 支持 | 不支持 | 不支持 |
控制台 | 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等 | 简单的监控查看 | 不提供控制台,可对接其它监控系统 |
Sentinel环境搭建
Maven依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
手动限流方式
qps限流
1.限制服务器 qps 当调用该api的QPS达到阈值的时候,进行限流;
当QPS超过阈值,会采取措施进行流控,策略包含:直接拒绝、Warm Up、匀速排队。
(1)直接拒绝:为默认的流控方式:直接拒绝(RuleConstant.CONTROL_BEHAVIOR_DEFAULT),拒绝后抛出FlowException。适用于系统处理能力已知(系统处理能力的水位已知)
(2)Warm Up方式,即预热/冷启动方式。通过冷启动,让通过的流量缓慢增加,逐渐增加到阈值上线(给系统一个预热时间),避免冷启动系统被压垮。
(3)匀速排队:让请求匀速通过,对应的是令牌桶算法(注意:匀速排队模式暂时不支持 QPS > 1000 的场景。)
/**
* 初始化限流路由策略
*
* @return
*/
@RequestMapping("/initFlowQpsRule")
public String initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
// 创建限流资源
rule1.setResource("getSentinelQps");
// QPS控制在2以内
rule1.setCount(2);
// QPS限流
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
//限流应用default
rule1.setLimitApp("default");
//添加该限流规则
rules.add(rule1);
FlowRuleManager.loadRules(rules);
return "....限流配置初始化成功..";
}
/**
* 演示getSentinelQps QPS 对接口限流
*
* @return
*/
@RequestMapping("/getSentinelQps")
public String getSentinelQps() {
Entry entry = null;
try {
entry = SphU.entry("getSentinelQps");
// 执行我们服务需要保护的业务逻辑
log.info("正常执行业务逻辑代码...");
return "getSentinelQps";
} catch (Exception e) {
log.error("<e:{}>", e);
return "该接口访问频率过多,请稍后重试!";
} finally {
// SphU.entry(xxx) 需要与 entry.exit() 成对出现,否则会导致调用链记录异常
if (entry != null) {
entry.exit();
}
}
}
并发限流
限制服务器端同时处理线程数量 基于并发数限流 当调用该api的线程数达到阈值的时候,进行限流。
1.并发数控制用于保护业务线程池不被慢调用耗尽,可以采用线程池隔离的隔离方案(不同业务使用不同的线程池);
2.sentinel采用的方法是,统计当前请求上下文的线程数据(正在执行的调用数据),超出阈值就会拒绝新的请求,效果类似于“信号量”隔离(信号量适用于那些资源有明确访问数量限制的场景,常用于限流 )。
/**
* 初始化限流路由策略
*
* @return
*/
@RequestMapping("/initFlowQpsRule2")
public String initFlowQpsRule2() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
// 创建限流资源
rule1.setResource("getSentinelThreads");
// 线程数是为2
rule1.setCount(2);
// 线程数类型
rule1.setGrade(RuleConstant.FLOW_GRADE_THREAD);
//限流应用default
rule1.setLimitApp("default");
//添加该限流规则
rules.add(rule1);
FlowRuleManager.loadRules(rules);
return "....限流配置初始化成功..";
}
/**
* 演示getSentinelThreads 线程数限流
*
* @return
*/
@RequestMapping("/getSentinelThreads")
public String getSentinelThreads() {
Entry entry = null;
try {
entry = SphU.entry("getSentinelThreads");
// 执行我们服务需要保护的业务逻辑
log.info("正常执行业务逻辑代码...");
Thread.sleep(3000);
return "getSentinelQps";
} catch (Exception e) {
log.error("<e:{}>", e);
return "服务器端忙,请稍后重试!";
} finally {
// SphU.entry(xxx) 需要与 entry.exit() 成对出现,否则会导致调用链记录异常
if (entry != null) {
entry.exit();
}
}
}
改造代码启动项目自动注册限流规则
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 自动加载限流规则
*/
@Component
@Slf4j
public class SentinelApplicationRunner implements ApplicationRunner {
/**
* 限流资源名称 getSentinelThreads
*/
private static final String SENTINE_KEY_SENTINELTHREADS = "getSentinelThreads";
/**
* 限流资源名称 getSentinelQps
*/
private static final String SENTINE_KEY_GETSENTINELQPS = "getSentinelQps";
@Override
public void run(ApplicationArguments args) throws Exception {
List<FlowRule> rules = new ArrayList<FlowRule>();
// 新增限流规则1
FlowRule rule1 = new FlowRule();
rule1.setResource(SENTINE_KEY_SENTINELTHREADS);
// QPS控制在2以内
rule1.setCount(1);
// QPS限流
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
rules.add(rule1);
FlowRule rule2 = new FlowRule();
// 创建限流资源
rule2.setResource(SENTINE_KEY_GETSENTINELQPS);
// QPS控制在2以内
rule2.setCount(2);
// QPS限流
rule2.setGrade(RuleConstant.FLOW_GRADE_THREAD);
//限流应用default
rule2.setLimitApp("default");
//添加该限流规则
rules.add(rule2);
FlowRuleManager.loadRules(rules);
log.info(">>>限流服务接口配置加载成功>>>");
}
}
注解形式配置管理Api限流
1.@SentinelResource value参数:流量规则资源名称、
2.blockHandler 限流/熔断出现异常执行的方法
3.fallback 服务的降级执行的方法
/**
* sentinelAnnotation 演示通过注解的方式 使用
*
* @return
*/
@RequestMapping("sentinelAnnotationQps")
@SentinelResource(value = "getSentinelQps", blockHandler = "getSentinelQpsException")
public String sentinelAnnotationQps() {
return "sentinelAnnotation";
}
控制台形式管理流控规则
Sentinel 环境快速搭建
Sentinel-Dashboard
链接:http://note.youdao.com/noteshare?id=8b31a62bf9618288b215fee9e25bc875
下载对应Sentinel-Dashboard
https://github.com/alibaba/Sentinel/releases/tag/1.7.1 运行即可。
运行执行命令
java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar Sentinel的安装包
范例:
1.8718属于界面端口号
2.8719属于API通讯的端口号
http://127.0.0.1:8718/#/dashboard/home
登录成功之后 账户和密码是为:sentinel/sentinel
SpringBoot项目整合控制台
1.编写测试接口
/**
* 整合getSentinelDashboardQps 仪表盘
*
* @return
*/
@SentinelResource(value = "getSentinelDashboardQps", blockHandler = "getSentinelDashboardQpsException")
@RequestMapping("/getSentinelDashboardQps")
public String getOrderDashboard() {
return "getOrderDashboard";
}
/**
* 被限流后返回的提示
*
* @param e
* @return
*/
public String getSentinelDashboardQpsException(BlockException e) {
log.error("<e:{}>", e);
return "该接口已经被限流啦!";
}
2.配置文件中新增:
server:
port: 22223
spring:
application:
name: mayikt-member
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
## 将数据上报 sentinel transport 仪表盘
dashboard: 127.0.0.1:8718
eager: true
Sentinel流控规则
Sentinel 动态QPS限流
1.相关测试代码:
/**
* 整合getSentinelDashboardQps 仪表盘
*
* @return
*/
@SentinelResource(value = "getSentinelDashboardQps", blockHandler = "getSentinelDashboardQpsException")
@RequestMapping("/getSentinelDashboardQps")
public String getSentinelDashboardQps() {
return "getOrderDashboard";
}
/**
* 整合getSentinelDashboardThreads 仪表盘
*
* @return
*/
@SentinelResource(value = "getSentinelDashboardThreads", blockHandler = "getSentinelDashboardQpsException")
@RequestMapping("/getSentinelDashboardThreads")
public String getSentinelDashboardThreads() throws InterruptedException {
log.info("<正在开始执行业务逻辑代码...>");
Thread.sleep(3000);
return "getSentinelDashboardThreads";
}
/**
* 被限流后返回的提示
*
* @param e
* @return
*/
public String getSentinelDashboardQpsException(BlockException e) {
log.error("<e:{}>", e);
return "该接口已经被限流啦!";
}
2.访问:http://127.0.0.1:8718/#/dashboard/flow/mayikt-member
编辑流控规则
1.资源名:唯一名称,默认是请求路径,。
2.针对来源:指定对哪个微服务进行限流,默认指default,意思是不区分来源,全部限制。
3.阈值类型/单机阈值:QPS(每秒请求数量): 当调用该接口的QPS达到阈值的时候,进行限流 / 线程数:当调用4.该接口的线程数达到阈值的时候,进行限流 。
5.是否集群:是否集群配置
如果是基于QPS 底层是基于令牌桶算法
如果是基于线程数 底层是基于信号量算法
1.直接(默认):接口达到限流条件时,开启限流。
2.关联:当关联的资源达到限流条件时,开启限流 (适合做应用让步)。
3.链路:当从某个接口过来的资源达到限流条件时,开启限流。
使用动态新增流控规则
资源名称:
如果该接口上没有加上 @SentinelResource
默认的资源名称就是为 该接口访问地址 /sentinelTestQps
一定要加上/
Sentinel关联服务限流
当关联的资源达到限流条件时,开启限流 (适合做应用让步)。
例如资源A getSentinelDashboardQpsA的关联资源 getSentinelDashboardQpsB
getSentinelDashboardQpsB 如果达到阈值则会导致 资源A 被限流
注意:模拟的过程中,选择阈值类型是为:线程数
相关代码:
/**
* 整合getSentinelDashboardQps 仪表盘
*
* @return
*/
@SentinelResource(value = "getSentinelDashboardQpsA", blockHandler = "getSentinelDashboardQpsException")
@RequestMapping("/getSentinelDashboardQpsA")
public String getSentinelDashboardQpsA() throws InterruptedException {
log.info("<getSentinelDashboardQpsA>");
Thread.sleep(3000);
return "getSentinelDashboardQpsA";
}
/**
* 整合getSentinelDashboardQps 仪表盘
*
* @return
*/
@SentinelResource(value = "getSentinelDashboardQpsB", blockHandler = "getSentinelDashboardQpsException")
@RequestMapping("/getSentinelDashboardQpsB")
public String getSentinelDashboardQpsB() throws InterruptedException {
log.info("<getSentinelDashboardQpsB>");
Thread.sleep(3000);
return "getSentinelDashboardQpsB";
}
http://127.0.0.1:22223/getSentinelDashboardQpsA
http://127.0.0.1:22223/getSentinelDashboardQpsB
Sentinel链路限流
Sentinel 提供2个接口分为为:getSentinelA 、 getSentinelB
都在调用show 方法,但是只需要对getSentinelA调用show方法限流。
@RequestMapping("/getSentinelA")
public String getSentinelA() {
sentinelManage.show();
return "getSentinelA";
}
@RequestMapping("/getSentinelB")
public String getSentinelB() {
log.info("getSentinelB");
sentinelManage.show();
return "getSentinelB";
}
http://127.0.0.1:22223/getSentinelA ----访问getSentinelA被限流
http://127.0.0.1:22223/getSentinelB ----没有被限流
Sentinel快速失败/排队等待
1.快速失败(默认): 直接失败,抛出异常,不做任何额外的处理,是最简单的效果
2.Warm Up:它从开始阈值到最大QPS阈值会有一个缓冲阶段,一开始的阈值是最大QPS阈值的1/3,然后慢慢增长,直到最大阈值,适用于将突然增大的流量转换为缓步增长的场景。
3.排队等待:让请求以均匀的速度通过,单机阈值为每秒通过数量,其余的排队等待; 它还会让设置一个超时时间,当请求超过超时间时间还未处理,则会被丢弃。
Sentinel 设置黑名单和白名单
让你设计 根据黑名单和白名单 来对接口限制访问。
白名单 该ip可以访问到该接口的
黑名单该ip 是不可以访问到该接口
1.编辑授权规则 设置流控应用 黑名单:禁止127.0.0.1
2.代码中需要配置IpLimiter 根据用户在请求中头中的IP 设置黑名单和白名单
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* @author 余胜军
* @ClassName IpLimiter
* @qq 644064779
* @addres www.mayikt.com
* 微信:yushengjun644
*/
@Component
public class IpLimiter implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest httpServletRequest) {
return httpServletRequest.getRemoteAddr();
}
}
http://127.0.0.1:22223/login
注意事项
如果接口上没有加上 @SentinelResource 资源名称就是为接口名称
在控制台项目中新增限流规则 资源名称 注意是需要加上/
Sentinel 雪崩/熔断/降级概念
在微服务架构中,经常会出现一些名词 例如:服务雪崩、服务熔断、服务降级、服务隔离等概念。
服务雪崩
1.在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,但是由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务堆积,最终导致服务瘫痪。其实,在单体服务中,高并发也会导致服务瘫痪
2.在分布式系统中,由于网络原因或自身的原因,服务一般无法保证 100% 可用。如果一个服务出现了问题,调用这个服务就会出现线程阻塞的情况,此时若有大量的请求涌入,就会出现多条线程阻塞等待,进而导致服务瘫痪。
3.于服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的 “雪崩效应”
调用链中:大量的请求到服务A入口(上游服务), 服务A调用服务B 服务B调用服务C 如果服务B或者服务C 宕机了 中间会引发重试,重试过程中会产生大量请求堆积,线程资源一直被占用,最终导致整个链崩溃,这种现象称之为服务雪崩效应。
我们无法完全杜绝雪崩源头的发生,只有做好足够的容错,保证在一个服务发生问题,不会影响到其它服务的正常运行, 我们就需要对接口实现容错方案。
模拟雪崩
/**
* 演示服务雪崩效应
*
* @return
*/
@RequestMapping("getMayiktA")
public String getMayiktA() throws InterruptedException {
// 模拟该接口处理需要5s
log.info("...正在处理业务逻辑getMayiktA....");
Thread.sleep(5000);
return "mayikt";
}
/**
* 另外接口
*
* @return
*/
@RequestMapping("/getMayiktB")
public String getMayiktB() {
log.info("...正在处理业务逻辑getMayiktB....");
return "mayiktB";
}
服务器端配置线程数
server:
port: 8090
tomcat:
max-threads: 30 ###最大线程数30
jmeter.bat 压力测试 http://127.0.0.1:8090/getMayiktA
导致 http://127.0.0.1:8090/getMayiktB 接口 服务器端没有足够线程执行, 浏览器一直转圈圈中…
服务容错
服务隔离
它是指将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。当有故障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体的系统服务。常见的隔离方式有:线程池隔离(sentinel 是有)和信号量隔离(线程数)(模块隔离)
服务熔断
服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。
服务降级
服务降级是从整个系统的负荷情况出发和考虑的,对某些负荷会比较高的情况,为了预防某些功能(业务场景)出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的fallback(退路)错误处理信息。这样,虽然提供的是一个有损的服务,但却保证了整个系统的稳定性和可用性。
1.超时降级:主要配置好超时时间和超时重试次数和机制,并使用异步机制探测回复情况
2.失败次数降级:主要是一些不稳定的 api,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况
3.故障降级:比如要调用的远程服务挂掉了(网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常),则可以直接降级。
4.限流降级:秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。
qps 3万 走服务降级 时间窗口 30s 无法访问该接口 直接返回一个友好提示
服务限流
对服务器接口实现限流 保护服务接口。 qps或者线程数限流。
Sentinel 服务降级
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。
Sentinel 提供以下几种熔断策略:
- 慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
- 异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
- 异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
以上内容摘自与:github “Sentinel ” 中文文档。
blockHandler限流异常回调方法
fallback 服务降级回调的方法
例子:例如调用该接口 1s 调用5次 都是失败,触发 服务降级策略
该接口设定降级的时间10s 意味着该接口10s 内无法访问,直接走
fallback 服务降级回调的方法
RT(平均响应时间策略)
当1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
访问rtDemo01接口1s 内5个请求 响应时间超过10毫秒,则会触发
服务降级策略 10s 该接口无法访问,走服务降级回调方法。
/**
* rtDemo01
*
* @return
*/
@GetMapping("/rtDemo01")
@SentinelResource(value = "rtDemo01", fallback = "rtDemo01Fallback")
public String rtDemo01() throws InterruptedException {
log.info("<rtDemo01>");
Thread.sleep(20);
return "rtDemo01";
}
/**
* 服务降级回调方法
*
* @return
*/
public String rtDemo01Fallback() {
log.info("服务降级啦...");
return "当前接口处理忙,请稍后重试!";
}
通俗易懂:在1s内如果发送5个请求 平均响应时间都达到该阈值,则开启服务降级,在设定规定时间窗口内暂时无法访问到该接口,等时间该时间窗口结束之后就会关闭服务降级。
jmeter 压测 http://127.0.0.1:8090/rtDemo01
相关代码:
/**
* rtDemo01
*
* @return
*/
@GetMapping("/rtDemo01")
@SentinelResource(value = "rtDemo01", fallback = "rtDemo01Fallback")
public String rtDemo01() throws InterruptedException {
Thread.sleep(1000);
return "rtDemo01";
}
/**
* 服务降级回调方法
*
* @return
*/
public String rtDemo01Fallback() {
return "当前接口处理忙,请稍后重试!";
}
异常比例
当资源的每秒请求量>= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
1s 内 5次请求 全部都是报错,就触发服务降级 服务降级时间10s
走服务降级方法。
相关代码:
/**
* 异常比例
*
* @return
*/
@RequestMapping("/getMayiktError")
@SentinelResource(value = "getMayiktError", fallback = "getMayiktErrorFallback")
public String getMayiktError(Integer age) {
log.info("<getMayiktError>");
Integer j = 1 / age;
return "getMayiktError:" + j;
}
public String getMayiktErrorFallback(Integer age) {
return "当前该接口错误次数太多,暂时无法访问!";
}
压力测试:http://127.0.0.1:8090/getMayiktError?age=0
正常访问:
http://127.0.0.1:8090/getMayiktError?age=1
异常数
当资源近1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
相关代码
/**
* 异常数
*
* @return
*/
@RequestMapping("/getMayiktErrorCount")
@SentinelResource(value = "getMayiktErrorCount", fallback = "getMayiktErrorCountFallback")
public String getMayiktErrorCount(Integer age) {
log.info("<getMayiktErrorCount>");
Integer j = 1 / age;
return "getMayiktErrorCount:" + j;
}
public String getMayiktErrorCountFallback(Integer age) {
return "当前该接口错误次数太多,暂时无法访问!";
}
Sentinel 热点规则
https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
相关代码:
/**
* 模拟秒杀接口
*
* @return
*/
@RequestMapping("/seckill")
@SentinelResource(value = "seckill", blockHandler = "seckillFallbackBlockHandler")
public String seckill(Long userId) {
log.info("<userId:{}>", userId);
return "seckill:" + userId;
}
public String seckillFallbackBlockHandler(Long userId, BlockException exception) {
log.info("<userId,{}您访问的频率太高,请稍后重试!>", userId);
return "userId:" + userId + "您访问的频率太高,请稍后重试!";
}
热点规例外限流:
Sentinel 整合Gateway
Gateway 配置整合Sentinel
从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:
route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组
基于SpringBoot再构建一个service-gateway网关模块,使用时需引入以下模块(以 Maven 为例):
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
</dependencies>
增加配置
server:
port: 81
####服务网关名称
spring:
application:
name: mayikt-gateway
cloud:
gateway:
discovery:
locator:
####开启以服务id去注册中心上获取转发地址
enabled: true
###路由策略127.0.0.1:81/mayikt-member
routes:
###路由id
- id: mayikt-member
#### 基于lb负载均衡形式转发
uri: lb://mayikt-member
filters:
- StripPrefix=1
###匹配规则
predicates:
- Path=/mayikt-member/**
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
## 将数据上报 sentinel transport 仪表盘
dashboard: 127.0.0.1:8718
eager: true
#配置限流之后,响应内容
scg:
fallback:
## 两种模式,一种是response返回文字提示信息,
## 一种是redirect,重定向跳转,需要同时配置redirect(跳转的uri)
mode: response
## 响应的状态
response-status: 200
## 响应体
response-body: '{"code": 200,"message": "请求失败,稍后重试!"}'
如果Sentinel 控制台 没有展示 API管理。
Gateway服务启动,设置该参数
@SpringBootApplication
public class AppGateway {
public static void main(String[] args) {
System.setProperty("csp.sentinel.app.type", "1");
SpringApplication.run(AppGateway.class);
}
}
让后重启Sentinel 控制器 刷新
Sentinel整合Gateway 限流规则
匹配模式根据前缀
tongg
访问网关接口测试
http://127.0.0.1:81/mayikt-member/member
频繁刷新访问
精确模式
/mayikt-member/member
访问接口:http://127.0.0.1:81/mayikt-member/getMayikt 没有被限流
访问接口:http://127.0.0.1:81/mayikt-member/member 被限流
通过网关访问接口,开头mayikt-member qps 1 ——
Sentinel 持久化
Sentinel 客户端如果重启之后 数据最终丢失 ,我们将Sentinel 持久化到
nacos、mysql等。
最后
以上就是阔达老虎为你收集整理的05.Sentinel实现对微服务接口保护Sentinel概述Sentinel与Hystrix 区别Sentinel环境搭建控制台形式管理流控规则Sentinel 雪崩/熔断/降级概念Sentinel 服务降级Sentinel 热点规则Sentinel 整合GatewaySentinel 持久化的全部内容,希望文章能够帮你解决05.Sentinel实现对微服务接口保护Sentinel概述Sentinel与Hystrix 区别Sentinel环境搭建控制台形式管理流控规则Sentinel 雪崩/熔断/降级概念Sentinel 服务降级Sentinel 热点规则Sentinel 整合GatewaySentinel 持久化所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复