主頁 > 後端開發 > 學習一下 SpringCloud (四)-- 服務降級、熔斷 Hystrix、Sentinel

學習一下 SpringCloud (四)-- 服務降級、熔斷 Hystrix、Sentinel

2021-02-03 06:19:45 後端開發

(1) 相關博文地址:

學習一下 SpringCloud (一)-- 從單體架構到微服務架構、代碼拆分(maven 聚合): https://www.cnblogs.com/l-y-h/p/14105682.html
學習一下 SpringCloud (二)-- 服務注冊中心 Eureka、Zookeeper、Consul、Nacos :https://www.cnblogs.com/l-y-h/p/14193443.html
學習一下 SpringCloud (三)-- 服務呼叫、負載均衡 Ribbon、OpenFeign : https://www.cnblogs.com/l-y-h/p/14238203.html

 

(2)代碼地址:

https://github.com/lyh-man/SpringCloudDemo

 

一、引入 服務降級、熔斷

1、問題 與 解決

【問題:】
    通過前面幾篇博客介紹,完成了基本專案創建、服務注冊中心、服務呼叫 以及 負載均衡(也即 各個模塊 已經能正常通信、共同對外提供服務了),
    
    對于一個復雜的分布式系統來說,可能存在數十個模塊,且模塊之間可能會相互呼叫(嵌套),
    這就帶來了一個問題:
        如果某個核心模塊突然宕機(或者不能提供服務了),那么所有呼叫該 核心模塊服務 的模塊 將會出現問題,
        類似于 病毒感染,一個模塊出現問題,將逐步感染其他模塊出現問題,最終導致系統崩潰(也即服務雪崩),

【服務雪崩:】
    服務雪崩 指的是 服務提供者 不可用(不能提供服務) 而導致 服務消費者不可用,并逐級放大的程序,
    比如:
        多個微服務之間形成鏈式呼叫,A、B 呼叫 C,C 呼叫 D,D 呼叫其他服務等,,,
        如果 D 因某種原因(宕機、網路延遲等) 不能對外提供服務了,將導致 C 訪問出現問題,而 C 出現問題,將可能導致 A、B 出現問題,也即 問題逐級放大(最終可能引起系統崩潰),

【解決:】
    服務降級、服務熔斷 是解決 服務雪崩的 常用手段,
相關技術:
    Hystrix(維護狀態,不推薦使用)
    Sentienl(推薦使用)

 

 

 

 

2、服務降級 與 服務熔斷

(1) 服務降級

【服務降級:】
    服務降級 指的是 當服務器壓力 劇增 時,根據當前 業務、流量 情況 對一些服務(一般為非核心業務)進行有策略的降級,確保核心業務正常執行,
    即 釋放非核心服務 占用的服務器資源 確保 核心任務正常執行,
注:
    可以理解為 損失一部分業務能力,保證系統整體正常運行,從而防止 服務雪崩,
    資源是有限的,請求并發高時,若不對服務進行降級處理,系統可能花費大量資源進行非核心業務處理,導致 核心業務 效率降低,進而影響整體服務性能,
    此處的降級可以理解為 不提供服務 或者 延時提供服務(服務執行暫時不正常,給一個默認的回傳結果,等一段時間后,正常提供服務),
    
【服務降級分類:】
手動降級:
    可以通過修改配置中心配置,并根據事先定義好的邏輯,執行降級邏輯,

自動降級:
    超時降級:設定超時時間、超時重試次數,請求超時則服務降級,并使用異步機制檢測 進行 服務恢復,
    失敗次數降級:當請求失敗達到一定次數則服務降級,同樣使用異步機制檢測 進行服務恢復,
    故障降級:服務宕機了則服務降級,
    限流降級:請求訪問量過大則服務降級,

 

(2)服務熔斷

【服務熔斷:】
    服務熔斷 指的是 目標服務不可用 或者 請求回應超時時,為了保證整體服務可用,
    不再呼叫目標服務,而是直接回傳默認處理(釋放系統資源),通過某種演算法檢測到目標服務可用后,則恢復其呼叫,
注:
    在一定時間內,服務呼叫失敗次數達到一定比例,則認為 當前服務不可用,
    服務熔斷 可以理解為 特殊的 服務降級(即 服務不可用 --> 服務降級 --> 服務呼叫恢復), 

【martinfowler 相關博客地址:】
    https://martinfowler.com/bliki/CircuitBreaker.html

 

 

 

(3)服務降級 和 服務熔斷 的區別

【相同點:】
    目標相同:均從 可靠性、可用性 觸發,避免系統崩潰(服務雪崩),
    效果相同:均屬于 某功能暫不可用,
    
【不同點:】
    服務降級 一般 是從整體考慮,可以手動關閉 非核心業務,確保 核心業務正常執行,
    服務熔斷 一般 是某個服務不可用,自動關閉 服務呼叫,并在一定時間內 重新嘗試 恢復該服務呼叫,
注(個人理解(僅供參考)):
    服務降級 可以作為 預防措施(手動降級),即 服務并沒有出錯,但是為了提升系統效率,我主動放棄 一部分非核心業務,保證系統資源足夠用于 執行 核心業務,
    服務熔斷 就是 服務出錯的 解決方案(自動降級),即 服務出錯后 的一系列處理,

 

二、服務降級、熔斷 -- Hystrix

1、什么是 Hystrix ?

【Hystrix:】
    Hystrix 是一個用于處理分布式系統 延遲 和 容錯的 開源庫,
    目的是 隔離遠程系統、服務和第三方庫的訪問點,停止級聯故障,并在不可避免發生故障的復雜分布式系統中實作恢復能力,
注:
    分布式系統難免出現 阻塞、超時、例外 等問題,Hystrix 可以保證在一個服務出問題時,不影響整個系統使用(避免服務雪崩),提高系統的可用性,
    雖然 Hystrix 已進入維護模式,不再更新,但還是可以學習一下思想、基本使用,

【常用特性:】
    服務降級
    服務熔斷
    服務監控

【相關地址:】
    https://github.com/Netflix/Hystrix

 

 

 

2、使用 JMeter 模擬超時故障發生

(1)什么是 JMeter ?

【JMeter】
    Apache 的一款基于 Java 的壓力測驗工具,
