Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容
可以理解我们平常的接口就是资源了
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
在 Sentinel 里面,所有的资源都对应一个资源名称以及一个 Entry。Entry 可以通过对主流框架的适配自动创建,也可以通过注解的方式或调用 API 显式创建;每一个 Entry 创建的时候,同时也会创建一系列功能插槽(slot chain)
插槽的职责:
Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能
方式一:公众号获取
关注I am Walker
回复sentinel控制台
即可获取jar包
方式二:github下载
https://github.com/alibaba/Sentinel/releases
java -Dserver.port=9088 -Dcsp.sentinel.dashboard.server=localhost:9088 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar&
这里的端口可以进行更改
启动成功,之后可以访问host:port
默认账号密码都是sentinel
java -Dserver.port=9088 -Dcsp.sentinel.dashboard.server=localhost:9088 -Dproject.name=sentinel-dashboard -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456 -Dserver.servlet.session.timeout=7200 -jar sentinel-dashboard-1.8.6.jar&
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
server:
port: 10111
servlet:
context-path: /order
spring:
application:
name: walker-order
cloud:
sentinel:
transport:
# dashboard的ip和端口
dashboard: localhost:9088
package com.walker.order.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Map;
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/get")
public String get(HttpServletRequest request){
return "you get order";
}
}
调用接口
调用之后,就可以看到出现的服务以及我们刚才调用的接口
多次访问请求地址,之后可以看见返回Blocked by Sentinel (flow limiting)
翻译:Sentinel堵塞(限流)
可以看到,返回的Status Code是429
这个代表,如果关联的接口超过阈值了,那么本接口也会被控制
package com.walker.order.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Map;
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/A")
public String A(){
return "A";
}
@GetMapping("/B")
public String B(){
return "B";
}
}
这里对/test/B设置单机阈值为1,也就是当/test/B访问的qps=1时,/test/A会被限流
因为没有使用jmeter进行并发测试,所以手速可以快一些
只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【API级别的针对来源】
熔断策略
主要分为:
慢调用比例 (SLOW_REQUEST_RATIO):
选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。
当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
1、接口编写
@GetMapping("/slow")
public String slow() throws InterruptedException {
Thread.sleep(1000);
return "ok";
}
2、规则设定
规则代表着,统计时长2s内,如果有2个请求数,且有0.5的比例响应时长超过500ms的,则熔断5s
3、测试
第一次调用
再次调用,则被熔断了
异常比例 (ERROR_RATIO):
当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
1、controller编写
@GetMapping("/errorPercent")
public String errorPercent(){
int i=1/0;
return "ok";
}
2、熔断规则
代表着2s内如果请求数量大于2条,且有0.1的比例是异常的,那么将熔断5s
3、测试
快速调用2次,都能获取到
调用两次之后,就出现了5s的熔断了
异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
package com.walker.order.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Map;
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/fusing")
public String fusing(){
// 报错
int a=1/0;
return "fusing";
}
}
资源:
资源名就是我们的路径了,也可以在代码中使用注解@SentinelResource进行备注
限流方式:这里只支撑QPS
参数索引:代表的是我们接口中使用的参数的下标
例如我们要对下面的接口k1有值的时候进行限流,那么参数索引就填写0,如果对k2进行限制,那么就填1
**单机阈值:**代表的是当QPS达到多少的时候,进行限流
**统计窗口时长:**代表的是链路被限流的时长
/**
* 热点key
*/
@GetMapping("/hotkey")
@SentinelResource(value = "hotkey",blockHandler = "hotkeyHandler")
public String hotkey(String k1,String k2){
return "hotkey";
}
public String hotkeyHandler(String k1, String k2, BlockException exception){
return "该热点key已经被限流";
}
**hotkeyHandler:**阻断处理器,可以自定义阻断的时候,对链路进行拦截,返回需要的信息,或者进行记录之类的
这里设置了参数0,QPS达到1s请求数=1的时候,进行5s的窗口时长
测试k1有值的时候
第一次请求是没有问题的
之后再请求就被限流了
测试k2
发现如何调用都没有影响,因为没有进行限制
使用@SentinelResource的blockHandler属性,然后编写方法
1、配置BlockExceptionHandler
package com.walker.order.config;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Component
// 1、实现BlockExceptionHandler
public class MyBlockExceptionHandler implements BlockExceptionHandler {
// 2、重写handle方法
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
String msg="";
if(e instanceof FlowException)
msg="接口限流";
else if(e instanceof DegradeException)
msg="服务降级了";
else if(e instanceof ParamFlowException)
msg="参数限流了";
else if(e instanceof AuthorityException)
msg="权限规则不通过";
else if(e instanceof SystemBlockException)
msg="系统保护";
httpServletResponse.setContentType("application/json;charset=utf-8");
httpServletResponse.getWriter().write(JSON.toJSONString(msg));
}
}
原因:
因为我的dashboard是部署在云服务上的,然后我的微服务放在本地,
但是本地和云服务器的网络不同,导致失败
可以查看sentinel-dashboard的日志
打通网络就可以了
https://blog.csdn.net/qq_51409098/article/details/126068253
https://sentinelguard.io/zh-cn/docs/introduction.html