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

(1) 相關博文地址:html

學習一下 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)代碼地址:java

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

 

1、引入 服務降級、熔斷

一、問題 與 解決

【問題:】
    經過前面幾篇博客介紹,完成了基本項目建立、服務註冊中心、服務調用 以及 負載均衡(也即 各個模塊 已經能正常通訊、共同對外提供服務了)。
    
    對於一個複雜的分佈式系統來講,可能存在數十個模塊,且模塊之間可能會相互調用(嵌套),
    這就帶來了一個問題:
        若是某個核心模塊忽然宕機(或者不能提供服務了),那麼全部調用該 核心模塊服務 的模塊 將會出現問題,
        相似於 病毒感染,一個模塊出現問題,將逐步感染其餘模塊出現問題,最終致使系統崩潰(也即服務雪崩)。

【服務雪崩:】
    服務雪崩 指的是 服務提供者 不可用(不能提供服務) 而致使 服務消費者不可用,並逐級放大的過程。
    好比:
        多個微服務之間造成鏈式調用,A、B 調用 C,C 調用 D,D 調用其餘服務等。。。
        若是 D 因某種緣由(宕機、網絡延遲等) 不能對外提供服務了,將致使 C 訪問出現問題,而 C 出現問題,將可能致使 A、B 出現問題,也即 問題逐級放大(最終可能引發系統崩潰)。

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

 

 

 

 

二、服務降級 與 服務熔斷

(1) 服務降級git

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

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

 

(2)服務熔斷github

【服務熔斷:】
    服務熔斷 指的是 目標服務不可用 或者 請求響應超時時,爲了保證總體服務可用,
    再也不調用目標服務,而是直接返回默認處理(釋放系統資源),經過某種算法檢測到目標服務可用後,則恢復其調用。
注:
    在必定時間內,服務調用失敗次數達到必定比例,則認爲 當前服務不可用。
    服務熔斷 能夠理解爲 特殊的 服務降級(即 服務不可用 --> 服務降級 --> 服務調用恢復)。 

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

 

 

 

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

【相同點:】
    目標相同:均從 可靠性、可用性 觸發,避免系統崩潰(服務雪崩)。
    效果相同:均屬於 某功能暫不可用。
    
【不一樣點:】
    服務降級 通常 是從總體考慮,能夠手動關閉 非核心業務,確保 核心業務正常執行。
    服務熔斷 通常 是某個服務不可用,自動關閉 服務調用,並在必定時間內 從新嘗試 恢復該服務調用。
注(我的理解(僅供參考)):
    服務降級 能夠做爲 預防措施(手動降級),即 服務並無出錯,可是爲了提高系統效率,我主動放棄 一部分非核心業務,保證系統資源足夠用於 執行 核心業務。
    服務熔斷 就是 服務出錯的 解決方案(自動降級),即 服務出錯後 的一系列處理。

 

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

一、什麼是 Hystrix ?

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

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

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

 

 

 

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

(1)什麼是 JMeter ?算法

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

 

 

 

(2)說明spring

【說明:】
    此處僅簡單演示,不須要啓動集羣(單機版 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} 能夠瞬間返回結果。
注:
  看頁面的刷新按鈕。express

 

 

併發度高時:
  使用 JMeter 模擬 200 個線程,循環 100 次,訪問 /consumer/user/testTimeout。
  此時再訪問 /consumer/user/get/{id} 時,不能瞬間返回結果(等待一段時間)。apache

 

 

 

 

(5)超時故障
  前面已經演示了高併發狀況下可能出現超時等待狀況,而若 業務執行時間過長 或者 服務調用設置了超時時間,那麼當訪問被阻塞時,將有可能引發故障。

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

 

 

 

 

三、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="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();
    }
}

 

 

 

 

四、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:
  簡單測試一下。
  當服務提供者 宕機時,此時服務調用失敗,將會執行 實現類中的邏輯。
  而服務提供者正常提供服務時,因爲上面已經在 服務提供者 處配置了 服務降級,則執行 服務提供者的服務降級策略。

 

 

 

五、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 = "true"),
        // 在必定時間內,請求總數達到了閾值,纔有資格進行熔斷。默認 20 個請求。
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
        // 熔斷以後,從新嘗試恢復服務調用的時間,在此期間,會執行 fallbackMethod 定義的邏輯。默認 5 秒。
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
        // 出錯閾值,請求總數超過了閾值,而且調用失敗率達到必定比率,會熔斷。默認 50%。
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
})
public Result testCircuitBreaker(@PathVariable Integer id) {
    if (id < 0) {
        throw new RuntimeException("ID 不能爲負數");
    }
    return Result.ok().message("調用成功, ID = " + id);
}

 

 

(3)直接訪問該服務測試一下(使用 JMeter 測試亦可)。
  以下圖所示,當請求失敗達到必定比率,將會開啓斷路器。
  一段時間後,嘗試恢復服務調用,關閉斷路器。

 

 

六、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 註解的服務時,將會觸發監控。

 

 

 

 

七、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"

 

 

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

一、什麼是 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
注:
    詳情請自行查閱官網文檔。

 

 

 

 

二、基本模塊構建

(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 中。

 

 

 

 

三、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

【實際場景舉例:】
    一般用於處理 間隔性請求。
好比:
    消息隊列,某瞬間的請求不少,但以後卻沒有請求,此時可使用排隊等待,將請求延遲執行(而不是直接拒絕)。

 

 以下圖所示,快速刷新頁面時,請求將會排隊等待執行,超時後將會報錯。

 

 

四、@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 回調函數參數 與 原方法相同,能夠調用成功。

 

 

 

 

五、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、
    併發線程數 等。

 

 

 

 

六、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() 將失敗,從而執行本地添加的邏輯。

 

 

 

 

七、持久化配置信息到 Nacos 

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

相關文章
相關標籤/搜索