注:
    有興趣的自行研究,此處不過多贅述,
    
【官網下載地址:】
    http://jmeter.apache.org/download_jmeter.cgi
    
【JMeter 簡單使用:】
    https://www.cnblogs.com/stulzq/p/8971531.html

 

 

 

(2)說明

【說明:】
    此處僅簡單演示,不需要啟動集群(單機版 Eureka 即可),
    eureka_server_7000 作為 服務注冊中心,
    eureka_client_producer_8001 作為服務提供者,
    eureka_client_consumer_9001 作為服務提供者, 
注:
    單機版 Eureka 可參考:https://www.cnblogs.com/l-y-h/p/14193443.html#_label2_1
    此處使用 RestTemplate 發送請求,使用上一篇 講到的 OpenFeign 技術亦可,

【演示說明:】
    在 eureka_client_producer_8001 新定義一個介面 testTimeout(),內部暫停 2 秒模擬業務處理所需時間,
    一般情況下,訪問 eureka_client_producer_8001 提供的 getUser() 介面時,會立即回應,
    
    但是如果大量請求訪問 testTimeout(),而將系統資源(執行緒)耗盡時,
    此時若有請求訪問 getUser() 就需要等待 前面請求執行完成后,才能繼續處理,
    而此時就可能造成 超時等待 的情況,從而引起一系列問題,

即:   
    并發度低時:
        先訪問 /consumer/user/testTimeout,再訪問 /consumer/user/get/{id} 可以瞬間回傳結果,

    并發度高時:
        若有大量請求訪問 /consumer/user/testTimeout,導致系統資源(執行緒)暫時耗盡,
        此時再訪問  /consumer/user/get/{id} 就需要等待一些時間才能回傳結果,
        嚴重時請求會出現超時故障,從而引起系統例外,

 

(3)定義介面
  在 eureka_client_producer_8001 中定義一個新介面 testTimeout(),
  在 eureka_client_consumer_9001 中定義一個新介面 呼叫 testTimeout(),

【eureka_client_producer_8001:】
@GetMapping("/testTimeout")
public Result testTimeout() {
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return Result.ok();
}

【eureka_client_consumer_9001:】
@GetMapping("/testTimeout")
public Result testTimeout() {
    return restTemplate.getForObject(PRODUCER_URL + "/producer/user/testTimeout", Result.class);
}

 

 

 

 

 

 

(4)啟動服務,并使用 JMeter 測驗
并發度低時:
  先訪問 /consumer/user/testTimeout,再訪問 /consumer/user/get/{id} 可以瞬間回傳結果,
注:
  看頁面的重繪按鈕,

 

 

并發度高時:
  使用 JMeter 模擬 200 個執行緒,回圈 100 次,訪問 /consumer/user/testTimeout,
  此時再訪問 /consumer/user/get/{id} 時,不能瞬間回傳結果(等待一段時間),

 

 

 

 

(5)超時故障
  前面已經演示了高并發情況下可能出現超時等待情況,而若 業務執行時間過長 或者 服務呼叫設定了超時時間,那么當訪問被阻塞時,將有可能引起故障,

【在宣告 RestTemplate 時,定義超時時間】
@Bean
@LoadBalanced // 使用 @LoadBalanced 注解賦予 RestTemplate 負載均衡的能力
public RestTemplate getRestTemplate() {
    SimpleClientHttpRequestFactory httpRequestFactory = new SimpleClientHttpRequestFactory();
    httpRequestFactory.setConnectTimeout(2000);
    httpRequestFactory.setReadTimeout(2000);
    return new RestTemplate(httpRequestFactory);
}

 

 

 

 

3、Hystrix 實作服務降級

(1)服務降級使用場景
  服務降級 目的是 防止 服務雪崩,本質也就是在 服務呼叫 出問題時,應該如何處理,

【服務降級使用場景:】
    服務器資源耗盡,請求回應慢,導致請求超時,
    服務器宕機 或者 程式執行出錯,導致請求出錯,
即:
    服務提供者 回應請求超時了,服務消費者 不能一直等待,需要 服務提供者進行 服務降級,保證 請求在一定的時間內被處理,
    服務提供者 宕機了,服務消費者 不能一直等待,需要 服務消費者進行 服務降級,保證 請求在一定的時間內被處理,
    服務提供者正常,但 服務消費者 出現問題了,需要服務消費者 自行 服務降級,
    
注:
    服務降級一般在 服務消費者 中處理,服務提供者 也可以 進行處理,

 

(2)在 服務提供者 上實作服務降級(超時自動降級)
  在 eureka_client_producer_8001 代碼基礎上進行補充,
Step1:
  引入 hystrix 依賴,

【引入依賴:】
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

 

 

Step2:
  通過 @HystrixCommand 注解 撰寫 服務降級策略,

【簡單說明:】
    @HystrixCommand 表示指定 服務降級 或者 服務熔斷的策略,
    fallbackMethod 表示服務呼叫失敗(請求超時 或者 程式執行例外)后執行的方法(方法引數要與 原方法一致),
    commandProperties 表示配置引數,
    @HystrixProperty 設定具體引數,
注:
    詳細引數情況可以參考 HystrixCommandProperties 類,
    com.netflix.hystrix.HystrixCommandProperties 


【定義服務降級策略:】
public Result testTimeoutReserveCase() {
    return Result.ok().message("當前服務器繁忙,請稍后再試!!!");
}

// 定義服務降級策略
@HystrixCommand(
        // 當請求超時 或者 介面例外時,會呼叫 fallbackMethod 宣告的方法(方法引數要一致)
        fallbackMethod = "testTimeoutReserveCase",
        commandProperties = {
                @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="https://www.cnblogs.com/l-y-h/archive/2021/02/02/1500")
        }
)
@GetMapping("/testTimeout")
public Result testTimeout() {
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return Result.ok();
}

 

 

Step3:
  在啟動類上添加 @EnableCircuitBreaker 注解,開啟服務降級、熔斷,

 

 

Step4:
  運行測驗(此處演示的是 超時自動降級),
  此處定義介面超時時間為 1.5 秒,模擬 0.5 秒業務處理時間,使用 JMeter 壓測該介面時,與上面演示的類似,會出現請求超時的情況,而一旦請求超時,則會觸發 fallbackMethod 方法,直接回傳資料,而不會持續等待,
