SpringCloud(二、服務組件Eureka、ribbon、feign、Hystrix、Gateway)

內容概述

spring cloud的各種組件

Feign 聲明式服務調用【掌握】
Hystrix 熔斷器【掌握】
Gateway 網關【掌握】

每個組件都是爲了解決微服務系統中的問題的。

一、Feign-概述

疑問: spring cloud遠程調用還是讓人覺得不好用,能不能像dubbo那樣,直接調用遠程的方法?

• Feign 是一個聲明式的 REST 客戶端,它用了基於接口的註解方式,很方便實現客戶端配置。

• Feign 最初由 Netflix 公司提供。eureka也是Netflix 公司

二、Feign-快速入門

疑問: 如何使用feign客戶端進行遠程調用?

操作步驟:

  1. 在消費端feign-consumer 引入 open-feign 依賴
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. Feign是基於ribbon負載均衡的,使用前必須有ribbon配置。編寫Feign調用接口
@Configuration
public class RestTemplateConfig {


@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}




/**
*
* feign聲明式接口。發起遠程調用的。
*
String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
Goods goods = restTemplate.getForObject(url, Goods.class);
*
* 1. 定義接口
* 2. 接口上添加註解 @FeignClient,設置value屬性爲 服務提供者的 應用名稱
* 3. 編寫調用接口,接口的聲明規則 和 提供方接口保持一致。
* 4. 注入該接口對象,調用接口方法完成遠程調用
*
*/

@FeignClient(value = "FEIGN-PROVIDER")
public interface GoodsFeignClient {


@GetMapping("/goods/findOne/{id}")
public Goods findGoodsById(@PathVariable("id") int id);

}

  1. 在啓動類 添加 @EnableFeignClients 註解,開啓Feign功能
@EnableDiscoveryClient // 激活DiscoveryClient
@EnableEurekaClient
@SpringBootApplication

@EnableFeignClients //開啓Feign的功能
public class ConsumerApp {


public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class,args);
}
}

  1. controller 調用
@RestController
@RequestMapping("/order")
public class OrderController {

@Autowired
private GoodsFeignClient goodsFeignClient;

@GetMapping("/goods/{id}")
public Goods findGoodsById(@PathVariable("id") int id){

Goods goods = goodsFeignClient.findGoodsById(id);

return goods;
}

}
  1. 測試調用

http://localhost:9000/order/goods/1

三、Feign-超時配置 先配置熔斷才行

疑問:遠程調用,連接或者業務處理慢,超時了會有什麼現象?

• Feign 底層依賴於 Ribbon 實現負載均衡和遠程調用。
• Ribbon默認1秒超時。

超時會報錯ReadTimeout,我們可以根據業務進行設置。
配置方式:


#配置熔斷的時間監聽
hystrix:
  command:
    default:
      execution:
          isolation:
            thread:
              timeoutInMilliseconds: 3000


# 設置Ribbon的超時時間
ribbon:
  ConnectTimeout: 1000 # 連接超時時間 默認1s
  ReadTimeout: 3000 # 邏輯處理的超時時間 默認1s

四、Feign-日誌記錄

疑問:遠程調用都被feign給封裝了,如何才能看到請求,響應的細節,數據?

分析:
配置feign的日誌記錄

操作步驟:

  1. 設置當前日誌的級別爲debug
# 設置當前的日誌級別 debug,feign只支持記錄debug級別的日誌
logging:
level:
cn.kinggm520: debug     #調用了feign客戶端所在代碼的包名
  1. 定義Feign日誌級別Bean
@Configuration
public class FeignLogConfig {


/*
NONE,不記錄
BASIC,記錄基本的請求行,響應狀態碼數據
HEADERS,記錄基本的請求行,響應狀態碼數據,記錄響應頭信息
FULL;記錄完成的請求 響應數據


*/

@Bean
public Logger.Level level(){
return Logger.Level.FULL;
}
}
  1. 啓動Feign日誌級別Bean
@FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class)
public interface GoodsFeignClient {


@GetMapping("/goods/findOne/{id}")
public Goods findGoodsById(@PathVariable("id") int id);

}
  1. 測試

http://localhost:9000/order/goods/1

五、Hystrix 熔斷器-概述

• Hystix 是 Netflix 開源的一個延遲和容錯庫,用於隔離訪問遠程服務、第三方庫,防止出現級聯失敗(雪崩)。
• 雪崩:一個服務失敗,導致整條鏈路的服務都失敗的情形。

Hystix 主要功能
• 隔離

  1. 線程池隔離

  2. 信號量隔離

