溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

springboot如何實(shí)現(xiàn)集成與使用Sentinel

發(fā)布時間:2020-11-03 15:01:51 來源:億速云 閱讀:2711 作者:Leah 欄目:開發(fā)技術(shù)

今天就跟大家聊聊有關(guān)springboot如何實(shí)現(xiàn)集成與使用Sentinel,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

進(jìn)入Sentinel的git,點(diǎn)擊下載提供的dashboard,最新的為1.8

springboot如何實(shí)現(xiàn)集成與使用Sentinel

下載到本地之后,其實(shí)就是一個springboot打成的jar包,windows環(huán)境下,cmd窗口,直接通過下面的命令啟動即可,

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

springboot如何實(shí)現(xiàn)集成與使用Sentinel

啟動成功后,訪問一下吧,初次訪問,需要登錄用戶名和密碼,均為 : sentinel/sentinel

springboot如何實(shí)現(xiàn)集成與使用Sentinel

但是進(jìn)來之后發(fā)現(xiàn)空空如也,別緊張,這個dashboard默認(rèn)是懶加載的,意思就是沒有應(yīng)用接入進(jìn)來,它就不展示任何信息,等到我們將本地的服務(wù)通過配置接入的時候就能看到效果了

springboot如何實(shí)現(xiàn)集成與使用Sentinel

springboot工程快速接入dashboard

1、導(dǎo)入基本的依賴

 <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&#63;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

 #設(shè)置單個文件最大上傳大小
 servlet:
  multipart:
   max-file-size: 20MB