如下圖所示,

 

 

(3)配置默認服務降級方法
  通過上面簡單演示可以完成 服務降級,但是存在一個問題,如果為每一個介面都系結一個 fallbackMethod,那么代碼將非常冗余,
  通過 @DefaultProperties 注解 定義一個默認的 defaultFallback 方法,介面例外時呼叫默認的方法,并僅對特殊的介面進行單獨處理,從而減少代碼冗余,

如下,新增一個 運行時例外,訪問介面時,將會呼叫 globalFallBackMethod() 方法,
而前面特殊定義的 testTimeout 超時后,仍呼叫 testTimeout_reserve_case() 方法,

@DefaultProperties(defaultFallback = "globalFallBackMethod")
public class UserController {
    public Result globalFallBackMethod() {
        return Result.ok().message("系統例外,請稍后再試!!!");
    }

    @GetMapping("/testRuntimeError")
    @HystrixCommand
    public Result testRuntimeError() {
        int temp = 10 / 0;
        return Result.ok();
    }
}

 

 

 

 

4、OpenFeign 實作服務降級

(1)說明

【說明:】
    上面使用 Hystrix 簡單演示了 服務提供者 的服務降級,
    這里使用 OpenFeign 演示 服務消費者 的服務降級,
注:
    重新新建一個模塊 eureka_openfeign_client_consumer_9007 作為服務消費者用于演示,
    可參考上一篇 OpenFeign 的使用:https://www.cnblogs.com/l-y-h/p/14238203.html#_label3_2
    服務提供者仍然是 eureka_client_producer_8001,

 

(2)配置 OpenFeign 基本代碼環境
Step1:
  創建模塊 eureka_openfeign_client_consumer_9007,
  修改父工程 與 當前工程 pom.xml 檔案,
  修改配置類,
  在啟動類上添加 @EnableFeignClients 注解,

【依賴:】
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

【application.yml】
server:
  port: 9007
spring:
  application:
    name: eureka-openfeign-client-consumer

eureka:
  instance:
    appname: eureka-openfeign-client-consumer-9007 # 優先級比 spring.application.name 高
    instance-id: ${eureka.instance.appname} # 設定當前實體 ID
  client:
    register-with-eureka: true # 默認為 true,注冊到 注冊中心
    fetch-registry: true # 默認為 true,從注冊中心 獲取 注冊資訊
    service-url:
      # 指向 注冊中心 地址,也即 eureka_server_7000 的地址,
      defaultZone: http://localhost:7000/eureka

# 設定 OpenFeign 超時時間(OpenFeign 默認支持 Ribbon)
ribbon:
  # 指的是建立連接所用的超時時間
  ConnectTimeout: 2000
  # 指的是建立連接后從服務器獲取資源的超時時間(即請求處理的超時時間)
  ReadTimeout: 2000

 

 

Step2:
  使用 @FeignClient 撰寫服務呼叫,

【ProducerFeignService:】
package com.lyh.springcloud.eureka_openfeign_client_consumer_9007.service;

import com.lyh.springcloud.common.tools.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "EUREKA-CLIENT-PRODUCER-8001")
@Component
public interface ProducerFeignService {
    @GetMapping("/producer/user/get/{id}")
    Result getUser(@PathVariable Integer id);

    @GetMapping("/producer/user/testTimeout")
    Result testFeignTimeout();

    @GetMapping("/producer/user/testRuntimeError")
    Result testRuntimeError();
}

 

 

Step3:
  撰寫 controller,并進行測驗 openfeign 是否能成功訪問服務,

【ConsumerController】
package com.lyh.springcloud.eureka_openfeign_client_consumer_9007.controller;

import com.lyh.springcloud.common.tools.Result;
import com.lyh.springcloud.eureka_openfeign_client_consumer_9007.service.ProducerFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/consumer/user")
public class ConsumerController {
    @Autowired
    private ProducerFeignService producerFeignService;

    @GetMapping("/get/{id}")
    public Result getUser(@PathVariable Integer id) {
        return producerFeignService.getUser(id);
    }

    @GetMapping("/testTimeout")
    public Result testFeignTimeout() {
        return producerFeignService.testFeignTimeout();
    }

    @GetMapping("/testRuntimeError")
    public Result testFeignRuntimeError() {
        return producerFeignService.testRuntimeError();
    }
}

 

 

 

 

(3)OpenFeign 實作服務降級

【步驟:】
Step1:在組態檔中,配置 feign.feign.enabled=true,開啟服務降級,
Step2:定義一個 實作類,實作 服務呼叫的 介面,并為每個方法重寫 呼叫失敗的邏輯,
Step3:在 @FeignClient 注解中,通過 fallback 引數指定 該實作類,

Step1:
  在組態檔中,開啟服務降級,

【application.yml】
# 開啟服務降級
feign:
  hystrix:
    enabled: true

 

 

Step2:
  定義一個實作類,實作 服務呼叫的介面,
  @Component 注解不要忘了,啟動時可能會報錯,

【ProducerFeignServiceImpl:】
package com.lyh.springcloud.eureka_openfeign_client_consumer_9007.service.impl;

import com.lyh.springcloud.common.tools.Result;
import com.lyh.springcloud.eureka_openfeign_client_consumer_9007.service.ProducerFeignService;
import org.springframework.stereotype.Component;

@Component
public class ProducerFeignServiceImpl implements ProducerFeignService {
    @Override
    public Result getUser(Integer id) {
        return Result.ok().message("系統例外,請稍后再試 -- 11111111111");
    }

    @Override
    public Result testFeignTimeout() {
        return Result.ok().message("系統例外,請稍后再試 -- 222222222222");
    }

    @Override
    public Result testRuntimeError() {
        return Result.ok().message("系統例外,請稍后再試 -- 333333333333");
    }
}

 

 

注:
  未添加 @Component 注解,啟動會報下面的錯誤,

【報錯資訊:】
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'consumerController': 
Unsatisfied dependency expressed through field 'producerFeignService'; nested exception is org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'com.lyh.springcloud.eureka_openfeign_client_consumer_9007.service.ProducerFeignService': 
FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: 
No fallback instance of type class com.lyh.springcloud.eureka_openfeign_client_consumer_9007.service.impl.ProducerFeignServiceImpl found for feign client EUREKA-CLIENT-PRODUCER-8001

 

 

