1. 程式人生 > 程式設計 >springboot整合與使用Sentinel的方法

springboot整合與使用Sentinel的方法

前言

在上一篇中,我們初步瞭解了Sentinel的基本概念,以及其有關限流方面的基礎理論,本篇將通過簡單的與框架進行整合,看看Sentinel如何在實際專案中進行使用

控制檯安裝與部署

在實際的小微服務中,使用Sentinel做限流還有另一個強大的利器,就是其提供的dashboard,儘管我們可以通過編寫Sentinel提供的一些API限流規則封裝一些通用的方法,但是這對於很多初次接觸Sentinel的同學來說,學習成本仍然不小,而提供的dashboard可以很方便的通過介面配置的方式達到上一篇中我們追求的效果,甚至更加靈活,而開發人員無非要做的就是,在程式程式碼中,只需要捕獲限流後的異常並拋給頁面提醒呼叫者即可,

進入Sentinel的git,點選下載提供的dashboard,最新的為1.8

在這裡插入圖片描述

下載到本地之後,其實就是一個springboot打成的jar包,windows環境下,cmd視窗,直接通過下面的命令啟動即可,

java -jar -Dserver.port=9100 sentinel-dashboard-1.8.0.jar

在這裡插入圖片描述

啟動成功後,訪問一下吧,初次訪問,需要登入使用者名稱和密碼,均為 : sentinel/sentinel

在這裡插入圖片描述

但是進來之後發現空空如也,別緊張,這個dashboard預設是懶載入的,意思就是沒有應用接入進來,它就不展示任何資訊,等到我們將本地的服務通過配置接入的時候就能看到效果了

在這裡插入圖片描述

springboot工程快速接入dashboard

1、匯入基本的依賴

 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.2.1.RELEASE</version>
    </dependency>

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

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql-connector-java.version}</version>
    </dependency>

		<dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-sentinel</artifactId>
    </dependency>

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

    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

2、yml配置

server:
 port: 8082

spring:
 datasource:
  driver-class-name: com.mysql.cj.jdbc.Driver
  url: jdbc:mysql://IT:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
  username: root
  password: root

#logging:
# config: classpath:logback-spring.xml #日誌

 application:
  name: service-order

 #註冊中心使用nacos
 cloud:
  nacos:
   discovery:
    server-addr: IP:8848
    
  #連線sentinel的dashboard
  sentinel:
   transport:
    dashboard: localhost:9100

 #設定單個檔案最大上傳大小
 servlet:
  multipart:
   max-file-size: 20MB