• 降級:異常,超時

• 熔斷

• 限流

總結: 主要解決服務器出現意外以後,應用該如何處理。

六、Hystrix 降級-服務提供方

疑問: 服務提供方何時會降級,如何編寫代碼?
分析:

服務提供方何時會降級?

兩種情況:

  1. 服務端代碼拋異常

  2. 服務端代碼超時(默認1秒鐘)

Hystrix 降級 – 服務提供方

操作步驟:

  1. 在服務提供方,引入 hystrix 依賴
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  1. 在啓動類上開啓Hystrix功能:@EnableCircuitBreaker
/**
* 啓動類
*/

@EnableEurekaClient 
@SpringBootApplication
@EnableCircuitBreaker // 開啓Hystrix功能
public class ProviderApp {
  1. 定義降級方法
/**
* 定義降級方法:
*  1. 方法的返回值需要和原方法一樣
*  2. 方法的參數需要和原方法一樣
*  3. 就是隻有方法名不同
*/
public Goods findOne_fallback(int id){
Goods goods = new Goods();
goods.setTitle("降級了~~~");

return goods;
}
  1. 使用 @HystrixCommand 註解配置降級方法
@GetMapping("/findOne/{id}")
@HystrixCommand(fallbackMethod = "findOne_fallback")
public Goods findOne(@PathVariable("id") int id){
。。。
}
  1. 如果要設置降級配置的屬性,可以通過@HystrixCommand註解的commandProperties屬性進行配置,配置的信息在HystrixCommandProperties類中定義。瞭解常用設置即可。
@GetMapping("/findOne/{id}")
@HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
//設置Hystrix的超時時間,默認1s
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")

})
public Goods findOne(@PathVariable("id") int id){

總結:

​ 定義的降級方法要和controller方法完全一致,除了方法名。通過fallbackMethod指定降級方法,只需要設置方法名即可,不要帶括號什麼的。

七、Hystrix 降級 – 服務消費方

疑問:那要是網絡有問題,都不能連上提供方,還能降級嗎?

分析:

Hystrix 降級 – 服務消費方

操作步驟:

  1. feign 組件已經集成了 hystrix 組件。

在這裏插入圖片描述

  1. 在application.yml中配置開啓 feign.hystrix.enabled = true
# 開啓feign對hystrix的支持
feign:
hystrix:
enabled: true
  1. 定義feign 調用接口實現類,複寫方法,即 降級方法
/**
* Feign 客戶端的降級處理類
* 1. 定義類 實現 Feign 客戶端接口
* 2. 使用@Component註解將該類的Bean加入SpringIOC容器
*/
@Component
public class GoodsFeignClientFallback implements GoodsFeignClient {
@Override
public Goods findGoodsById(int id) {
Goods goods = new Goods();
goods.setTitle("又被降級了~~~");
return goods;
}
}

  1. 在 @FeignClient 註解中使用 fallback 屬性設置降級處理類。
@FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class)
public interface GoodsFeignClient {


@GetMapping("/goods/findOne/{id}")
public Goods findGoodsById(@PathVariable("id") int id);

}

總結:

​ 注意編寫的調用方降級類需要實現Feign客戶端的接口,還要添加@Component註解交給spring容器管理。

問題:如果服務器端程序拋出異常,那麼提供方還是消費方的降級方法生效?

​ 提供方生效,因爲提供方降級後,將會給消費方返回了正常的結果,所以消費方就不會生效。

問題

服務處理的時間過長,但是不想因爲超時降級,還需要得到服務器的結果,如何配置?

配置兩個方面:

  1. feign客戶端調用的時候 先配置熔斷超時

#配置熔斷的時間監聽
hystrix:
  command:
    default:
      execution:
          isolation:
            thread:
              timeoutInMilliseconds: 3000


# 設置Ribbon的超時時間
ribbon:
  ConnectTimeout: 1000 # 連接超時時間 默認1s
  ReadTimeout: 3000 # 邏輯處理的超時時間 默認1s
  1. 服務提供方降級的時間