Step3:
  在 @FeignClient 注解上,通過 fallback 引數指定上面定義的實作類,

package com.lyh.springcloud.eureka_openfeign_client_consumer_9007.service;

import com.lyh.springcloud.common.tools.Result;
import com.lyh.springcloud.eureka_openfeign_client_consumer_9007.service.impl.ProducerFeignServiceImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "EUREKA-CLIENT-PRODUCER-8001", fallback = ProducerFeignServiceImpl.class)
@Component
public interface ProducerFeignService {
    @GetMapping("/producer/user/get/{id}")
    Result getUser(@PathVariable Integer id);

    @GetMapping("/producer/user/testTimeout")
    Result testFeignTimeout();

    @GetMapping("/producer/user/testRuntimeError")
    Result testRuntimeError();
}

 

 

Step4:
  簡單測驗一下,
  當服務提供者 宕機時,此時服務呼叫失敗,將會執行 實作類中的邏輯,
  而服務提供者正常提供服務時,由于上面已經在 服務提供者 處配置了 服務降級,則執行 服務提供者的服務降級策略,

 

 

 

5、Hystrix 實作服務熔斷

(1)說明

【服務熔斷:】
    服務熔斷可以理解為特殊的服務降級,當某個服務出錯或者回應時間長時,將會進行服務降級處理,
    從而熔斷該服務的呼叫,但其會檢測服務是否正常,若正常,則恢復服務呼叫,
注:
    代碼方面 與 上面配置 超時服務自動降級 類似(在其基礎上進行代碼擴充),

【斷路器開啟、關閉條件:】
開啟條件:
    滿足一定的請求閾值(默認 10 秒內請求數超過 20),且失敗率達到閾值(默認 10 秒內 50% 的請求失敗),此時將會開啟斷路器,

關閉條件:
    斷路器開啟一段時間后(默認 5 秒),此時斷路器處于半開狀態,會對其中一部分請求進行轉發,如果成功訪問,則斷路器關閉,
    若請求仍然失敗,則再次進入開啟狀態,  

 

 

(2)添加介面配置服務熔斷
  在 eureka_client_producer_8001 中新增一個介面,并配置服務熔斷邏輯,

【服務熔斷:】
public Result testCircuitBreakerFallBack(@PathVariable Integer id) {
    return Result.ok().message("呼叫失敗, ID 不能為負數");
}

@GetMapping("/testCircuitBreaker/{id}")
@HystrixCommand(fallbackMethod = "testCircuitBreakerFallBack", commandProperties = {
        // 是否開啟斷路器,默認為 true,
        @HystrixProperty(name = "circuitBreaker.enabled", value = "https://www.cnblogs.com/l-y-h/archive/2021/02/02/true"),
        // 在一定時間內,請求總數達到了閾值,才有資格進行熔斷,默認 20 個請求,
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "https://www.cnblogs.com/l-y-h/archive/2021/02/02/10"),
        // 熔斷之后,重新嘗試恢復服務呼叫的時間,在此期間,會執行 fallbackMethod 定義的邏輯,默認 5 秒,
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "https://www.cnblogs.com/l-y-h/archive/2021/02/02/10000"),
        // 出錯閾值,請求總數超過了閾值,并且呼叫失敗率達到一定比率,會熔斷,默認 50%,
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "https://www.cnblogs.com/l-y-h/archive/2021/02/02/60")
})
public Result testCircuitBreaker(@PathVariable Integer id) {
    if (id < 0) {
        throw new RuntimeException("ID 不能為負數");
    }
    return Result.ok().message("呼叫成功, ID = " + id);
}

 

 

(3)直接訪問該服務測驗一下(使用 JMeter 測驗亦可),
  如下圖所示,當請求失敗達到一定比率,將會開啟斷路器,
  一段時間后,嘗試恢復服務呼叫,關閉斷路器,

 

 

6、Hystrix Dashboard

(1)Dashboard
  Hystrix 提供了圖形化的監控工具(Hystrix Dashboard)進行準實時的呼叫監控,其可以持續的記錄通過 Hystrix 發送的請求執行資訊,并以圖形、統計報表的形式呈現給用戶,
  SpringCloud 對其進行了整合,匯入相關依賴即可,

 

(2)使用
Step1:
  引入依賴(hystrix-dashboard 以及 actuator),

【依賴:】
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

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

 

 

Step2:
  在啟動類上添加 @EnableHystrixDashboard 注解,開啟 Dashboard,

 

 

Step3:
  啟動服務后,訪問 http://localhost:8001/hystrix,填寫需要監控的地址即可,
  開啟監控后,訪問配置了 @HystrixCommand 注解的服務時,將會觸發監控,

 

 

 

 

7、Dashboard 錯誤解決(Unable to connect to Command Metric Stream.)

(1)錯誤
  使用 Dashboard 最常見的錯誤就是 Unable to connect to Command Metric Stream,
  根據控制臺列印的 日志進行相關配置即可解決此錯誤,
  錯誤效果如下圖所示,

 

 

(2)錯誤一與解決:

【錯誤一:】
控制臺列印錯誤如下:
    Proxy opening connection to: http://localhost:8001/hystrix.stream

【解決:】
    在配置類中添加如下配置,
/**
 * 錯誤 Unable to connect to Command Metric Stream. 本質是無法決議  "/hystrix.stream",
 * 自行配置一下即可,
 */
@Bean
public ServletRegistrationBean getServlet() {
    HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
    ServletRegistrationBean<HystrixMetricsStreamServlet> registrationBean = new ServletRegistrationBean(streamServlet);
    registrationBean.setLoadOnStartup(1);
    registrationBean.addUrlMappings("/hystrix.stream");
    registrationBean.setName("HystrixMetricsStreamServlet");
    return registrationBean;
}

 

 

(3)錯誤二與解決:

【錯誤二:】
    上面解決了連接錯誤,但是仍然報錯,
控制臺列印錯誤如下:
    Origin parameter: http://localhost:8001/hystrix.stream is not in the allowed list of proxy host names.  
    If it should be allowed add it to hystrix.dashboard.proxyStreamAllowList.
    