mybatis-plus:
 mapper-locations: classpath*:mapper/*.xml
 global-config:
  db-column-underline: true #開啟駝峰轉換
  db-config:
   id-type: uuid
   field-strategy: not_null
  refresh: true
 configuration:
  map-underscore-to-camel-case: true
  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #列印sql語句便於除錯

#暴露的健康檢查服務端點
management:
 endpoints:
  web:
   exposure:
    include: '*'

3、編寫簡單的controller介面

@RestController
public class FlowController {

  @Autowired
  private FlowService flowService;

  @GetMapping("/testFlow")
  public String testFlow(){
    return flowService.doFlow();
  }

}

瀏覽器訪問一次:localhost:8082/testFlow 之後,這次再觀察dashboard,發現相關的可配置選單和視覺化介面的引數就都展示了出來

在這裡插入圖片描述

dashboard使用簡單說明

其實在上一篇中,我們談到了使用Sentinel提供的API配置的多種限流規則,比如基於QPS下的快速失敗,預熱,勻速佇列,關聯鏈路等,而dashboard上面的配置則正好對應其底層的各種配置規則,下面我們演示幾種常用的場景吧

在這裡插入圖片描述

在簇點鏈路這一欄,圖中可以看到我們的後端服務介面即剛剛呼叫過的介面就會展示在這裡,配置限流規則可以通過加號中的”新增流控“進行配置,

在這裡插入圖片描述

規則1:QPS,如上所示,我們配置了針對訪問testFlow這個介面的所有來源的請求進行QPS的限流,每秒最大允許通過2個請求,

在這裡插入圖片描述

配置完畢後,當我們再次快速訪問介面時,會出現下面的結果,很明顯,我們的配置規則生效了

在這裡插入圖片描述

在上面的演示中,其實我們用到的就是最基本的降級策略,就是基於QPS的快速降級,我們不妨點開高階選項,是不是發現這裡有了更多的配置,其實在視覺化介面下,使用它做限流規則配置時就是使用它提供的不同配置項組合使用

在這裡插入圖片描述

關聯配置

在這裡插入圖片描述

鏈路配置,比如多個微服務之間存在多級呼叫時,請求第一個服務介面,而第一個服務再呼叫第二個服務介面,第一個服務請求介面失敗了,這時候再訪問第二個服務介面時就會快速失敗,通過這種配置規則可以避免服務的雪崩

在這裡插入圖片描述

關於流控效果,在前一篇中我們通過簡單的demo演示了效果,就不再贅述了

關於降級

還以前面的 /testFlow介面為例:

在這裡插入圖片描述

服務降級可能大家並不陌生,即在一個應用中,當請求到某個服務介面長時間沒有響應時,為了避免更多的請求進來造成服務的雪崩,我們採取一種機制,讓程式快速返回結果,或者乾脆丟擲友好的提示,讓呼叫者知道當前的服務不可用,這樣就不至於出現服務端的執行緒資源被耗盡的情況

對於上述圖中的配置,解釋起來就是:超過了每秒請求的閾值之後,後面的請求再過來的時候,在5秒之內,服務處於不可用的狀態,5秒之後,服務恢復,我們通過快速重新整理介面,可以看到效果

在這裡插入圖片描述

如果是異常數的配置,則觸發條件如下:

  • 開啟條件:1秒內,有一個/testFlow請求過來,便開啟熔斷檢查
  • 觸發熔斷:當前時間視窗內,有超過50%的請求產生異常
  • 觸發熔斷之後的5秒內,再有請求過來,都會被blocked

在這裡插入圖片描述

Sentinel異常處理、註解使用、與限流

在上面我們為 /testFlow這個介面配置了限流的規則,當請求超過每秒2個時,後端返回了下面的異常,這個異常是由Sentinel框架自身返回的提示

Blocked by Sentinel (flow limiting)

但在真實的開發中,這樣做並不友好,而且對於呼叫者來說,並不知道到底出了什麼問題,甚至前端的同學也不知道怎麼做後續的處理,因此需要服務端對Sentinel的異常進行處理

@SentinelResource

使用這個註解,可以對我們要進行限流的資源介面當出現異常時進行捕獲,比如下面的這個介面 getByResource,@SentinelResource的使用很簡單,最基本的就是配置資源名稱,加上blockHandler ,blockHandler 裡面是觸發限流規則時的方法,即在這個方法中進行後續的業務處理,如丟擲友好的提示等

@RestController
public class RateLimitController {

  @GetMapping("/getByResource")
  @SentinelResource(value = "getByResource",blockHandler = "handleException")
  public ResponseResult getByResource(){
    return ResponseResult.success("this is success result");
  }

  public ResponseResult handleException(BlockException blockExe){
    return ResponseResult.fail(412,"is block:" + blockExe.getMessage());
  }

}

同樣,我們在dashboard中對這個介面進行配置,每秒1次的QPS,正常訪問時,

在這裡插入圖片描述

快速訪問時,就走到了降級後的方法中了

在這裡插入圖片描述

但是如果這麼做的話,很明顯的一個問題就是,異常處理的邏輯和業務耦合在一起,程式碼會越來越膨脹,後續不方便管理,因此我們單獨提供一個類,這個類專門用於提供不同的異常方法,

public class CustomerBlockHandler {

  public static ResponseResult handleException(BlockException exe){
    return ResponseResult.fail(412,"is block:" + exe.getMessage());
  }
}

那麼在介面中我們就可以這樣呼叫

@GetMapping("/getByResource1")
  @SentinelResource(value = "customerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,blockHandler = "handleException")
  public ResponseResult getByResource1(){
    return ResponseResult.success("this is success result");
  }

同樣,再在控制檯配置限流規則後可以達到我們的效果,

在這裡插入圖片描述

Sentinel降級處理

有這麼一種情況,當呼叫介面時,由於引數校驗不通過,或者後端丟擲了執行時的異常,如果沒有合適的處理,將會出現下面的結果,

@GetMapping("/createOrder")
  @SentinelResource(value = "fallback")
  public String createOrder(String id){
    if(id.equals("2")){
      throw new IllegalArgumentException("引數異常");
    }
    return orderService.createOrder(id);
  }

在這裡插入圖片描述

顯然,這是一種不太友好的情況,對於這種情況,就可以使用Sentinel的服務降級進行處理了,改造後的介面如下:

@GetMapping("/createOrder")
  @SentinelResource(value = "fallback",fallback = "getFallBack")
  public String createOrder(String id){
    if(id.equals("2")){
      throw new IllegalArgumentException("引數異常");
    }
    return orderService.createOrder(id);
  }

  public static String getFallBack(String id,Throwable t){
    return id + ":=====>" + t.getMessage();
  }

再次訪問時,可以看到出現了我們的降級方法,也可以理解為兜底的方法

在這裡插入圖片描述

同樣我們可以利用一個單獨的類,統一處理這樣的降級,如下:

@GetMapping("/createOrder")
  @SentinelResource(value = "fallback",fallbackClass = MyFallBackHandler.class,fallback = "getFallBack")
  public String createOrder(String id){
    if(id.equals("2")){
      throw new IllegalArgumentException("引數異常");
    }
    return orderService.createOrder(id);
  }
public class MyFallBackHandler {

  public static String getFallBack(String id,Throwable t){
    return id + ":=====>" + t.getMessage();
  }

}

其實在真實的開發中,不管是單應用還是微服務之間的呼叫,一般情況下可能出現的異常我們基本上都是可以提前預知的,如超時異常,系統引數異常等,這樣我們就可以預設部分的降級處理方法,在適當的介面上面進行引用即可

Sentinel降級處理結合feign的使用

在上一篇和本次的dashboard的講解使用中,我們提到了鏈路的處理規則,對應於不同的微服務來說就是不同的服務之間的呼叫,當呼叫某個服務介面失敗時的情況,以openfeign的使用為例,本例我們在createOrder介面中,還呼叫了storage服務中的介面,

@Component
@FeignClient(value = "service-storage")
public interface StorageFeignService {

  @GetMapping(value = "/storage/get/{id}")
  public Integer getPaymentById(@PathVariable("id") String id);
}
	@Autowired
  private StorageFeignService feignService;

  @Override
  public String createOrder(String id) {
    int storage = feignService.getPaymentById(id);
    log.info("storage is = {}",storage);
    return "success";
  }

設想,假如在呼叫getPaymentById介面失敗時,為了不至於因為報錯或者長時間的超時等待造成雪崩,我們可以統一feignService中進行處理,這裡需要提供一個類,比如FallBackStorageService,這個類實現了StorageFeignService 介面

@Component
@FeignClient(value = "service-storage",fallback = FallBackStorageService.class)
public interface StorageFeignService {

  @GetMapping(value = "/storage/get/{id}")
  public Integer getPaymentById(@PathVariable("id") String id);
}
@Component
public class FallBackStorageService implements StorageFeignService {

  @Override
  public Integer getPaymentById(String id) {
    return 1001;
  }
}

即當storage模組中的getPaymentById服務介面異常或者不可用時,將會由FallBackStorageService 中的getPaymentById進行降級,俗稱兜底

當然不要忘了在yml中新增如下這一句配置,讓Sentinel支援在feign呼叫時對於異常的生效

feign:
 sentinel:
  enabled: true

那我們簡單測試下吧,正常訪問時:

在這裡插入圖片描述

這時我們停掉storage服務,再次訪問上面的介面時,很明顯就走到了我們的降級邏輯中,當然我這裡只是做了很簡單的處理,可以在降級邏輯中新增更友好的提示資訊

在這裡插入圖片描述

當然上面是服務不可用的時候的降級邏輯,當情況是異常時候,我們可以通過實現FallbackFactory介面進行處理

@Component
public class FeignFallbackHandler implements FallbackFactory<StorageFeignService> {
  
  @Override
  public StorageFeignService create(Throwable throwable) {
    return new StorageFeignService(){
      @Override
      public Integer getPaymentById(String id) {
        System.out.println("異常觸發:" + throwable.getMessage());
        return 1001;
      }
    };
  }
}

本篇到這裡就要結束了,通過本篇內容,比較詳細的介紹了Sentinel的相關使用,基於dashboard配置的各種限流規則,以及結合程式中進行使用,最後提到了和feign整合使用時的處理方法,篇幅較長,最後感謝觀看!

到此這篇關於springboot整合與使用Sentinel的方法的文章就介紹到這了,更多相關springboot Sentinel整合與使用內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!