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();
}