【解決:】
    在組態檔中配置 proxyStreamAllowList 放行 host 即可,
hystrix:
  dashboard:
    proxy-stream-allow-list: "*"
#    proxy-stream-allow-list: "localhost"

 

 

三、服務降級、熔斷 -- Sentinel

1、什么是 Sentinel?

(1)什么是 Sentinel?

【Sentinel:】
    Sentinel 是阿里開源的專案,面向云原生微服務的高可用流控防護組件,
    從流量控制、熔斷降級、系統負載保護等多個維度來保障服務之間的穩定性,
注:
    官方檔案上寫的還是很詳細的,并提供了相應的中文檔案,
    此處不過多描述,僅介紹使用,相關概念、原理 請自行翻閱檔案,

【官網地址:】
    https://github.com/alibaba/Sentinel
    https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

Sentinel 主要特性如下(圖片來源于網路:)

 

 

(2)Sentinel 組成

【Sentinel 組成:】
    Sentinel 可以分為兩部分:Java 客戶端  、Dashboard 控制臺,

Java 客戶端(核心庫):    
    核心庫 不依賴于 任何框架、庫,能夠運行于 Java7 及以上版本的 Java 運行時環境,
    同時對 Dubbo / Spring Cloud 等框架也有較好的支持,
    
Dashboard 控制臺:
    基于 SpringBoot 開發,打包后可直接運行,無需額外的 Tomcat 容器部署,
    控制臺主要負責管理推送規則、監控、集群限流分配管理、機器發現等,
注:
    控制臺使用參考檔案:
        https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0
    控制臺 jar 包下載:
        https://github.com/alibaba/Sentinel/releases

注:
    通過 Dashboard 控制臺,可以很輕松的通過 web 頁面設定 服務降級、熔斷等規則,也可以通過代碼的方式進行配置,
    個人比較傾向于 web 頁面操作,省去了撰寫代碼的作業(視作業環境而定),
     后面介紹的 Dashboard 操作均以 web 界面進行操作,若想通過代碼進行配置,請自行翻閱官方檔案,
     web 頁面編輯的規則 在 重啟服務后 會丟失,需要將其進行持久化處理,一般都是持久化到 nacos 中(后續介紹),

 

(3)Hystrix 與 Sentinel 區別

【官網地址:】
    https://github.com/alibaba/Sentinel/wiki/Guideline:-%E4%BB%8E-Hystrix-%E8%BF%81%E7%A7%BB%E5%88%B0-Sentinel
注:
    詳情請自行查閱官網檔案,

 

 

 

 

2、基本模塊構建

(1)說明

【說明:】
    Sentinel 一般與 Nacos 一起使用,Nacos 使用后續介紹,此處仍使用 Eureka 進行整合,
    新建一個 eureka_client_sentinel_producer_8010 模塊(引入核心庫依賴)進行演示,
    從官網下載 sentinel-dashboard,用于啟動 Dashboard 界面,
注:
    下載地址:https://github.com/alibaba/Sentinel/releases    

 

(2)下載并啟動 sentinel-dashboard,
Step1:下載 sentinel-dashboard,

 

 

Step2:命令列啟動 jar 包,

【命令列啟動 jar 包:】
    java -jar sentinel-dashboard-1.8.0.jar
注:
    啟動后,默認訪問埠為 8080,可以通過 -Dserver.port 引數進行修改,
    比如: java -jar -Dserver.port=8888 sentinel-dashboard-1.8.0.jar
    
【訪問地址:】
    通過 IP + 埠 即可進入登錄界面,登錄用戶、密碼 都默認為 sentinel,
    比如:http:localhost:8888

 

 

 

 

(3)基本模塊 eureka_client_sentinel_producer_8010 創建
Step1:
  修改 父工程、當前工程 pom.xml 檔案,并引入相關依賴,

【直接引入依賴(帶上版本號):】
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>

【或者在父工程中統一進行版本管理:】
<properties>
  <spring.cloud.alibaba.version>2.1.0.RELEASE</spring.cloud.alibaba.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-alibaba-dependencies</artifactId>
          <version>${spring.cloud.alibaba.version}</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

注:
    spring-cloud-alibaba 各版本地址:
    https://github.com/alibaba/spring-cloud-alibaba/releases

 

 

Step2:
  修改組態檔,配置 dashboard 資訊,

【application.yml】
server:
  port: 8010

spring:
  application:
    name: eureka_client_sentinel_producer_8010
  # 配置 sentinel
  cloud:
    sentinel:
      transport:
        # 配置 sentinel-dashboard 地址,此處在本地啟動,所以 host 為 localhost
        dashboard: localhost:8888
        # 應用與 dashboard 互動的埠,默認為 8719 埠
        port: 8719

eureka:
  instance:
    appname: eureka_client_sentinel_producer_8010 # 優先級比 spring.application.name 高
    instance-id: ${eureka.instance.appname} # 設定當前實體 ID
  client:
    register-with-eureka: true # 默認為 true,注冊到 注冊中心
    fetch-registry: true # 默認為 true,從注冊中心 獲取 注冊資訊
    service-url:
      # 指向 注冊中心 地址,也即 eureka_server_7000 的地址,
      defaultZone: http://localhost:7000/eureka

 

 

Step3:
  撰寫測驗 controller,進行測驗,

【TestController】
package com.spring.cloud.eureka_client_sentinel_producer_8010.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/testSentinel")
public class TestController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello World";
    }

    @GetMapping("/relation")
    public String relation() {
        return "relation";
    }
}

 

Step4:
  啟動 eureka_server_7000、以及當前服務 ,測驗一下,
注:
  即使服務啟動,Sentinel Dashboard 也是空白的,需要呼叫一下當前服務的介面,其相關資訊才會出現在 Sentinel 中,

 

 

 

 

3、Sentinel Dashboard 使用 -- 流控規則

(1)什么是流量控制(flow control)?

【流量控制:】
    流量控制 本質上是 監控 應用流量的 QPS 或者 并發執行緒數等指標,
    當監控的指標達到 閾值 后,將會對訪問進行限制,減少請求的正常回應,
    從而避免應用 被瞬間的高并發請求擊垮而崩潰,進而保障應用的高可用性,
