Alibaba Sentinel(1):快速上手

Alibaba Sentinel 是一個靈活的系統負載控制框架,通過控制接口和方法的調用來保證系統負載不會過大,維持正常響應速度。

該項目的地址是 https://github.com/alibaba/Se... 。但是阿里的文檔一貫看起來一頭霧水,所以本文介紹如何用一個最簡單的項目來上手。如果你熟悉 Spring Boot,那麼幾分鐘就可以搞定。

1、創建一個 Maven 項目

首先創建一個空的 Maven 項目,加上 Spring Boot 的依賴。pom.xml 看起來是下面的樣子,你可以直接拿來用:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
        http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.demo</groupId>
  <artifactId>sentinel-test</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.1.3.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

</project>

這裏沒有將 Spring Boot 作爲 parent 項目,而是使用 <dependencyManagement>,但效果是一樣的。

2、添加依賴關係

pom.xml 中,首先添加 Spring Boot 依賴:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
</dependency>

然後添加 Sentinel。在這個例子當中,我們將用 註解 來實現負載控制,所以添加 sentinel-annotation-aspectj 依賴:

<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-annotation-aspectj</artifactId>
  <version>1.5.1</version>
</dependency>

添加了這兩個依賴就 OK 了。

3、啓動類

Spring Boot 項目需要一個 main() 方法來啓動,我們命名這個類爲 com.demo.SentinelTestApplication,其內容如下:

@SpringBootApplication
public class SentinelTestApplication {
  public static void main(String[] args) throws Exception {
    SpringApplication.run(SentinelTestApplication.class, args);
  }
}

目前這個類還沒有具體的內容,但我們應該先運行一下,確保前面做的事情沒有出錯,然後再添加內容。

4、需要進行訪問控制的服務 DemoService

我們在 com.demo 包下創建一個名爲 DemoService 的類,這個類包含一個需要做訪問控制的 call() 方法:

@Service
public class DemoService {

  private int counter;

  @SentinelResource(value = "DemoService.call", blockHandler = "callBlocked")
  public void call() {
    System.out.println("Hello (" + ++counter + ")");
  }

  public void callBlocked(BlockException ex) {
    System.err.println("Blocked (" + ++counter + ") : " + ex.toString());
  }
}

所謂訪問控制就是當某個方法調用過於頻繁時,拒絕掉一部分調用。什麼才叫過於頻繁,我們可以通過自定義控制規則的方式來告訴 Sentinel。定義控制規則的部分放在後面介紹,我們現在先關注業務本身,也就是 DemoService 類。

這個類包含兩個方法,其中 call() 方法是主角,正常的業務會調用這個方法;而 callBlocked() 則會在 call() 方法被拒絕掉時調用。

call() 方法上面的 @SentinelResource 註解標明瞭該方法是需要進行訪問控制的。Sentinel 將需要進行訪問控制的方法都稱作資源。這個註解有兩個屬性,value 屬性表示該資源的名稱,我們通過名稱爲不同的資源制定不同的控制規則。blockHandler 屬性表示方法被拒絕時應該調用哪個替代方法,這個替代方法必須在同一個類當中,且參數列表要在原方法參數列表的基礎上再添加一個 BlockException 類型的參數。

5、編寫控制規則

Sentinel 將控制規則包裝爲 com.alibaba.csp.sentinel.slots.block.flow.FlowRule 類。它包含下面幾個屬性:

  • resource : 該規則針對哪個資源;
  • grade : 從哪個方面進行度量,如該方法的每秒調用次數,或同時調用該方法的線程數等等。
  • count : 度量閾值。超過這個閾值則會拒絕調用該方法。
  • strategy : 多個規則之間的搭配策略,具體參考這裏

下面我們在 SentinelTestApplication 類裏面添加一個創建規則的方法,同時在 main() 方法裏面初始化它:

  private static void initRules() throws Exception {
    FlowRule rule1 = new FlowRule();
    rule1.setResource("DemoService.call");
    rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule1.setCount(5);   // 每秒調用最大次數爲 5 次

    List<FlowRule> rules = new ArrayList<>();
    rules.add(rule1);
    
    // 將控制規則載入到 Sentinel
    com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager.loadRules(rules);  
  }

  public static void main(String[] args) throws Exception {
    initRules();  // Sentinel 載入規則不一定非要在 Spring 初始化之前,在這之後也可以。
    SpringApplication.run(SentinelTestApplication.class, args);
  }

這樣 Sentinel 的規則就設置完畢。

6、啓用 Sentinel 註解的 AOP 攔截

Spring 提供 AOP 機制來實現方法調用的攔截,這是 Sentinel 實現控制規則的原理。Sentinel 提供 com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect 類,我們要在 Spring 容器中加入這個 bean 才能讓 @SentinelResource 註解起作用。我們需要在 SentinelTestApplication 類裏面添加下面的代碼:

  @Bean
  public SentinelResourceAspect sentinelResourceAspect() {
    return new SentinelResourceAspect();
  }

當然,在實際項目裏面這一步可以放到自動配置當中。

7、測試控制規則

最後我們寫一個方法來測試控制規則是否起作用,同樣是在 SentinelTestApplication 類裏面:

  @Autowired
  private DemoService demoService;

  @PostConstruct
  public void run() {
    for (int i = 0; i < 10; i++) {
      demoService.call();
    }
  }

實際運行 main() 方法時,你將會看到這樣的輸出:

Hello (1)
Hello (2)
Hello (3)
Hello (4)
Hello (5)
Blocked (6) : com.alibaba.csp.sentinel.slots.block.flow.FlowException
Blocked (7) : com.alibaba.csp.sentinel.slots.block.flow.FlowException
Blocked (8) : com.alibaba.csp.sentinel.slots.block.flow.FlowException
Blocked (9) : com.alibaba.csp.sentinel.slots.block.flow.FlowException
Blocked (10) : com.alibaba.csp.sentinel.slots.block.flow.FlowException

通過這個例子,你應該大概瞭解 Sentinel 運作的機制了。在這個基礎上,Sentinel 還能實現控制規則的實時修改、遠程配置、狀態監控等等,它是個非常強大的框架。

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