Sentinel用法解析 红太狼 2023-10-01 23:39 2阅读 0赞 **目录** 一.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.热点数据 -------------------- ### 一.Sentinel概述 ### #### 1.Sentinel介绍 #### [https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5][https_github.com_alibaba_Sentinel_wiki_E4_B8_BB_E9_A1_B5] Sentinel是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 #### 2.Sentinel核心组件 #### (1)核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。 (2)控制台(Dashboard):控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。 #### 3.Sentinel基本概念 #### <1> 资源:资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。 <2> 规则:围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。 ### 二.Sentinel核心功能 ### #### 1.流量控制 #### Sentinel作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如图 ![597f8d6d22d04ecf9321b1a64dd0d6f6.png][] #### 2.熔断降级 #### 当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。 ### 三.SpringBoot整合Sentinel ### #### 1.gateway引入依赖 #### <!--sentinel依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.5.RELEASE</version> </dependency> #### 2.sentinel控制台搭建 #### (1)下载Sentinel控制台jar包地址:[https://github.com/alibaba/Sentinel/releases][https_github.com_alibaba_Sentinel_releases] ![85f3f64284094b54aafaffb06d890851.png][] 源码地址:[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/ ][http_localhost_8080_]用户名密码都是:sentinel #### 3.gateway配置文件修改 #### 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进行配置更改。 #### 4.启动gateway服务查看sentinel控制台 #### ![ba22a299f4614e4a92cd7180906bb603.png][] ### 四.Sentinel使用 ### #### 1.@SentinelResource注解 #### `@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 逻辑中,而是会原样抛出。 #### 2.Sentinel的规则 #### (1)流量控制规则 (2)熔断降级规则 (3)系统保护规则 (4)访问控制规则 (5)热点规则 #### 3.OpenFeign支持 #### Sentinel 适配了 Feign 组件,使用步骤如下 (1)需要在服务调用方加入依赖 <!--sentinel--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.5.RELEASE</version> </dependency> <!--Openfeign api模块中已存在也可不引入--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> (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; } } 在被调用方,人为制造异常,访问接口返回如下 ![cfb46921f29d42f894b8120ecbc932f5.png][] 注意:服务出现异常,可以再被调用方降级,也可以在调用方降级 下面介绍在调用方进行降级 **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)再次测试,看是否走到降级逻辑 ![71cab546ccfc4571ace9455300e43c5a.png][] **fallbackFactory** 我们可以为 DriverFeign 接口创建一个降级处理的工厂对象,在工厂对象中处理程序异常降级处理方法,用工厂对象处理可以拿到异常信息,代码如下 (1)创建工厂对象 @Component public class Server2FallbackFactory implements FallbackFactory<Server2Feign> { @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)重新启动测试,看是否走到工厂类降级逻辑 ![49006d8de6d540cb9dac7ebdeed1b647.png][] #### 4.gateway规则配置 #### (1)新增gateway配置类,配置规则信息 @Configuration public class GatewayConfiguration { private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public GatewayConfiguration(ObjectProvider<List<ViewResolver>> 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<ApiDefinition> definitions = new HashSet<>(); ApiDefinition api1 = new ApiDefinition("customer_api") .setPredicateItems(new HashSet<ApiPredicateItem>() { { 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<GatewayFlowRule> 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次会被限流 ### 五.Sentinel控制台使用 ### #### 1.实时监控 #### 同一个服务下的所有机器的簇点信息会被汇总,并且秒级地展示在"实时监控"下。 注意:实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。 实时监控接口文档参照如下连接编写 [https://github.com/alibaba/Sentinel/wiki/%E5%AE%9E%E6%97%B6%E7%9B%91%E6%8E%A7][https_github.com_alibaba_Sentinel_wiki_E5_AE_9E_E6_97_B6_E7_9B_91_E6_8E_A7] 通过接口拿到的数据如下图所示: ![eb388391c1ce4a6aa4276d4a70170c7a.png][] #### 2.流控规则 #### 我们可以在【流控规则】页面中新增,点击【流控规则】进入页面新增页面,如下图: ![1ba73f34a8524f9297265b1d385b8c96.png][] 资源名:可以和请求路径保持一致, 流控模式为QPS,触发流控执行阈值为1 通过上面的留空规则配置,下面的接口访问1次就被限流了。 [http://localhost:8000/server1/demo1][http_localhost_8000_server1_demo1]接口访问一次后被限流如下图 ![b05586d311ca4618bdaa2b0b00795871.png][] #### 3.降级规则 #### 我们可以选择 降级规则>新增降级规则 ,如下图: ![183c2f80d394495e91d373ef15e8a3b1.png][] 降级规则的熔断策略有3种,分别是慢调用比例、异常比例、异常数,和程序中是一样的。 #### 4.热点数据 #### 热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。 ![7a7a6d8bbac24b5abfbf4f515806db3b.png][] [https_github.com_alibaba_Sentinel_wiki_E4_B8_BB_E9_A1_B5]: https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5 [597f8d6d22d04ecf9321b1a64dd0d6f6.png]: https://img-blog.csdnimg.cn/597f8d6d22d04ecf9321b1a64dd0d6f6.png [https_github.com_alibaba_Sentinel_releases]: https://github.com/alibaba/Sentinel/releases [85f3f64284094b54aafaffb06d890851.png]: https://img-blog.csdnimg.cn/85f3f64284094b54aafaffb06d890851.png [http_localhost_8080_]: http://localhost:8080/ [ba22a299f4614e4a92cd7180906bb603.png]: https://img-blog.csdnimg.cn/ba22a299f4614e4a92cd7180906bb603.png [cfb46921f29d42f894b8120ecbc932f5.png]: https://img-blog.csdnimg.cn/cfb46921f29d42f894b8120ecbc932f5.png [71cab546ccfc4571ace9455300e43c5a.png]: https://img-blog.csdnimg.cn/71cab546ccfc4571ace9455300e43c5a.png [49006d8de6d540cb9dac7ebdeed1b647.png]: https://img-blog.csdnimg.cn/49006d8de6d540cb9dac7ebdeed1b647.png [https_github.com_alibaba_Sentinel_wiki_E5_AE_9E_E6_97_B6_E7_9B_91_E6_8E_A7]: https://github.com/alibaba/Sentinel/wiki/%E5%AE%9E%E6%97%B6%E7%9B%91%E6%8E%A7 [eb388391c1ce4a6aa4276d4a70170c7a.png]: https://img-blog.csdnimg.cn/eb388391c1ce4a6aa4276d4a70170c7a.png [1ba73f34a8524f9297265b1d385b8c96.png]: https://img-blog.csdnimg.cn/1ba73f34a8524f9297265b1d385b8c96.png [http_localhost_8000_server1_demo1]: http://localhost:8000/server1/demo1 [b05586d311ca4618bdaa2b0b00795871.png]: https://img-blog.csdnimg.cn/b05586d311ca4618bdaa2b0b00795871.png [183c2f80d394495e91d373ef15e8a3b1.png]: https://img-blog.csdnimg.cn/183c2f80d394495e91d373ef15e8a3b1.png [7a7a6d8bbac24b5abfbf4f515806db3b.png]: https://img-blog.csdnimg.cn/7a7a6d8bbac24b5abfbf4f515806db3b.png
还没有评论,来说两句吧...