注:
    QPS(Query Per Second):每秒查詢率,即服務每秒能回應的查詢(請求)次數,

【檔案地址:】
    https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6

 

(2)流控規則基本引數

【相關類:】
    com.alibaba.csp.sentinel.slots.block.flow.FlowRule
注:
    通過代碼設定流控規則可以參考如下代碼:
    https://github.com/alibaba/Sentinel/blob/master/sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/flow/FlowQpsDemo.java

【流控規則頁面引數:】
資源名:
    默認為 請求的資源路徑,唯一,
    
針對來源:
    默認為 default,表示不區分來源,
注:
    網上查閱的資料都說可以根據 微服務名 進行限流,有待確認,
    此處未研究原理,留個坑,后續有時間再去研究,
    
閾值型別:
    QPS:
        當呼叫該資源介面的 QPS 達到閾值后,將會限流,
    執行緒數:
        當呼叫該資源介面的 執行緒數 達到閾值后,將會限流,
        
單機閾值:
    設定 閾值型別(QPS、執行緒數)的 閾值,

流控模式:
    直接:
        當資源介面達到限流條件時,會當前資源直接限流,
    關聯:
        當某個資源關聯的資源達到限流條件時,則 當前資源 被限流,
    鏈路:
        資源之間的呼叫形成呼叫鏈路,而 鏈路 模式僅記錄 指定入口的流量,如果達到限流條件,則限流,
        
流控效果:
    快速失敗:
        一旦達到限流條件,則直接拋例外(FlowException),然后走失敗的處理邏輯,
    Warm Up:
        根據冷加載因子(coldFactor,默認 3),剛開始閾值請求數為 原閾值/coldFactor,經過一段時間后,閾值才會變為 原閾值,
    排隊等待:
        請求會排隊等待執行,勻速通過,此時的 閾值型別必須為 QPS, 

 

 

(3)演示 -- 直接、快速失敗,

【說明:】
配置 /testSentinel/hello 的流控規則,不區分請求來源,
當 QPS 超過 1(即 1 秒鐘超過 1 次查詢)時,將會執行 直接限流,效果為 快速失敗(會顯示默認錯誤),

【設定流控規則如下:】
資源名: /testSentinel/hello
針對來源: default
閾值型別: QPS
單機閾值: 1
流控模式: 直接
流控效果: 快速失敗

 

 

如下圖所示,1 秒重繪一次是正常回傳的結果,而 1 秒重繪多次后,將會輸出默認的錯誤資訊,

 

 

(4)演示 -- 關聯、快速失敗,

【說明:】
現有資源 A、B,A 為 /testSentinel/hello,B 為 /testSentinel/relation,
配置 A 的流控規則,不區分請求來源,將 A 關聯 B,
當 B 的 QPS 超過 1(即 1 秒鐘超過 1 次查詢)時,A 將會被限流,效果為 快速失敗(會顯示默認錯誤),

【設定流控規則如下:】
資源名: /testSentinel/hello
針對來源: default
閾值型別: QPS
單機閾值: 1
流控模式: 關聯
關聯資源: /testSentinel/relation
流控效果: 快速失敗

【實際使用場景舉例:】
    兩個資源之間具有依賴關系或者競爭資源時,可以使用關聯,
比如:
    對資料庫 讀操作、寫操作 進行限制,可以設定寫操作優先,當 寫操作 過于頻繁時,讀操作將被限流,

 

 如下圖所示,正常訪問 A 是沒問題的,但是 B 在 1 秒內多次重繪后,A 將會輸出默認出錯資訊,

 

 

(5)演示 -- 直接、Wram Up,

【說明:】
配置 /testSentinel/hello 的流控規則,不區分請求來源,
設定 QPS 為 6,預熱時間為 3 秒,則開始 QPS 閾值將為 2,預熱時間結束后,QPS 會恢復到 6,

【設定流控規則如下:】
資源名: /testSentinel/hello
針對來源: default
閾值型別: QPS
單機閾值: 6
流控模式: 直接
流控效果: Warm Up
預熱時長: 3

【實際場景舉例:】
秒殺系統開啟瞬間會有很多請求進行訪問,如果不做限制,可能一下子系統直接崩潰了,
采用 Warm Up 方式,給系統一個緩沖時間,慢慢的增大 QPS,

 

 如下圖所示,開始 QPS 較小,重繪容易報錯,3 秒后,QPS 恢復原值,重繪不容易報錯,

 

 

(6)演示 --  直接、排隊等待

【說明:】
配置 /testSentinel/hello 的流控規則,不區分請求來源,
QPS 超過 1 時,請求將會排隊等待,超時時間為 2 秒,超時后將會輸出錯誤資訊,

【設定流控規則如下:】
資源名: /testSentinel/hello
針對來源: default
閾值型別: QPS
單機閾值: 1
流控模式: 直接
流控效果: 排隊等待
超時時間: 2000

【實際場景舉例:】
    通常用于處理 間隔性請求,
比如:
    訊息佇列,某瞬間的請求很多,但之后卻沒有請求,此時可以使用排隊等待,將請求延遲執行(而不是直接拒絕),

 

 如下圖所示,快速重繪頁面時,請求將會排隊等待執行,超時后將會報錯,

 

 

4、@SentinelResource 注解

(1)@SentinelResource 注解
  @SentinelResource 可以等同于 Hystrix 中的 @HystrixCommand 注解進行理解,

【相關地址:】
    https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81
    
【@SentinelResource:】
    @SentinelResource 注解用于定義資源,并提供了可選的例外處理 以及 fallback 配置項,

value:資源名稱,必須項(不能為空),
    
blockHandler:
    指定限流例外(BlockException)發生后,應該執行的方法,
    注意事項:
        方法訪問權限修飾符為 public,
        回傳值型別 與 原方法回傳值型別一致,
        引數型別 與 原方法一致,并追加一個 額外引數,引數型別為 BlockException,
        blockHandler 指定的函式默認需要與 原方法在同一個類中,

blockHandlerClass:
    指定限流例外(BlockException)發生后,應該執行的方法(此方法可以位于 其他類),
    注意事項:
        方法訪問權限修飾符為 public,
        方法必須是 static 函式,否則無法決議,

fallback:
    指定例外(除了 exceptionsToIgnore 指定的例外外的例外)發生后,應該執行的方法,
    注意事項:
        回傳值型別 與 原方法回傳值型別一致,
        引數型別 與 原方法一致,可以額外增加一個 Throwable 型別的引數用于接收對應的例外,
        fallback 指定的函式默認需要與 原方法在同一個類中,
        
fallbackClass:
    指定例外發生后,應該執行的方法(此方法可以位于 其他類),
    注意事項:
        方法訪問權限修飾符為 public,
        方法必須是 static 函式,否則無法決議, 

defaultFallback:
    指定例外發生后,執行默認的邏輯(即 通用處理邏輯),
    與 fallback 類似,但 其指定的方法引數為空,可以額外增加一個 Throwable 型別的引數用于接收對應的例外,
   當 fallback 與 defaultFallback 同時存在時,只有 fallback 會生效,

exceptionsToIgnore:
    用于指定哪些例外被排除掉,不會計入例外統計中,也不會進入 fallback 邏輯中(直接對外拋出原例外),

【@SentinelResource 使用注意事項:】
    若 blockHandler 和 fallback 都配置了,當限流降級例外發生時(即 拋出 BlockException),只會執行 blockHandler 指定的方法,
   若未配置 fallback、blockHandler 時,則限流降級時,則可能直接拋出 BlockException 例外,若方法本身沒定義 throws BlockException,則例外將會被 JVM 包裝為 UndeclaredThrowableException 例外,

可以簡單的理解為: 
    blockHandler 用于指定 限流、降級 等例外(BlockException)發生后應該執行的規則,
    fallback 用于指定 其他例外(比如: RuntimeException)發生后應該執行的規則,

 

 

(2)@SentinelResource 使用舉例

【說明:】
    在 controller 中新增如下代碼,
    fallback() 表示例外發生后的回呼函式,
    defaultFallback() 表示例外發生后默認的回呼函式,
    blockHandler()、blockHandler2() 表示 流控、降級 等 BlockException 例外發生后的回呼函式,
        
    testBlockHandler() 用于測驗 blockHandler 引數,
    testFallback() 用于測驗 fallback 引數,
    testDefaultFallback() 用于測驗 defaultFallback 引數,

【新增代碼:】
public String fallback(Integer id, Throwable ex) {
    return ex.getMessage();
}

public String defaultFallback(Throwable ex) {
    return ex.getMessage();
}

public String blockHandler(BlockException ex) {
    return "block Handler";
}

public String blockHandler2(Integer id, BlockException ex) {
    return "block Handler --------- 2";
}

@GetMapping("/testBlockHandler")
@SentinelResource(value = "testBlockHandler", blockHandler = "blockHandler")
public String testBlockHandler() {
    return "ok";
}

@GetMapping("/testFallback/{id}")
@SentinelResource(value = "testFallback", blockHandler = "blockHandler", fallback = "fallback")
public String testFallback(@PathVariable Integer id) {
    if (id > 10) {
        throw new RuntimeException("fallback");
    }
    return "ok";
}

@GetMapping("/testDefaultFallback/{id}")
@SentinelResource(value = "testDefaultFallback", blockHandler = "blockHandler2", defaultFallback = "defaultFallback")
public String testDefaultFallback(@PathVariable Integer id) {
    if (id > 10) {
        throw new RuntimeException("defaultFallback");
    }
    return "ok";
}

 

 

Step1:
  訪問 testBlockHandler(),測驗 blockHandler 執行回呼函式,
  如下,給 testBlockHandler 添加流控規則,當 QPS 大于 1 時,將進行限流,此時將會執行 blockHandler 指定的回呼函式,
注:
  正常訪問 testBlockHandler() 時,sentinel dashboard 會監控到兩個資源名,此處應選擇 @SentinelResource 注解中 value 定義的資源名,并配置 流控、降級 規則,

 

 

 

 

 

 

Step2:
  訪問 testFallback(),測驗 fallback 執行回呼函式,
  當 id 小于等于 10 時,正常呼叫,
  當 id 大于 10 時,拋出例外后被 fallback 接收并執行回呼函式,
  同樣,設定 流控規則,QPS 大于 1 時,限流,但由于 blockHandler 引數指定的回呼方法引數 與 原方法不同,所以該回呼函式不生效(空白),
注:
  限流、降級 等例外 執行的是 blockHandler 指定的回呼函式,
  而其他例外 執行的是 fallback 指定的回調函式,

 

 

 

 

Step3:
  訪問 testDefaultFallback(),測驗 defaultFallback 執行回呼函式,
  與上例類似,只是此處 blockHandler 回呼函式引數 與 原方法相同,可以呼叫成功,

 

 

 

 

5、Sentinel Dashboard 使用 -- 降級規則、系統規則(系統自適應限流)

(1)熔斷降級
  熔斷降級相關概念,前面在 Hystrix 已經介紹了,
  此處僅演示 Sentinel 降級操作,

【降級策略:】
慢呼叫比例(SLOW_REQUEST_RATIO): 
    若選擇 慢呼叫比例 作為閾值,需外同時設定幾個引數,
    引數:
        慢呼叫最大回應時間(最大 RT),當請求回應時間大于該值時,將被統計為慢呼叫,
        比例閾值,比率的閾值范圍是 [0.0, 1.0],代表 0% - 100%,當慢呼叫比例大于該值時,將會觸發熔斷機制,
        最小請求數,單位統計時長內接收請求的最小數,
        熔斷時長,熔斷執行的時間,
    簡單解釋:
        當單位統計時長(statIntervalMs)內請求數目 大于 最小請求數,且 慢呼叫比例(超時請求占總請求數的比例) 大于 比例閾值 時,
        將會在一定的 熔斷時長 內熔斷請求(執行 熔斷的相關代碼),
        熔斷時長結束后,會進入探測恢復狀態(即 Hystrix 中提到的 HALF-OPEN 狀態),若檢測到接下來的一個請求正常呼叫,則結束熔斷,若依舊超時,則再次熔斷,
注:
    此處的 HALF-OPEN 狀態,來源于官網介紹(針對 Sentinel 1.8.0 及以上版本),
    舊版本可能沒有 HALF-OPEN 狀態(沒實際驗證過),