@GetMapping("/findOne/{id}")
@HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
//設置Hystrix的超時時間,默認1s
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public Goods findOne(@PathVariable("id") int id){

八、Hystrix 熔斷-概念

Hystrix 熔斷機制,用於監控微服務調用情況,當失敗的情況達到預定的閾值(5秒失敗20次),會打開斷路器,拒絕所有請求,直到服務恢復正常爲止。

在這裏插入圖片描述

總結:

熔斷的目的是爲了保護系統。全自動,不需要干預。

​ 三種狀態之間的切換

  1. 關閉到打開。失敗降級的次數達到閾值。默認5秒失敗20次。
  2. 打開到半開。持續5秒鐘。半開:(允許一半的請求通過)
  3. 半開到關閉。通過的請求成功超過80%

九、Hystrix 熔斷-代碼演示

分析:

​ 熔斷是Hystrix 自動的機制,只要使用了Hystrix ,就可以進行系統的熔斷保護。

所以我們做這個實驗,只需要讓我們的代碼發生降級就可以。

需求: 讓我們的請求ID爲1的時候拋出異常,引發降級。

hystrix-provider的GoodsController中進行設置:

public Goods findOne(@PathVariable("id") int id){

//如果id == 1 ,則出現異常,id != 1 則正常訪問
if(id == 1){
//1.造個異常
int i = 3/0;
}

可以通過@HystrixCommand註解的commandProperties屬性進行配置:

@GetMapping("/findOne/{id}")
@HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
//設置Hystrix的超時時間,默認1s
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
//監控時間 默認5000 毫秒
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "5000"),
//失敗次數。默認20次
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "20"),
//失敗率 默認50%
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50")

})
public Goods findOne(@PathVariable("id") int id){

十、Hystrix -熔斷監控

分析:

Hystrix 熔斷監控
• Hystrix 提供了 Hystrix-dashboard 功能,用於實時監控微服務運行狀態。
• 但是Hystrix-dashboard只能監控一個微服務。
• Netflix 還提供了 Turbine ,進行聚合監控。

搭建Turbine 聚合監控的步驟:

SpringCloud-資料\day02\資料\1. turbine 搭建\Turbine搭建步驟.md

在這裏插入圖片描述

總結: 瞭解內容,面試能把Turbine 名字說出來就可以。

十一、Gateway 網關-概述

疑問: 什麼是網關?幹什麼用的?

分析:

​ 定義:

• 網關旨在爲微服務架構提供一種簡單而有效的統一的API路由管理方式。

• 在微服務架構中,不同的微服務可以有不同的網絡地址,各個微服務之間通過互相調用完成用戶請求,客戶端可能通過調用N個微服務的接口完成一個用戶請求。

• 存在的問題:
• 客戶端多次請求不同的微服務,增加客戶端的複雜性
• 認證複雜,每個服務都要進行認證
• http請求不同服務次數增加,性能不高

• 網關就是系統的入口,封裝了應用程序的內部結構,爲客戶端提供統一服務,一些與業務本身功能無關的公共邏輯可以在這裏實現,諸如認證、鑑權、監控、緩存、負載均衡、流量管控、路由轉發等

• 在目前的網關解決方案裏,有Nginx+ Lua、Netflix Zuul 、Spring Cloud Gateway等等

在這裏插入圖片描述

總結: 網關也是一個應用,有了網關之後,我們所有的請求都訪問網關應用,由網關幫我們去調用其他服務。

網關幹什麼用?主要功能有兩個:

  1. 路由

  2. 過濾

十二、Gateway 網關-快速入門

疑問:如何來使用Gateway 網關?
需求:使用Gateway 網關來路由轉發請求

操作步驟:

  1. 搭建網關模塊,導入資料中的初始化代碼

其實就是創建一個最基本的spring cloud模塊。

  1. 引入依賴:starter-gateway
<dependencies>
<!--引入gateway 網關-->

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

<!-- eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
  1. 編寫啓動類,無特殊操作
@SpringBootApplication
@EnableEurekaClient
public class ApiGatewayApp {

public static void main(String[] args) {
SpringApplication.run(ApiGatewayApp.class,args);
}

}

  1. 編寫配置文件
server:
port: 80

spring:
application:
name: api-gateway-server

cloud:
# 網關配置
gateway:
# 路由配置:轉發規則
routes: #集合。
# id: 唯一標識。默認是一個UUID
# uri: 轉發路徑
# predicates: 條件,用於請求網關路徑的匹配規則

- id: gateway-provider
uri: http://localhost:8001/
predicates:
- Path=/goods/**

- id: gateway-cum
uri: http://localhost:9000/
predicates:
- Path=/orders/**

  1. 啓動測試

訪問網關應用: http://localhost/goods/findOne/2

十三、Gateway 網關-靜態路由

疑問: 什麼是靜態路由?

就是轉發的地址是固定的。在開發中不便於維護,不使用。知道概念就可以。

分析:

配置:

server:
port: 80

spring:
application:
name: api-gateway-server

cloud:
# 網關配置
gateway:
# 路由配置:轉發規則
routes: #集合。
# id: 唯一標識。默認是一個UUID
# uri: 轉發路徑
# predicates: 條件,用於請求網關路徑的匹配規則
# filters:配置局部過濾器的

- id: gateway-provider
# 靜態路由
uri: http://localhost:8001/
predicates:
- Path=/goods/**

- id: gateway-consumer
uri: http://localhost:9000
predicates:
- Path=/order/**
# 微服務名稱配置

十四、Gateway 網關-動態路由

疑問:靜態路由的缺點是什麼?什麼是動態路由?有什麼用

分析:

靜態路由的缺點是什麼?

​ 靜態路由,在網關中uri的配置是寫死的,不便於維護。

什麼是動態路由?有什麼用?

​ 讓網關應用能夠從註冊中心Eureka中,動態的通過應用的名稱來獲取應用的地址

配置方式:

  1. 添加依賴(之前已經完成)
<!-- eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. 啓動類添加註解(之前已經完成)
@SpringBootApplication
@EnableEurekaClient
public class ApiGatewayApp {
  1. 配置動態路由
- id: gateway-consumer
# uri: http://localhost:9000
uri: lb://GATEWAY-CONSUMER
predicates:
- Path=/order/**


eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka

總結: 爲網關添加Eureka客戶端依賴,能夠從註冊中心發現服務。在配置路由的uri時,通過lb://服務名稱 來獲取轉發服務器的地址信息。

十五、Gateway 網關 – 微服務名稱配置

疑問: 網關路由轉發的應用很多,名稱容易衝突,如何進行方便的區分?

分析:

​ 將Eureka註冊中心裏應用的名稱作爲uri中的前綴來區分不同的應用。

配置:

spring:
application:
name: api-gateway-server

cloud:
# 網關配置
gateway:
discovery:
locator:
enabled: true # 設置爲true 請求路徑前可以添加微服務名稱
lower-case-service-id: true # 允許爲小寫

測試:

​ 訪問網關應用: http://localhost/goods/findOne/2

​ 也可以: http://localhost/gateway-provider/goods/findOne/2

十六、Gateway 網關 – 過濾器-概述

過濾器

• Gateway 支持過濾器功能,對請求或響應進行攔截,完成一些通用操作。

• Gateway 提供兩種過濾器方式:“pre”和“post”
• pre 過濾器,在轉發之前執行,可以做參數校驗、權限校驗、流量監控、日誌輸出、協議轉換等。
• post 過濾器,在響應之前執行,可以做響應內容、響應頭的修改,日誌的輸出,流量監控等。

• Gateway 還提供了兩種類型過濾器
• GatewayFilter:局部過濾器,針對單個路由
• GlobalFilter :全局過濾器,針對所有路由

在這裏插入圖片描述

十七、Gateway 網關 – 局部過濾器

局部過濾器

• GatewayFilter 局部過濾器,是針對單個路由的過濾器。

• 在Spring Cloud Gateway 組件中提供了大量內置的局部過濾器,對請求和響應做過濾操作。

• 遵循約定大於配置的思想,只需要在配置文件配置局部過濾器名稱,併爲其指定對應的值,就可以讓其生效。

參考資料: SpringCloud-資料\day02\資料\2. gateway內置過濾器工廠

配置:

# filters:配置局部過濾器的

- id: gateway-provider
# 靜態路由
# uri: http://localhost:8001/
# 動態路由
uri: lb://GATEWAY-PROVIDER
predicates:
- Path=/goods/**
filters:
- AddRequestParameter=username,zhangsan

總結:

​ 根據文檔中的過濾器的作用和名稱進行配置,過濾的參數和值之間使用,逗號分隔。

十八、Gateway 網關 – 全局過濾器

全局過濾器

• GlobalFilter 全局過濾器,不需要在配置文件中配置,系統初始化時加載,並作用在每個路由上。

• Spring Cloud Gateway 核心的功能也是通過內置的全局過濾器來完成。

• 自定義全局過濾器步驟:

  1. 定義類實現 GlobalFilter 和 Ordered接口
  2. 複寫方法
  3. 完成邏輯處理
@Component
public class MyFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

System.out.println("自定義全局過濾器執行了~~~");
//獲取web應用的對象
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();

return chain.filter(exchange);//放行
}

/**
* 過濾器排序
* @return 數值越小 越先執行
*/
@Override
public int getOrder() {
return 0;
}
}

總結:

自定義全局過濾器無需配置,只需要實現接口中的方法就可以。

自定義的過濾器需要添加@Component交給spring容器管理。

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