springcloud alibaba 之 sentinel

大名鼎鼎的 sentinel没用过的都想用,用过都说好,下面是集成过程。

项目源码

在开始之前首先需要看一下

一、搭建 sentinel服务

sentinel docker选择以下一种即可

sentinel:
  container_name: sentinel-dashboard
  image: registry.cn-hangzhou.aliyuncs.com/lcts/sentinel-dashboard:1.7.1
  restart: always
  ports:
    - "8858:8080"
  environment:
      TZ : "Asia/Shanghai"

会在本地端口 8858启动一个 sentinel服务

访问 http://localhost:8858默认账户和密码是 sentinel

二、在项目中集成 sentinel

  • maven依赖
<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
<!--提供 sentinel 监控-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!-- sentinel 与 dubbo2.7.x以上的整合包 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-apache-dubbo-adapter</artifactId>
            <version>1.7.1</version>
        </dependency>
        <!-- sentinel 提供 AspectJ 的扩展用于自动定义资源、处理 BlockException等 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-annotation-aspectj</artifactId>
            <version>1.7.1</version>
        </dependency>
  • 基于 bean的配置
/**
 * Sentinel 配置
 */
@Configuration
public class SentinelConfiguration {

    /**
     * 配置方法级别的Sentinel aop
     */
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }

    /**
     * 让web层请求都经过 sentinelFilter,如果不需要监控web层 可以去掉这个方法
     */
    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() {
        FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new CommonFilter());
        registration.addUrlPatterns("/*");
        registration.setName("sentinelFilter");
        registration.setOrder(1);

        return registration;
    }
}
  • 启动配置中增加
spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8858
    nacos:
      discovery:
        server-addr: localhost:8848  #Nacos服务器侦听器的IP和端口 #80不能省略
        weight:  10 # 值范围:1到100。值越大,权重越大

三、在项目中使用 sentinel

  • 演示在 controller层的使用
@RestController
@RequestMapping("/config")
public class ConfigController {

    @Value("${spring.profiles.active}")
    String active;
    @Autowired
    RestTemplate restTemplate;

    /**
     * http://localhost:8080/config/get
     */
    @GetMapping("get")
    public String get(@RequestParam(required = false) String str) {
        return active + " | " + str;
    }

    /**
     * http://localhost:8080/config/rest
     */
    @SentinelResource("ss")
    @GetMapping("rest")
    public String rest() {
        return restTemplate.getForObject("http://nacos-provider/config/get/" + "?str=consumerSend", String.class);
    }
}

  • 基于业务实现层的使用
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.lc.cloud.alibaba.api.TestDubboService;
import com.lc.cloud.alibaba.consumer.fuse.SentinelTestServiceBlockHandler;
import com.lc.cloud.alibaba.consumer.fuse.SentinelTestServiceFallbackHandler;
import com.lc.cloud.alibaba.consumer.domain.service.SentinelTestService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

@Service
public class SentinelTestServiceImpl implements SentinelTestService {
    @Reference
    TestDubboService testDubboService;

    /*******
     * 注意 :若 blockHandler 和 fallback 都进行了配置
     * 则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑
     */
    @SentinelResource(blockHandler = "get2BlockHandler",
            blockHandlerClass = {SentinelTestServiceBlockHandler.class},
            fallback = "get1FallbackHandler",
            fallbackClass = {SentinelTestServiceFallbackHandler.class})
    @Override
    public String get(String str) {
        if (1 == 1) throw new RuntimeException("自定义异常");
        return testDubboService.get(str);
    }

    @SentinelResource(blockHandler = "get2BlockHandler",
            blockHandlerClass = {SentinelTestServiceBlockHandler.class})
    @Override
    public String get2(String str) {
        if (1 == 1) throw new RuntimeException("自定义异常");
        return testDubboService.get2(str);
    }

    @SentinelResource(fallback = "get3Fallback")
    @Override
    public String get3(String str) {
        if (1 == 1) throw new RuntimeException("自定义异常");
        return testDubboService.get3(str);
    }

    //这里的服务降级或回退方法只需要  public 修饰
    public String get2BlockHandler(String str) {
        return "get2BlockHandler :" + str;
    }

    public String get3Fallback(String str) {
        return "get3Fallback :" + str;
    }
}
注意:
  • 最灵性的地方在于 @SentinelResource注解,想要哪个被监控就加哪个,上面基于 bean配置的时候已经加入了 web层 ,所以 web层不需要显式使用这个注解了

  • blockHandlerClass fallbackClass对应的方法 必须是 public static修饰 ,而且调用优先级最高。也就是在有

blockHandler   
fallback  
blockHandlerClass 
fallbackClass

都存在的情况下,只会调用 blockHandlerClass fallbackClass

  • 需要特别注意的是 @SentinelResource下面的这几个属性的用法,这里不使用篇幅介绍了,可以直接去看本项目源码,或者 sentinel文档
 /**
     * @return name of the Sentinel resource
     */
    String value() default "";
/**
     * @return name of the block exception function, empty by default
     */
    String blockHandler() default "";

    /**
     * The {@code blockHandler} is located in the same class with the original method by default.
     * However, if some methods share the same signature and intend to set the same block handler,
     * then users can set the class where the block handler exists. Note that the block handler method
     * must be static.
     *
     * @return the class where the block handler exists, should not provide more than one classes
     */
    Class<?>[] blockHandlerClass() default {};

    /**
     * @return name of the fallback function, empty by default
     */
    String fallback() default "";

    /**
     * The {@code defaultFallback} is used as the default universal fallback method.
     * It should not accept any parameters, and the return type should be compatible
     * with the original method.
     *
     * @return name of the default fallback method, empty by default
     * @since 1.6.0
     */
    String defaultFallback() default "";

    /**
     * The {@code fallback} is located in the same class with the original method by default.
     * However, if some methods share the same signature and intend to set the same fallback,
     * then users can set the class where the fallback function exists. Note that the shared fallback method
     * must be static.
     *
     * @return the class where the fallback method is located (only single class)
     * @since 1.6.0
     */
    Class<?>[] fallbackClass() default {};

四、在监控面板中使用 sentinel

访问 http://localhost:8858默认账户和密码是 sentinel后 请求上面的示例,你会看到惊喜,更多用法请参考 sentinel文档

到此 sentinel集成完成

欢迎关注我的个人公众号

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章