例外比例(ERROR_RATIO):
    例外比例 與 慢呼叫比例 類似,例外比例的引數少了個 最大回應時間,
    簡單解釋:
        當單位統計時長(statIntervalMs)內請求數目 大于 最小請求數,且 例外比例(例外請求占總請求數的比例) 大于 比例閾值 時,
        將會在一定的 熔斷時長 內熔斷請求(執行 熔斷的相關代碼),
        熔斷時長結束后,會進入探測恢復狀態(HALF-OPEN 狀態),若檢測到接下來的一個請求正常呼叫,則結束熔斷,否則會再次被熔斷,

例外數(ERROR_COUNT):
    例外數 與 例外比例 類似,例外數 將引數 例外比例 變為 例外數(直接監控例外數,而非比例),
    簡單解釋:
        當單位統計時長(statIntervalMs)內 例外請求數 超過 例外數閾值 后,
        將會在一定的 熔斷時長 內熔斷請求(執行 熔斷的相關代碼),
        熔斷時長結束后,會進入探測恢復狀態(HALF-OPEN 狀態),若檢測到接下來的一個請求正常呼叫,則結束熔斷,否則會再次被熔斷,

 

 

(2)演示 -- 例外比例
  在上面 testDefaultFallback() 基礎上,添加 降級 規則,演示 例外比例 降級,
注:
  洗掉添加的流控規則,并指定 降級規則,
  當降級發生時,將會觸發 blockHandler 指定的回呼方法,

 

 

 

 

(3)系統規則

【相關檔案:】
    https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81

【什么是系統規則(系統自適應限流):】
    系統自適應限流 是從 整體維度 對 應用程式 入口流量 進行控制,即 在呼叫應用程式的 方法(介面) 前,將請求攔截下來,
    通過自適應的流控策略,讓 系統的入口流量 和 系統的負載 達到一個平衡,即 讓系統盡可能 在保證 最大吞吐量的同時 保證 系統整體的穩定性,
常用指標: 
    應用的負載(Load)、
    CPU 使用率、
    總體平均回應時間(RT)、
    入口 QPS、
    并發執行緒數 等,

 

 

 

 

6、OpenFeign 整合 Sentinel(引入 sentinel 依賴需要注意版本問題)

(1)說明

【說明:】
    OpenFeign 一般用于消費端,此處以 eureka_client_consumer_9001 為基礎,整合 Sentinel,
注:
    此處為了省事,直接用之前創建好的子模塊,亦可自行創建新的模塊,
    使用流程 與 Hystrix 類似,

 

(2)整合 Sentinel
Step1:
  在 eureka_client_consumer_9001 基礎上引入 依賴,

【依賴:】
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<!-- alibaba-sentinel -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2.2.1.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </exclusion>
    </exclusions>
</dependency>

【注意事項:(巨坑)】
    alibaba-sentinel 的版本可能會影響程式的執行,

此處使用的版本:
    springcloud  Hoxton.SR9
    spring.cloud.alibaba 2.1.0.RELEASE
    springboot 2.3.5.RELEASE
引入 alibaba-sentinel 依賴后,服務一直無法啟動,
報錯:
    nested exception is java.lang.AbstractMethodError: Receiver class com.alibaba.cloud.sentinel.feign.SentinelContractHolder does not define or inherit an implementation of the resolved method 'abstract java.util.List parseAndValidateMetadata(java.lang.Class)' of interface feign.Contract.

具體原因沒整明白,但是如上引入依賴后,可以解決問題(有時間再去研究),

 

 

 

 

Step2:
  修改組態檔,開啟 Sentinel 對 Feign 的支持,

【application.yml】
# 開啟 sentinel 對 feign 的支持
feign:
  sentinel:
    enabled: true

 

 

Step3:
  使用 @FeignClient 撰寫服務呼叫,

【ProducerFeignService】
package com.lyh.springcloud.eureka_client_consumer_9001.service;

import com.lyh.springcloud.eureka_client_consumer_9001.service.impl.ProducerFeignServiceImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "EUREKA-CLIENT-SENTINEL-PRODUCER-8010", fallback = ProducerFeignServiceImpl.class)
@Component
public interface ProducerFeignService {

    @GetMapping("/testSentinel/testDefaultFallback/{id}")
    String testDefaultFallback(@PathVariable Integer id);

    @GetMapping("/testSentinel/hello")
    String hello();
}

【ProducerFeignServiceImpl】
package com.lyh.springcloud.eureka_client_consumer_9001.service.impl;

import com.lyh.springcloud.eureka_client_consumer_9001.service.ProducerFeignService;
import org.springframework.stereotype.Component;

@Component
public class ProducerFeignServiceImpl implements ProducerFeignService {
    @Override
    public String testDefaultFallback(Integer id) {
        return "系統例外,請稍后重試 --------- 1111111111111";
    }

    @Override
    public String hello() {
        return "系統例外,請稍后重試 --------- 2222222222222";
    }
}

 

 

Step4:
  撰寫 controller,

【TestController】
package com.lyh.springcloud.eureka_client_consumer_9001.controller;

import com.lyh.springcloud.eureka_client_consumer_9001.service.ProducerFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/consumer2")
@RestController
public class TestController {

    @Autowired
    private ProducerFeignService producerFeignService;

    @GetMapping("/testDefaultFallback/{id}")
    public String testDefaultFallback(@PathVariable Integer id) {
        return producerFeignService.testDefaultFallback(id);
    }

    @GetMapping("/hello")
    public String hello() {
        return producerFeignService.hello();
    }
}

 

 

Step5:
  在啟動類上添加 @EnableFeignClients 注解,開啟 feign 功能,

 

 

Step6:
  測驗,
  給 testDefaultFallback() 添加流控規則,QPS 大于 1 時將限流,
  QPS 小于等于 1 時,正常訪問,
  若遠程服務斷開后,訪問 testDefaultFallback() 將失敗,從而執行本地添加的邏輯,

 

 

 

 

7、持久化配置資訊到 Nacos 

 后續使用到 Nacos 再介紹,此處暫時省略,,,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/255841.html

標籤:其他

上一篇:(一)MyBatis從入門到入土——簡介

下一篇:什么是IOC容器?為什么需要IOC容器?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more