mybatis-plus:
 mapper-locations: classpath*:mapper/*.xml
 global-config:
  db-column-underline: true #開啟駝峰轉(zhuǎn)換
  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語句便于調(diào)試

#暴露的健康檢查服務(wù)端點(diǎn)
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,發(fā)現(xiàn)相關(guān)的可配置菜單和可視化界面的參數(shù)就都展示了出來

springboot如何實(shí)現(xiàn)集成與使用Sentinel

dashboard使用簡單說明

其實(shí)在上一篇中,我們談到了使用Sentinel提供的API配置的多種限流規(guī)則,比如基于QPS下的快速失敗,預(yù)熱,勻速隊(duì)列,關(guān)聯(lián)鏈路等,而dashboard上面的配置則正好對應(yīng)其底層的各種配置規(guī)則,下面我們演示幾種常用的場景吧

springboot如何實(shí)現(xiàn)集成與使用Sentinel

在簇點(diǎn)鏈路這一欄,圖中可以看到我們的后端服務(wù)接口即剛剛調(diào)用過的接口就會展示在這里,配置限流規(guī)則可以通過加號中的”添加流控“進(jìn)行配置,

springboot如何實(shí)現(xiàn)集成與使用Sentinel

規(guī)則1:QPS,如上所示,我們配置了針對訪問testFlow這個接口的所有來源的請求進(jìn)行QPS的限流,每秒最大允許通過2個請求,

springboot如何實(shí)現(xiàn)集成與使用Sentinel

配置完畢后,當(dāng)我們再次快速訪問接口時,會出現(xiàn)下面的結(jié)果,很明顯,我們的配置規(guī)則生效了

springboot如何實(shí)現(xiàn)集成與使用Sentinel

在上面的演示中,其實(shí)我們用到的就是最基本的降級策略,就是基于QPS的快速降級,我們不妨點(diǎn)開高級選項(xiàng),是不是發(fā)現(xiàn)這里有了更多的配置,其實(shí)在可視化界面下,使用它做限流規(guī)則配置時就是使用它提供的不同配置項(xiàng)組合使用

springboot如何實(shí)現(xiàn)集成與使用Sentinel

關(guān)聯(lián)配置

springboot如何實(shí)現(xiàn)集成與使用Sentinel

鏈路配置,比如多個微服務(wù)之間存在多級調(diào)用時,請求第一個服務(wù)接口,而第一個服務(wù)再調(diào)用第二個服務(wù)接口,第一個服務(wù)請求接口失敗了,這時候再訪問第二個服務(wù)接口時就會快速失敗,通過這種配置規(guī)則可以避免服務(wù)的雪崩

springboot如何實(shí)現(xiàn)集成與使用Sentinel

關(guān)于流控效果,在前一篇中我們通過簡單的demo演示了效果,就不再贅述了

關(guān)于降級

還以前面的 /testFlow接口為例:

springboot如何實(shí)現(xiàn)集成與使用Sentinel

服務(wù)降級可能大家并不陌生,即在一個應(yīng)用中,當(dāng)請求到某個服務(wù)接口長時間沒有響應(yīng)時,為了避免更多的請求進(jìn)來造成服務(wù)的雪崩,我們采取一種機(jī)制,讓程序快速返回結(jié)果,或者干脆拋出友好的提示,讓調(diào)用者知道當(dāng)前的服務(wù)不可用,這樣就不至于出現(xiàn)服務(wù)端的線程資源被耗盡的情況

對于上述圖中的配置,解釋起來就是:超過了每秒請求的閾值之后,后面的請求再過來的時候,在5秒之內(nèi),服務(wù)處于不可用的狀態(tài),5秒之后,服務(wù)恢復(fù),我們通過快速刷新接口,可以看到效果

springboot如何實(shí)現(xiàn)集成與使用Sentinel

如果是異常數(shù)的配置,則觸發(fā)條件如下:

  • 開啟條件:1秒內(nèi),有一個/testFlow請求過來,便開啟熔斷檢查
  • 觸發(fā)熔斷:當(dāng)前時間窗口內(nèi),有超過50%的請求產(chǎn)生異常
  • 觸發(fā)熔斷之后的5秒內(nèi),再有請求過來,都會被blocked

springboot如何實(shí)現(xiàn)集成與使用Sentinel

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

在上面我們?yōu)?/testFlow這個接口配置了限流的規(guī)則,當(dāng)請求超過每秒2個時,后端返回了下面的異常,這個異常是由Sentinel框架自身返回的提示

Blocked by Sentinel (flow limiting)

但在真實(shí)的開發(fā)中,這樣做并不友好,而且對于調(diào)用者來說,并不知道到底出了什么問題,甚至前端的同學(xué)也不知道怎么做后續(xù)的處理,因此需要服務(wù)端對Sentinel的異常進(jìn)行處理

@SentinelResource

使用這個注解,可以對我們要進(jìn)行限流的資源接口當(dāng)出現(xiàn)異常時進(jìn)行捕獲,比如下面的這個接口 getByResource,@SentinelResource的使用很簡單,最基本的就是配置資源名稱,加上blockHandler ,blockHandler 里面是觸發(fā)限流規(guī)則時的方法,即在這個方法中進(jìn)行后續(xù)的業(yè)務(wù)處理,如拋出友好的提示等

@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中對這個接口進(jìn)行配置,每秒1次的QPS,正常訪問時,

springboot如何實(shí)現(xiàn)集成與使用Sentinel

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

springboot如何實(shí)現(xiàn)集成與使用Sentinel

但是如果這么做的話,很明顯的一個問題就是,異常處理的邏輯和業(yè)務(wù)耦合在一起,代碼會越來越膨脹,后續(xù)不方便管理,因此我們單獨(dú)提供一個類,這個類專門用于提供不同的異常方法,

public class CustomerBlockHandler {

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

那么在接口中我們就可以這樣調(diào)用

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

同樣,再在控制臺配置限流規(guī)則后可以達(dá)到我們的效果,

springboot如何實(shí)現(xiàn)集成與使用Sentinel

Sentinel降級處理

有這么一種情況,當(dāng)調(diào)用接口時,由于參數(shù)校驗(yàn)不通過,或者后端拋出了運(yùn)行時的異常,如果沒有合適的處理,將會出現(xiàn)下面的結(jié)果,

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

springboot如何實(shí)現(xiàn)集成與使用Sentinel

顯然,這是一種不太友好的情況,對于這種情況,就可以使用Sentinel的服務(wù)降級進(jìn)行處理了,改造后的接口如下:

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

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

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

springboot如何實(shí)現(xiàn)集成與使用Sentinel

同樣我們可以利用一個單獨(dú)的類,統(tǒng)一處理這樣的降級,如下:

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

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

}

其實(shí)在真實(shí)的開發(fā)中,不管是單應(yīng)用還是微服務(wù)之間的調(diào)用,一般情況下可能出現(xiàn)的異常我們基本上都是可以提前預(yù)知的,如超時異常,系統(tǒng)參數(shù)異常等,這樣我們就可以預(yù)設(shè)部分的降級處理方法,在適當(dāng)?shù)慕涌谏厦孢M(jìn)行引用即可

Sentinel降級處理結(jié)合feign的使用

在上一篇和本次的dashboard的講解使用中,我們提到了鏈路的處理規(guī)則,對應(yīng)于不同的微服務(wù)來說就是不同的服務(wù)之間的調(diào)用,當(dāng)調(diào)用某個服務(wù)接口失敗時的情況,以openfeign的使用為例,本例我們在createOrder接口中,還調(diào)用了storage服務(wù)中的接口,

@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";
  }

設(shè)想,假如在調(diào)用getPaymentById接口失敗時,為了不至于因?yàn)閳?bào)錯或者長時間的超時等待造成雪崩,我們可以統(tǒng)一feignService中進(jìn)行處理,這里需要提供一個類,比如FallBackStorageService,這個類實(shí)現(xiàn)了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;
  }
}

即當(dāng)storage模塊中的getPaymentById服務(wù)接口異?;蛘卟豢捎脮r,將會由FallBackStorageService 中的getPaymentById進(jìn)行降級,俗稱兜底

當(dāng)然不要忘了在yml中添加如下這一句配置,讓Sentinel支持在feign調(diào)用時對于異常的生效

feign:
 sentinel:
  enabled: true

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

springboot如何實(shí)現(xiàn)集成與使用Sentinel

這時我們停掉storage服務(wù),再次訪問上面的接口時,很明顯就走到了我們的降級邏輯中,當(dāng)然我這里只是做了很簡單的處理,可以在降級邏輯中添加更友好的提示信息

springboot如何實(shí)現(xiàn)集成與使用Sentinel

當(dāng)然上面是服務(wù)不可用的時候的降級邏輯,當(dāng)情況是異常時候,我們可以通過實(shí)現(xiàn)FallbackFactory接口進(jìn)行處理

@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("異常觸發(fā):" + throwable.getMessage());
        return 1001;
      }
    };
  }
}

看完上述內(nèi)容,你們對springboot如何實(shí)現(xiàn)集成與使用Sentinel有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI