找回密码
 立即注册
首页 业界区 业界 nacos(八): sentinel——基本使用

nacos(八): sentinel——基本使用

稿辏付 2025-6-3 14:14:11
一、概要
在微服务的架构中,流控是一个重要的任务。sentinel是阿里开源的流量治理组件,针对访问的“资源”或服务路径进行流控,内置了限流、熔断及系统负载保护等功能。
sentinel分为系统库及控制面板(也称“控制台")两个部分。其中,控制台能运行于java 8及以上版本,不依赖于其它三方资源;而控制面板则是sentinel的管理中心,用户可通过图形化界面对规则进行管理和配置。
 
二、下载sentinel控制面板
Sentinel官网地址:https://sentinelguard.io/zh-cn/index.html
Sentinel项目地址:https://github.com/alibaba/Sentinel
当前版本1.8.8:
1.png

 
三、启动sentinel
1) 一般启动:
  1. java -jar sentinel-dashboard-1.8.8.jar
复制代码
2) 带参数启动:
  1. java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.8.jar
复制代码
其中:
-Dserver.port=8080:指定Sentinel控制台程序的端口为8080。
-Dcsp.sentinel.dashboard.server=localhost:8080:Sentinel控制台的访问地址,客户端会自动向该地址发送心跳包。
-Dproject.name=sentinel-dashboard:指定Sentinel控制台程序显示的名称。
3) 带参数启动:
  1. nohup java -server -Xms64m -Xmx256m -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=192.168.66.100:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.8.jar >> /opt/sentinel.log 2>&1 &
复制代码
启动成功后 ,在浏览器访问http://127.0.0.1:8080,即可看到sentinel的管理界面。并输入用户名sentinel和密码sentinel,即可进入管理,如下图:
2.png

 
四、配置项目与sentinel进行通信
当前将多模块项目中的producer(看这里)进行扩展,集成sentinel。
1)在pom.xml中添加依赖
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.     <modelVersion>4.0.0</modelVersion>
  5.     <parent>
  6.         <groupId>com.example</groupId>
  7.         multimod_nacos</artifactId>
  8.         <version>0.0.1-SNAPSHOT</version>
  9.     </parent>
  10.     producer</artifactId>
  11.     <packaging>jar</packaging>
  12.     <dependencies>
  13.         
  14.         <dependency>
  15.             <groupId>org.springframework.boot</groupId>
  16.             spring-boot-starter</artifactId>
  17.         </dependency>
  18.         <dependency>
  19.             <groupId>org.springframework.boot</groupId>
  20.             spring-boot-starter-web</artifactId>
  21.         </dependency>
  22.         
  23.         <dependency>
  24.             <groupId>com.alibaba.cloud</groupId>
  25.             spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  26.         </dependency>
  27. <strong>        
  28.         <dependency>
  29.             <groupId>com.alibaba.cloud</groupId>
  30.             spring-cloud-starter-alibaba-sentinel</artifactId>
  31.         </dependency></strong>
  32.     </dependencies>
  33.     <build>
  34.         <plugins>
  35.             <plugin>
  36.                 <groupId>org.apache.maven.plugins</groupId>
  37.                 maven-compiler-plugin</artifactId>
  38.                 <version>3.8.1</version>
  39.                 <configuration>
  40.                     <source>1.8</source>
  41.                     <target>1.8</target>
  42.                     <encoding>UTF-8</encoding>
  43.                 </configuration>
  44.             </plugin>
  45.             <plugin>
  46.                 <groupId>org.springframework.boot</groupId>
  47.                 spring-boot-maven-plugin</artifactId>
  48.                 <version>${spring-boot.version}</version>
  49.                 <configuration>
  50.                     <mainClass>com.example.producer.ProducerApplication</mainClass>
  51.                     <skip>false</skip>
  52.                 </configuration>
  53.                 <executions>
  54.                     <execution>
  55.                         <id>repackage</id>
  56.                         <goals>
  57.                             <goal>repackage</goal>
  58.                         </goals>
  59.                     </execution>
  60.                 </executions>
  61.             </plugin>
  62.         </plugins>
  63.     </build>
  64. </project>
复制代码
2)配置application.yml
  1. server:
  2.   port: 8085
  3. spring:
  4.   cloud:
  5.     nacos:
  6.       discovery:
  7.         server-addr: 127.0.0.1:8848
  8.         username: nacos
  9.         password: nacos
  10.       config:
  11.         server-addr: 127.0.0.1:8848
  12.         username: nacos
  13.         password: nacos
  14.         namespace: public
  15.     loadbalancer:
  16.       nacos:
  17.         enabled: true
  18. <strong>    sentinel:
  19.       transport:
  20.         port: 8719
  21.         dashboard: 127.0.0.1:8080</strong>
  22.   application:
  23.     name: product1
复制代码
配置完成后,启动producer。访问producer中的资源/hello即可在sentinel面板中找到对就的模块。
注意:因为sentinel是lazyload模式,所以单纯的producer启动成功sentinel是不显示的。只有访问了项目的资源,sentinel才会显示对应的项目模块。
3.png

 
五、规则配置
在“链路规则”菜单中,可以看到访问过的资源。在资源右侧,可以流控、熔断、热点和授权四种规则。
4.png

 关于这四种规则的详细配置,打开设置面版一目了解,就不在此一一赘述,如果感兴趣的小伙伴可查看这里(点击查看)
在使用的过程中,会遇到以下问题:如何对资源进行通配符限制?关于这个问题,只需要在项目中添加一个UrlCleaner类,就可以对访问的url进行规整并以通配符的形式传给sentinel:
5.png

 
6、自定义限流方法
 1) 针对单个资源自定义限流方法
