目录
一.Sentinel概述
1.Sentinel介绍
2.Sentinel核心组件
3.Sentinel基本概念
二.Sentinel核心功能
1.流量控制
2.熔断降级
三.SpringBoot整合Sentinel
1.gateway引入依赖
2.sentinel控制台搭建
3.gateway配置文件修改
4.启动gateway服务查看sentinel控制台
四.Sentinel使用
1.@SentinelResource注解
2.Sentinel的规则
3.OpenFeign支持
4.gateway规则配置
五.Sentinel控制台使用
1.实时监控
2.流控规则
3.降级规则
4.热点数据
https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5
Sentinel是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。
(1)核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
(2)控制台(Dashboard):控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。
<1> 资源:资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
<2> 规则:围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
Sentinel作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如图
当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
2.2.5.RELEASE
(1)下载Sentinel控制台jar包地址:https://github.com/alibaba/Sentinel/releases
源码地址:https://github.com/alibaba/Sentinel/releases
(2)启动:java -jar sentinel-dashboard-1.8.3.jar 启动,默认端口是8080
(3)登录:http://localhost:8080/ 用户名密码都是:sentinel
spring:
cloud:
sentinel:
transport:
port: 8179
dashboard: 127.0.0.1:8080
注意:
(1)这里的 spring.cloud.sentinel.transport.port 端口配置会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互,比如限流规则拉取。
(2)配置信息现在是存储到nacos中,到nacos进行配置更改。
@SentinelResource
用于定义资源,并提供可选的异常处理和 fallback 配置项。
注意该注解只能作用在实现类,不能作用在接口上面
@SentinelResource注解包含一下属性:
(1)vale
资源名称,必需项,因为需要通过resource name找到对应的规则,这个是必须配置的。 定义资源名,该名称将会显示在控制台中,并且在定义流控以及熔断降级规则时,指定资源名称。
(2)entryType
入口类型,可选项: EntryType.IN和EntryType.OUT(默认为 EntryType.OUT)
public enum EntryType {
IN("IN"),
OUT("OUT");
}
(3)blockHandler
对应处理 BlockException 的函数名称,可选项。
(4)blockHandlerClass
blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
(5)fallback
函数名称,可选项,仅针对降级功能生效(DegradeException)。fallback 函数的访问范围需要是 public,参数类型和返回类型都需要与原方法相匹配,并且需要和原方法在同一个类中。业务异常不会进入 fallback 逻辑。
(6)fallbackClass
fallbackClass的应用和blockHandlerClass类似,fallback 函数默认需要和原方法在同一个类中。 若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
(7)defaultFallback
如果没有配置defaultFallback方法,默认都会走到这里来,默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑,默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理,若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。
(8)exceptionsToIgnore
用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
(1)流量控制规则
(2)熔断降级规则
(3)系统保护规则
(4)访问控制规则
(5)热点规则
Sentinel 适配了 Feign 组件,使用步骤如下
(1)需要在服务调用方加入依赖
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
2.2.5.RELEASE
org.springframework.cloud
spring-cloud-starter-openfeign
(2)服务调用方配置文件中开启Feign支持 sentinel
feign:
#开启Sentinel对Feign的支持
sentinel:
enabled: true
(3)远程调用代码如下
调用方
@RestController
@RequestMapping("server1")
@Slf4j
public class DemoServer1Controller {
@Autowired
private Server2Feign server2Feign;
@RequestMapping("/demo1")
public String demo1(){
String server2Result = server2Feign.demo2("promote msg from server1");
return server2Result;
}
}
公共调用Feign接口
@FeignClient(name = "demo-server2")
public interface Server2Feign {
@GetMapping("/server2/demo2/{param}")
public String demo2(@PathVariable(value = "param") String param);
}
被调用方
@RestController
@RequestMapping("server2")
@Slf4j
public class DemoServer2Controller {
@RequestMapping("/demo2/{param}")
public String demo2(@PathVariable(value = "param") String param){
if (param.startsWith("promote")){
throw new RuntimeException("信息不存在");
}
return "收到server1的msg:"+param;
}
}
在被调用方,人为制造异常,访问接口返回如下
注意:服务出现异常,可以再被调用方降级,也可以在调用方降级
下面介绍在调用方进行降级
fallback
(1)在demo-api中创建公共Feign接口的实现类
@Component
public class FallbackServer2Feign implements Server2Feign {
@Override
public String demo2(String param) {
return "系统繁忙,走降级逻辑~";
}
}
(2)在接口的注解上指定降级处理类
@FeignClient(name = "demo-server2",fallback = FallbackServer2Feign.class)
public interface Server2Feign {
@GetMapping("/server2/demo2/{param}")
public String demo2(@PathVariable(value = "param") String param);
}
(3)再次测试,看是否走到降级逻辑
fallbackFactory
我们可以为 DriverFeign 接口创建一个降级处理的工厂对象,在工厂对象中处理程序异常降级处理方法,用工厂对象处理可以拿到异常信息,代码如下
(1)创建工厂对象
@Component
public class Server2FallbackFactory implements FallbackFactory {
@Override
public Server2Feign create(Throwable throwable) {
return new Server2Feign() {
@Override
public String demo2(String param) {
return "系统繁忙,走fallbackFactory降级逻辑~";
}
};
}
}
(2)在接口注解上指定工厂类
@FeignClient(name = "demo-server2",fallbackFactory = Server2FallbackFactory.class)
public interface Server2Feign {
@GetMapping("/server2/demo2/{param}")
public String demo2(@PathVariable(value = "param") String param);
}
(3)重新启动测试,看是否走到工厂类降级逻辑
(1)新增gateway配置类,配置规则信息
@Configuration
public class GatewayConfiguration {
private final List viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
@PostConstruct
public void doInit() {
// 自定义 api 分组
initCustomizedApis();
// 初始化网关流控规则
initGatewayRules();
}
private void initCustomizedApis() {
Set definitions = new HashSet<>();
ApiDefinition api1 = new ApiDefinition("customer_api")
.setPredicateItems(new HashSet() {{
add(new ApiPathPredicateItem().setPattern("/order/**")
/**
* 匹配策略:
* URL_MATCH_STRATEGY_EXACT:url精确匹配
* URL_MATCH_STRATEGY_PREFIX:url前缀匹配
* URL_MATCH_STRATEGY_REGEX:url正则匹配
*/
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
definitions.add(api1);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
private void initGatewayRules() {
Set rules = new HashSet<>();
rules.add(new GatewayFlowRule("hailtaxi-driver") // 资源名称,可以是网关中的 routeid或者用户自定义的 API分组名称
.setCount(2) // 限流阈值
.setIntervalSec(10) // 统计时间窗口默认1s
.setGrade(RuleConstant.FLOW_GRADE_QPS) // 限流模式
/**
* 限流行为:
* CONTROL_BEHAVIOR_RATE_LIMITER 匀速排队
* CONTROL_BEHAVIOR_DEFAULT 快速失败(默认)
* CONTROL_BEHAVIOR_WARM_UP:
* CONTROL_BEHAVIOR_WARM_UP_RATE_LIMITER:
*/
.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)
//匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效
.setMaxQueueingTimeoutMs(1000)
/**
* 热点参数限流配置
* 若不设置,该网关规则将会被转换成普通流控规则;否则会转换成热点规则
*/
.setParamItem(new GatewayParamFlowItem()
/**
* 从请求中提取参数的策略:
* PARAM_PARSE_STRATEGY_CLIENT_IP
* PARAM_PARSE_STRATEGY_HOST
* PARAM_PARSE_STRATEGY_HEADER
* PARAM_PARSE_STRATEGY_URL_PARAM
*/
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
/**
* 若提取策略选择 Header 模式或 URL 参数模式,
* 则需要指定对应的 header 名称或 URL 参数名称。
*/
.setFieldName("token")
/**
* 参数的匹配策略:
* PARAM_MATCH_STRATEGY_EXACT
* PARAM_MATCH_STRATEGY_PREFIX
* PARAM_MATCH_STRATEGY_REGEX
* PARAM_MATCH_STRATEGY_CONTAINS
*/
.setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_EXACT)
//参数值的匹配模式,只有匹配该模式的请求属性值会纳入统计和流控
.setPattern("123456") // token=123456 10s内qps达到2次会被限流
)
);
rules.add(new GatewayFlowRule("customer_api")
/**
* 规则是针对 API Gateway 的 route(RESOURCE_MODE_ROUTE_ID)
* 还是用户在 Sentinel 中定义的 API 分组(RESOURCE_MODE_CUSTOM_API_NAME),默认是 route。
*/
.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
.setCount(2)
.setIntervalSec(1)
.setGrade(RuleConstant.FLOW_GRADE_QPS)
);
GatewayRuleManager.loadRules(rules);
}
}
(2)启动测试
接口一10秒内请求超过2次会 被限流
接口二1秒内qps达到2次会被限流
同一个服务下的所有机器的簇点信息会被汇总,并且秒级地展示在"实时监控"下。
注意:实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。
实时监控接口文档参照如下连接编写
https://github.com/alibaba/Sentinel/wiki/%E5%AE%9E%E6%97%B6%E7%9B%91%E6%8E%A7
通过接口拿到的数据如下图所示:
我们可以在【流控规则】页面中新增,点击【流控规则】进入页面新增页面,如下图:
资源名:可以和请求路径保持一致,
流控模式为QPS,触发流控执行阈值为1
通过上面的留空规则配置,下面的接口访问1次就被限流了。
http://localhost:8000/server1/demo1接口访问一次后被限流如下图
我们可以选择 降级规则>新增降级规则 ,如下图:
降级规则的熔断策略有3种,分别是慢调用比例、异常比例、异常数,和程序中是一样的。
热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。