对微服务系统进行保护
代替hystrix
hystrix --> sentinel (服务降级,服务熔断,服务限流)
hystrix dashboard --> sentinel dashboard(仪表盘,状态查看,配置规则)
hystrix:豪猪,全身是刺
sentienl wiki :介绍 · alibaba/Sentinel Wiki · GitHub
sentinel两大概念:
资源(rest接口)
规则(流量、熔断、负载)
定位哪个资源,配置什么规则(使用sentinel dashboard)
好处:解耦,不想要规则直接删除即可,不需要动代码,使微服务的管理变得更加灵活
下载sentinel jar
Release v1.8.4 · alibaba/Sentinel · GitHub
java -jar -Dserver.port=8080 运行
访问localhost:8080
目前什么都没有
启动nacos
创建springboot应用,注册到nacos
# 应用名称
spring.application.name=sentinel-demo
# 应用服务 WEB 访问端口
server.port=8081
# Sentinel 控制台地址
spring.cloud.sentinel.transport.dashboard=localhost:8080
# 取消Sentinel控制台懒加载
# 默认情况下 Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包
# 配置 sentinel.eager=true 时,取消Sentinel控制台懒加载功能
spring.cloud.sentinel.eager=true
# sentinel与dashboard通信端口,默认8719
spring.cloud.sentinel.transport.port=8719
# 如果有多套网络,又无法正确获取本机IP,则需要使用下面的参数设置当前机器可被外部访问的IP地址,供admin控制台使用
# spring.cloud.sentinel.transport.client-ip=
# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
# Nacos认证信息
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
# Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 注册到 nacos 的指定 namespace,默认为 public
spring.cloud.nacos.discovery.namespace=public
启动后,在nacos和sentinel dashboard可以看到服务
这时dashboard中的实时监控依然是没有数据的,因为还没有资源(接口)
创建一个接口
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello";
}
}
访问几次,再次查看sentinel控制台,出现了hello接口的实时监控信息
QPS:Query Per Second,每秒的请求数
RT:Response Time,每个请求的响应时间
五大规则
流控规则:监控应用的流量QPS,达到指定阈值时对流量进行控制,避免被瞬时的流量高峰冲垮
熔断规则:监控应用的资源调用,达到指定的阈值时自动触发熔断降级(如设置某资源出现两次异常后就停用)
热点规则:热点即经常访问的数据,对其进行限流
系统规则:系统自适应限流,从整体维度对入口流量进行控制
授权规则:黑白名单控制
流控规则案例
对/hello添加流控规则(1s内只能处理2个请求)
这时,当1s内超过2次请求时,会出现如下页面
并发线程数:服务器处理请求的线程数,和请求数没有关系
通过并发线程数限流:当服务器创建的线程数超过指定的阈值时,对请求限流
注意区分QPS和并发线程数两种方式
显然,当设置并发线程数阈值为2时,限流将比设置QPS为2更松,因为当前业务很简单,线程处理请求的速度是非常快的,即大概率不会超过2个线程
流控模式
1s内10个请求只能处理2个,其他8个失败
1s内对/a的请求数超过两个,此时访问/hello直接失败(反向关联)
1s内对/hello的请求数超过两个,此时访问/b直接失败(正向关联)
流控效果(只对QPS类型有效)
快速失败:拒绝请求,抛出异常
Warm Up:冷启动、预热(慢慢处理,由少到多)
排队等待:始终匀速处理(固定1s多少个)
熔断规则
RT(响应时间)
异常比例
异常数
热点规则(热点参数限流)
访问资源中携带了指定参数时限流
如统计一段时间内最常购买的商品id进行限制
统计一段时间内频繁访问的用户id进行限制
注意
只能是QPS模式,因为热点参数包含在请求中
热点规则不能使用资源路径的形式,使用资源别名
使用sentinel别名:@SentinelResource
@RestController
public class HelloController {
@GetMapping("/hello/{id}")
@SentinelResource(value = "hello") //sentinel别名
public String hello(@PathVariable("id") Integer id) {
return "hello " + id;
}
}
这时在簇点链路中可以看到hello资源
并且可以直接对hello资源增加规则(不用手动写/hello),这也是配置别名的好处
对hello资源新增热点规则
在1s内访问/hello(携带一个参数),并且超过1次,对其进行限流
当不带参数时,不会出现限流
携带一个参数,1s内访问超过1次,出现异常页面
注意这里是直接抛出异常
通过@SentinelResource(blockHander="")可以自定义返回信息
@GetMapping("/hello/{id}")
@SentinelResource(value = "hello",blockHandler = "blockHandler")
public String hello(@PathVariable("id") Integer id) {
return "hello " + id;
}
public String blockHandler(Integer id, BlockException e){
log.debug(e.getMessage());
if(e instanceof FlowException){
return "当前已被流控,请稍后再试";
}else if(e instanceof DegradeException){
return "当前已被熔断,请稍后再试";
}else if(e instanceof ParamFlowException){
return "热点参数限流";
}
return "出现异常,请稍后再试";
}
这里演示的是发生ParamFlowException时的返回信息,其他异常同理
如果方法中出现业务异常(不是流控异常),可以通过@SentinelResource(fallback="")自定义返回结果
@GetMapping("/hello/{id}")
@SentinelResource(value = "hello",blockHandler = "blockHandler",fallback = "helloFallback")
public String hello(@PathVariable("id") Integer id) {
if(id <0){
throw new RuntimeException("id不能为负数");
}
return "hello " + id;
}
public String helloFallback(Integer id){
return "hello-业务异常";
}
通常热点数据不是很多,可以对热点限流再做细化
当第一个参数的值为12时,每秒只能允许一个请求,否则每秒可以允许10个请求