SpringCloud Hystrix要點及Geteway入門
技術標籤:HystrixGatewayspringcloudspring cloud
Hystrix與Geteway簡介
前言
Hystrix(英文含義:豪豬)由Netflix公司開發的,後來由Spring Cloud Hystrix基於這款框架實現了斷路器、執行緒隔離等一系列服務保護功能,該框架的目標在於通過控制訪問遠端系統、服務和第三方庫的節點,從而延遲和故障提供更強大的容錯能力。
Hystrix防止某個單元出現故障.從而引起依賴關係引發故障的蔓延,最終導致整個系統的癱瘓。
Spring Cloud Gateway 裡明確的區分了 Router 和 Filter,並且一個很大的特點是內建了非常多的開箱即用功能,並且都可以通過 SpringBoot 配置或者手工編碼鏈式呼叫來使用。
提示:以下是本篇文章正文內容,下面案例可供參考
一、服務降級
服務降級:伺服器忙碌或者網路擁堵時,不讓客戶端等待並立刻返回一個友好提示,fallback(備選方案)。
1.區域性服務降級
1.1 在服務提供方設定
在服務提供方進行區域性服務設定,首先設定自身呼叫超時的峰值,峰值內正常執行,超出峰值需要有兜底的方法處理,作服務降級fallback呼叫。(1)引入Hystrix依賴
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix< /artifactId>
</dependency>
(2)在service中對超時方法進行設定,訪問超時呼叫兜底方法
( 降級方法(邏輯)編寫的原則是方法的形參和返回值必須要和被降級的方法保持一致。)
/**
超時訪問的方法,新增@HystrixCommand註解
*/
@HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
//設定峰值,超過 3 秒,就會呼叫兜底方法,這個時間也可以由feign控制
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public String paymentInfo_Timeout(Integer id){
//設定超時呼叫時間
int interTime = 5;
//int i = 10/0;
try{
TimeUnit.SECONDS.sleep(interTime);
}catch (Exception e){
e.printStackTrace();
}
return "執行緒池:" + Thread.currentThread().getName() + " ,paymentInfo_Timeout,id:" + id + "耗時" + interTime + "秒鐘";
}
// 定義服務出現異常之後,兜底的方法
//降級方法(邏輯)編寫的原則是方法的形參和返回值必須要和被降級的方法保持一致。
public String timeoutHandler(Integer id){
return "服務異常,請重試......";
}
}
(3)在啟動類上加上@EnableCircuitBreaker 作用:開啟服務熔斷
(4)執行測試結果
(5)同樣在service的方法中設定一個異常(替換上一步的超時設定),用於模擬測試
public String paymentInfo_Timeout(Integer id){
//int interTime = 5;
//定義一個異常,用於測試
int i = 10/0;
}
(6)測試結果。
在發生服務不可用(呼叫超時或方法內部異常)時,都會進行降級呼叫來處理問題。
1.2 在消費方設定
(1)首先取消上述對於服務提供方的降級呼叫設定
(2)引入Hystrix依賴
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
(3)在啟動類上加上@EnableCircuitBreaker 作用:開啟服務熔斷
(4) 在controller層設定服務降級的邏輯編寫,訪問超時呼叫兜底方法
@HystrixCommand(fallbackMethod = "handeException", commandProperties = {
//設定峰值,超過 1.5 秒,就會呼叫兜底方法
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value = "1500")
})
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String paymentInfo_Timeout(@PathVariable("id")Integer id){
log.info("paymentInfo_timeout");
return orderService.paymentInfo_Timeout(id);
}
//定義兜底方法
public String handeException(Integer id){
return "服務呼叫異常,請稍後再試.....";
}
(5)執行測試結果
(6)在服務提供方的service的方法中設定一個異常,返回一個值,用於測試結果
public String paymentInfo_Timeout(Integer id){
//設定超時呼叫時間
//int interTime = 5;
//定義異常
int i = 10/0;
/*try{
TimeUnit.SECONDS.sleep(interTime);
}catch (Exception e){
e.printStackTrace();
}
return "執行緒池:" + Thread.currentThread().getName() + " ,paymentInfo_Timeout,id:" + id + "耗時" + interTime + "秒鐘";*/
return "發生內部異常";
}
2.全域性服務降級
(1)全域性服務降級
1.在消費方的啟動類上面要加上一個@EnableCircuitBreaker
2.在消費方的controller裡面,定義一個全域性降級的方法。
//全域性服務降級處理在服務消費方上面實現
// 全域性降級處理方法
public String globalHandler(){
return "這是全域性處理降級邏輯的方法.......";
}
3.在controller上面 新增一個註解@DefaultProperties(defaultFallback = “handleAll”)
4.在指定的被降級的方法上新增一個@HystrixCommand
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "globalHandler") //開啟全域性降級處理
public class OrderController {
@Autowired
OrderService orderService;
@HystrixCommand //不寫fallbackMethod屬性,預設是全域性
@GetMapping("/consumer/payment/hystrix/timeout/{id}") //服務超時
public String paymentInfo_Timeout(@PathVariable("id")Integer id){
log.info("paymentInfo_timeout");
return orderService.paymentInfo_Timeout(id);
}
}
注意:降級邏輯的優先順序 區域性的降級邏輯>全域性的降級邏輯
(2)服務降級方法抽取
- 在消費方的啟動類上面要加上一個@EnableCircuitBreaker
- 在配置檔案裡面,開啟feign對Hystrix的支援
feign:
hystrix:
enabled: true
- 定義一個類,實現Feign客戶端。重寫裡面的方法(編寫降級處理方法)
@Component
public class FallBackService implements OrderService {
@Override
public String paymentInfo_OK(Integer id) {
return "進行paymentInfo_OK方法降級處理......";
}
@Override
public String paymentInfo_Timeout(Integer id) {
return "進行paymentInfo_Timeout方法降級處理";
}
}
- 使用@FeignClient註解,將這個類繫結到Feign客戶端上去
@Component
@FeignClient(value = "cloud-payment-service",fallback = FallBackService.class)
public interface OrderService {
@GetMapping("/payment/hystrix/{id}")
public String paymentInfo_OK(@PathVariable("id")Integer id);
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_Timeout(@PathVariable("id")Integer id);
}
- 進行測試,檢視降級處理結果
二、服務熔斷
程式碼如下(示例):
1.服務熔斷的概述
當用戶訪問某個服務,達到了最大的訪問量之後,直接拒絕使用者訪問。
在SpringCloud框架中,熔斷機制通過Hystrix實現。Hystrix會監控微服務間呼叫的狀況。當失敗的呼叫到一定閾值時,預設是5秒內20次呼叫失敗,就會啟動熔斷機制。熔斷機制的註解是@HystrixCommand。
2.熔斷有哪幾種狀態
熔斷狀態機3個狀態:
(1)Closed:關閉狀態,所有請求都正常訪問。
(2)Open:開啟狀態,所有請求都會被降級。Hystix會對請求情況計數,當一定時間內失敗請求百分比達到閾值,則觸發熔斷,斷路器會完全開啟。預設失敗比例的閾值是50%,請求次數最少不低於20次。
(3)Half Open:半開狀態,open狀態不是永久的,開啟後會進入休眠時間(預設是5S)。隨後斷路器會自動進入半開狀態。此時會釋放部分請求通過,若這些請求都是健康的,則會完全關閉斷路器,否則繼續保持開啟,再次進行休眠計時。
3.斷路器的工作原理
統計使用者在指定的時間範圍(預設10s)之內的請求總數達到指定的數量之後,如果不健康的請求(超時、異常)佔總請求數量的百分比(50%)達到了指定的閾值之後,就會觸發熔斷。觸發熔斷後,斷路器就會開啟(open),此時所有請求都不能通過。在5s之後,斷路器會恢復到半開狀態(half open),會允許少量請求通過,如果這些請求都是健康的,那麼斷路器會回到關閉狀態(close).如果這些請求還是失敗的請求,斷路器還是恢復到開啟的狀態(open)。
4.如何開啟熔斷?
1.在指定請求方法上,開啟熔斷
@HystrixCommand(fallbackMethod = "handleCircuitBreaker",commandProperties = {
@HystrixProperty(name="circuitBreaker.enabled", value="true"), // 是否開啟斷路器
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="10"), //請求次數
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds", value="10000"), // 時間視窗期
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value="60"), // 失敗率達到多少後跳閘
//整體意思:10秒內 10次請求,有6次失敗,就跳閘
})
public String enableCircuitBreaker(Integer id){
if(id < 0){
throw new RuntimeException();
}
String uuid = UUID.randomUUID().toString();
return "返回的uuid是:" + uuid;
}
2.使用XML的方式進行熔斷的配置
#全域性服務降級,feign+hystrix整合,即 service 實現類的方式做全域性配置?
hystrix:
command:
default:
circuitBreaker:
enabled: true
requestVolumeThreshold: 10
sleepWindowInMilliseconds: 10000
errorThresholdPercentage: 60
三、Hystrix DashBoard
除了隔離依賴服務的呼叫以外,Hystrix還提供了準時呼叫監控(Hystrix DashBoard),Hystrix 會持續地記錄所有通過Hystrix發起的請求的執行資訊,並以統計報表和圖形的形式展示給使用者,包括每秒執行多少請求多少成功,多少失敗等。
Netflix通過hystrix-metrics-event-stream專案實現了對以上指標的指控。SpringCloud也提供了Hystrix Dashboard的整合,對監控內容轉化為視覺化介面。
1.建立儀表盤監控模組
(1)在專案中建立儀表盤監控模組
(2)編寫啟動類,使用@EnableHystrixDashboard註解開啟儀表盤監控
@SpringBootApplication
@EnableHystrixDashboard //開啟儀表盤監控
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class,args);
}
}
(3)編寫配置檔案
server:
port: 9001 #埠號,自定義
(4)引入依賴
注意:所有被監控的服務都需要新增依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
(5)啟動測試:訪問 http://localhost:9001/hystrix
2. 監控實戰
(1)在http://localhost:9001/hystrix頁面中訪問http://localhost:8001/hystrix.stream
(2)訪問:http://localhost:8001/payment/circuit/1 ,請求資料
檢視請求量等資訊。
類如下圖所示:
四、Geteway閘道器
1.Geteway閘道器簡介
Spring Cloud Gateway是Spring官方基於Spring 5.0,Spring Boot 2.0和Project Reactor等技術開發的閘道器,Spring Cloud Gateway旨在為微服務架構提供一種簡單而有效的統一的API路由管理方式。Spring Cloud Gateway作為Spring Cloud生態系中的閘道器,目標是替代ZUUL,其不僅提供統一的路由方式,並且基於Filter鏈的方式提供了閘道器基本的功能,例如:安全,監控/埋點,和限流等。
2.Gateway 的核心概念
三大核心概念:
(1)路由(Route):路由是閘道器的基本模組,由ID,目標URL,一系列的斷言和過濾器組成。斷言為真,則路由匹配。
(2)斷言(Predicate):輸入型別是一個ServerWebExchange。開發人員可以使用它匹配HTTP請求中的任何內容,例如headers或引數。如果請求和斷言相匹配,則進行路由。
(3)過濾(Filter):Gateway中的Filter分為兩種型別,分別是Gateway Filter和Global Filter。過濾器可以在請求被路由前或之後
對請求進行修改。
3.如何簡單使用gateway(入門案例)
(1)建立gateway模組
(2)引入POM依賴
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--eureka-client gateWay作為閘道器,也要註冊進服務中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- gateway和web不能同時存在,即web相關jar包不能匯入 -->
(2)編寫application.yml配置檔案
server:
port: 9527
spring:
application:
name: cloud-gateway
## GateWay配置
cloud:
gateway:
discovery:
locator:
enabled: true # 開啟從註冊中心動態建立路由的功能,利用微服務名進行路由
routes:
- id: payment_routh # 路由ID , 沒有固定的規則但要求唯一,建議配合服務名
uri: lb://cloud-payment-service # 匹配後提供服務的路由地址,之前http://localhost:8001,換成
predicates:
- Path=/payment/** # 斷言,路徑相匹配的進行路由
- id: payment_routh2 # 路由ID , 沒有固定的規則但要求唯一,建議配合服務名
uri: lb://cloud-payment-service # 匹配後提供服務的路由地址,之前localhost:8001,cloud-payment-service
predicates:
- Path=/payment/lb/** # 斷言,路徑相匹配的進行路由,lb 屬於GateWay 的關鍵字,代表是動態uri,即代表使用的是服務註冊中心的微服務名,它預設開啟使用負載均衡機制
# 在這個時間之後失效
#- After=2021-01-18T21:08:21.474+08:00[GMT+08:00]
#- Before=2021-01-18T21:08:21.474+08:00[GMT+08:00]
#- Between=2021-01-18T21:08:21.474+08:00[GMT+08:00],2021-01-18T22:08:21.474+08:00[GMT+08:00]
# 註冊進 eureka Server
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
register-with-eureka: true
fetch-registry: true
(3)建立啟動類
@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GatewayMain9527.class,args);
}
}
(4)測試結果
可使用閘道器埠呼叫業務邏輯,隱藏了業務微服務埠,使用閘道器服務對微服務進行保護。