先定义一个处理限流的类,类内部定义自定义限流方法:
  1. package com.example.producer.component;
  2. import com.alibaba.csp.sentinel.slots.block.BlockException;
  3. import org.springframework.stereotype.Component;
  4. import java.io.IOException;
  5. @Component
  6. public class GlobalBlockHandler {
  7.     public static String handleBlock(<strong>String id,</strong>BlockException ex) throws IOException {
  8.         return "Global block handler: " + ex.getMessage();
  9.     }
  10.     public static String handleFlow(<strong>String id,</strong> Throwable ex) throws IOException {
  11.         return "Global flow handler: " + ex.getMessage();
  12.     }
  13. }
复制代码
再用@SentinelResource注解标注对应的类资源:
  1. @RestController
  2. public class HelloController {
  3.     @RequestMapping("/hello")
  4.     @SentinelResource(value = "hello",
  5.            <strong> fallback </strong><strong>= "handleFlow",
  6.             fallbackClass = com.example.producer.component.GlobalBlockHandler.class</strong><strong>,</strong>
  7.             blockHandler = "handleBlock",
  8.             blockHandlerClass = com.example.producer.component.GlobalBlockHandler.class)
  9.     public String Hello(<strong>String id</strong>){
  10.         return "hello world "+id;
  11.     }
  12. }
复制代码
这里要注意的是,自定义限流方法的参数,一定要跟controller里资源方法一致。
另外,需要重点注意的是,在sentinel控制面板内限流设置的时候,要使用资源名称去限流,自定义的限流方法才会生效;如果使用路径限流,自定义限流不生效。
6.png

2)自定义全局限流方法 
  1. @Component
  2. public class MyBlockExceptionHandler implements BlockExceptionHandler {
  3.     @Override
  4.     public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
  5.         log.info("UrlBlockHandler.....................................");
  6.         // 自定义封装的类,可以定义
  7.         Result restObject = null;
  8.         if (e instanceof FlowException) {
  9.             // 限流
  10.             restObject = ResultUtils.wrapFail(5001,"接口限流");
  11.         } else if (e instanceof DegradeException) {
  12.             // 降级
  13.             restObject = ResultUtils.wrapFail(5002,"服务降级");
  14.         } else if (e instanceof ParamFlowException) {
  15.             // 热点参数
  16.             restObject = ResultUtils.wrapFail(5003,"热点参数限流");
  17.         } else if (e instanceof SystemBlockException) {
  18.             // 系统保护
  19.             restObject = ResultUtils.wrapFail(5004,"触发系统保护规则");
  20.         } else if (e instanceof AuthorityException) {
  21.             // 授权规则
  22.             restObject = ResultUtils.wrapFail(5005,"授权规则不通过");
  23.         }
  24.         //返回json数据
  25.         response.setStatus(200);
  26.         response.setCharacterEncoding("utf-8");
  27.         response.setContentType(MediaType.APPLICATION_JSON_VALUE);
  28.         //springmvc 的一个json转换类 (jackson)
  29.         new ObjectMapper().writeValue(response.getWriter(), restObject);
  30.     }
  31. }
复制代码
重点注意:只有对路径进行限流设置,全局的限流方法才能生效;如果是针对资源名称进行限流设置,全局限流方法不被触发。
3)全局系统异常实现全局自定义限流方法
  1. import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
  2. import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
  3. import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
  4. import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
  5. import org.springframework.http.HttpStatus;
  6. import org.springframework.web.bind.annotation.ExceptionHandler;
  7. import org.springframework.web.bind.annotation.ResponseBody;
  8. import org.springframework.web.bind.annotation.RestControllerAdvice;
  9. import java.util.HashMap;
  10. import java.util.Map;
  11. @RestControllerAdvice
  12. public class CustomExceptionHandler {
  13.     /**
  14.      * 限流全局异常
  15.      */
  16.     @ExceptionHandler(FlowException.class)
  17.     public Map handlerFlowException(){
  18.         return new HashMap(){{
  19.             put("code", HttpStatus.TOO_MANY_REQUESTS.value());
  20.             put("msg", "被限流");
  21.         }};
  22.     }
  23.     /**
  24.      * 熔断全局异常
  25.      */
  26.     @ExceptionHandler(DegradeException.class)
  27.     public Map handlerDegradeException(){
  28.         return new HashMap(){{
  29.             put("code", HttpStatus.TOO_MANY_REQUESTS.value());
  30.             put("msg", "被熔断");
  31.         }};
  32.     }
  33.     /**
  34.      * 热点限流异常
  35.      */
  36.     @ExceptionHandler(ParamFlowException.class)
  37.     public Map handlerparamFlowException(){
  38.         return new HashMap(){{
  39.             put("code", HttpStatus.TOO_MANY_REQUESTS.value());
  40.             put("msg", "热点限流");
  41.         }};
  42.     }
  43.     /**
  44.      *  Sentinel 权限拦截全局异常
  45.      */
  46.     @ExceptionHandler(AuthorityException.class)
  47.     @ResponseBody
  48.     public Map handlerAuthorityException(){
  49.         return new HashMap(){{
  50.             put("code", HttpStatus.UNAUTHORIZED.value());
  51.             put("msg", "暂无权限");
  52.         }};
  53.     }
  54. }
复制代码
重点注意的是,在sentinel控制面板内限流设置的时候,要使用资源名称去限流,全局系统异常自定义的限流方法才会生效;如果使用路径限流,则不生效。
 
好了,到这里sentinel的基本使用以及自定义的限流方法已进行了较为详细的讨论。下一篇,让我们一起了解sentinel规则的持久化:)
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册