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集成完成

歡迎關注我的個人公衆號

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