openfeign + hystrix 實現遠端呼叫,配置熔斷、超時、多 name
阿新 • • 發佈:2020-12-24
1,前提條件
生產者和消費者兩個專案必須都註冊到同一個註冊中心
2,生產者
生產者無需特殊配置,只需要是一個正常的web專案並且提供可訪問的介面即可,介面示例如下
package com.hwq.data.base.client; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HomeClient { @GetMapping("/client/home/index") public String index() { return "Open Feign"; } }
3,消費者
1,pom.xml
<!-- 遠端呼叫 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-archaius</artifactId> </exclusion> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-archaius</artifactId> </exclusion> </exclusions> </dependency> <!-- Hystrix 熔斷器 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-archaius</artifactId> </exclusion> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-archaius</artifactId> </exclusion> </exclusions> </dependency>
2,配置開啟熔斷功能
feign:
hystrix:
# 開啟熔斷器
enabled: true
3,啟動類
package com.hwq.admin.back; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication // 啟動 SpringBoot 專案 @EnableDiscoveryClient // 啟動 服務發現客戶端 功能 @EnableFeignClients // 啟動 遠端呼叫 public class AdminBackApp { public static void main(String[] args) { SpringApplication.run(AdminBackApp.class); } }
4,FeignClient 介面
package com.hwq.admin.back.feign;
import com.hwq.admin.back.feign.impl.HomeFeignImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
// 宣告為 feign 遠端呼叫,name:生產者專案名,fallback:發生錯誤或超時時的熔斷類
@FeignClient(name = "sc-web-data-base", fallback = HomeFeignImpl.class)
public interface HomeFeign {
// 這裡的方法簽名要和生產者保持一致
@GetMapping("/client/home/index")
String index();
}
5,熔斷類
該類需要實現 FeignClient 介面,並且配置在 fallback 引數中
package com.hwq.admin.back.feign.impl;
import com.hwq.admin.back.feign.HomeFeign;
import org.springframework.stereotype.Component;
@Component
public class HomeFeignImpl implements HomeFeign {
@Override
public String index() {
return "觸發熔斷";
}
}
5,呼叫的控制層
package com.hwq.admin.back.controller;
import com.hwq.admin.back.feign.HomeFeign;
import com.hwq.admin.back.vo.ResultVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
// FeignClient 介面 可以直接注入使用
@Autowired
private HomeFeign homeFeign;
@GetMapping("/home/feign")
public ResultVO<String> fegin() {
String index = homeFeign.index();
return ResultVO.success("OK", index);
}
}
4,測試
啟動專案後,訪問:http://localhost:2011/home/feign
我們關閉生產者,再次訪問觸發熔斷
5,超時配置
配置超時可有效防止因為程式效能問題導致的長時間無響應,並且造成執行緒池忙碌堵塞
feign:
hystrix:
# 開啟熔斷器,如果要採用
enabled: true
ribbon:
# 遠端請求呼叫的超時時間 5 秒
ConnectTimeout: 5000
# 連線後的等待處理的超時時間 30 分鐘
ReadTimeout: 1800000
# 最大重試次數,當註冊中心中可以找到服務,但是服務連不上時將會重試
MaxAutoRetries: 0
# 切換例項的重試次數
MaxAutoRetriesNextServer: 0
hystrix:
command:
default:
execution:
isolation:
thread:
# 觸發熔斷的超時時間
timeoutInMilliseconds: 1801000
- openfeign 是依賴於 ribbon 的,所以超時配置配置 ribbon
- ribbon 配置下的項必須使用駝峰,使用中橫線會失效,雖然這看起來怪怪的
- 重生次數建議設定為 0,否則會出現冪等性的問題,當然查詢的無所謂
- 熔斷觸發的超時時間應該大於 (ConnectTimeout + ReadTimeout)* (總重試次數 + 1)
- 總重試次數 = MaxAutoRetries * MaxAutoRetriesNextServer + 1
6,相同 name 配置
1,場景
我們在開發中常常會配置多個 feignclient 指向同一個服務,這必然導致這些介面的 name 屬性是形同的,但是啟動之後卻會出現如下異常:
2,原因
如果我們要建立多個具有相同名稱或URL的偽客戶端,以便它們指向同一臺伺服器,但每個客戶端具有不同的自定義配置,則必須使用的contextId
屬性
3,解決辦法
package com.hwq.admin.back.feign;
import com.hwq.admin.back.feign.impl.HomeFeignImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
// 宣告為 feign 遠端呼叫,name:生產者專案名,contextId: 唯一標識,fallback:發生錯誤或超時時的熔斷類
@FeignClient(name = "sc-web-data-base", contextId = "home", fallback = HomeFeignImpl.class)
public interface HomeFeign {
// 這裡的簽名要和生產者保持一致
@GetMapping("/client/home/index")
String index();
}