Spring Cloud Feign 是聲明式的 Web 服務客戶端,我們只需創建一個接口並用註解的方式來配置它,就可以實現對某個服務接口的調用,簡化了直接使用RestTemplate 來調用服務接口的開發量。Feign 具備可插拔的註解支持,同時支持Feign註解、JAX-RS 註解及 SpringMvc 註解。Feign 整合了 Ribbon 和 Hystrix,擁有負載均衡和服務容錯功能。
聲明式的 Web 服務客戶端定義的方式:通過編寫簡單的接口和註解,就可以定義好 HTTP 請求的參數、格式、地址等信息。Feign 會完全代理 HTTP 的請求,在使用過程中我們只需要依賴注入 Bean,然後調用對應的方法傳遞參數即可。
一、準備工作
1.1、創建啓動一個註冊中心,二個服務提供者
請參考:SpringCloud Eureka 服務註冊中心組建1:搭建註冊中心
- piao-server:服務註冊中心,端口2000。
- piao-client:客戶服務端提供者,端口2010。
- piao-client2:客戶服務端提供者,端口2011。
如果不想創建多個項目,可以請考這篇文章:IDEA 啓動多個SpringBoot項目不同端口
啓動成功如下:
二、創建服務消費者 Feign
2.1、創建 piao-feign 項目。
我們這裏使用IDEA創建,文件-》新建-》項目-》下一步到如下的頁面:
我們選擇以上兩個依賴包。然後在點下一步,直到完成。
2.2、修改依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.piao</groupId>
<artifactId>piao-feign</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>piao-feign</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.3、添加配置
編輯項目的 application.properites 文件,添加如下相關配置:
#服務註冊中心端口號
server.port=2007
#指定服務名稱
spring.application.name=piao-feign
#指定服務註冊中心的地址
eureka.client.serviceUrl.defaultZone=http://localhost:2000/eureka/
在啓動類上添加 @EnableFeignClients 註解開啓 Spring Cloud Feign 的支持功能。
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class PiaoFeginApplication {
public static void main(String[] args) {
SpringApplication.run(PiaoFeginApplication.class, args);
}
}
2.4、編寫 Service, 使用 Feign 客戶端的調用。
@FeignClient("piao-client")
public interface ConsumerService {
@RequestMapping("/client")
String client();
@RequestMapping("/param")
String param(@RequestParam String param);
}
這裏的服務名不區分大小寫,所以使用 hello-service 和 HELLO-SERVICE 都是可以的。
2.5、編寫Controller
@RestController
public class ConsumerController {
@Autowired
private ConsumerService consumerService;
@GetMapping("/consumer")
public String consumer() {
return consumerService.client();
}
@GetMapping("/param")
public String param(@RequestParam String param) {
return consumerService.param(param);
}
}
2.6、啓動項目
我們訪問註冊中心地址:http://127.0.0.1:2000/
請求服務消費者地址:http://127.0.0.1:2007/consumer
請求服務消費者地址:http://127.0.0.1:2007/param?param=piao
第一次訪問:
第二次訪問:
可以看到我們實現負載均衡,這裏就是 Fegin 整合了 Ribbon 功能。
三、Feign 重試機制
在 Spring Cloud Feign 中默認實現了請求的重試機制。
Ribbon 的超時與 Hystrix 的超時是兩個概念。爲了讓上述實現有效,我們需要讓 Hystrix 的超時時間大於 Ribbon 的超時時間,否則 Hystrix 命令超時後,該命令直接熔斷,重試機制就沒有任何意義了。
全局配置:
#斷路器的超時時長需要大於Ribbon的超時時間,不然不會觸發重試
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
#請求連接超時時間(毫秒)
ribbon.ConnectTimeout=1000
#請求處理的超時時間(毫秒)
ribbon.ReadTimeout=3000
#對所有請求都進行重試(是否所有操作都重試,若false則僅get請求重試)
ribbon.OkToRetryOnAllOperations=true
#切換實例的重試次數
ribbon.MaxAutoRetriesNextServer=2
#對當前實例的重試次數
ribbon.MaxAutoRetries=1
指定服務配置:
#斷路器的超時時長需要大於Ribbon的超時時間,不然不會觸發重試
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
#請求連接超時時間(毫秒)
piao-client.ribbon.ConnectTimeout=1000
#請求處理的超時時間(毫秒)
piao-client.ribbon.ReadTimeout=3000
#對所有請求都進行重試(是否所有操作都重試,若false則僅get請求重試)
piao-client.ribbon.OkToRetryOnAllOperations=true
#切換實例的重試次數
piao-client.ribbon.MaxAutoRetriesNextServer=2
#對當前實例的重試次數
piao-client.ribbon.MaxAutoRetries=1
當訪問到故障請求的時候,它會再嘗試訪問一次當前實例(次數由 MaxAutoRetries 配置),如果不行,就換一個實例進行訪問,如果還不行,再換一次實例訪問(更換次數由 MaxAutoRetriesNextServer 配置),如果依然不行,返回失敗信息。
四、配置負載均衡策略
全局配置:
#修改負載均衡算法
ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
指定服務配置:
#修改負載均衡算法
piao-client.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
Ribbon的負載均衡策略:
- com.netflix.loadbalancer.RandomRule:從提供服務的實例中以隨機的方式;
- com.netflix.loadbalancer.RoundRobinRule:以線性輪詢的方式,就是維護一個計數器,從提供服務的實例中按順序選取,第一次選第一個,第二次選第二個,以此類推,到最後一個以後再從頭來過;
- com.netflix.loadbalancer.RetryRule:在RoundRobinRule的基礎上添加重試機制,即在指定的重試時間內,反覆使用線性輪詢策略來選擇可用實例;
- com.netflix.loadbalancer.WeightedResponseTimeRule:對RoundRobinRule的擴展,響應速度越快的實例選擇權重越大,越容易被選擇;
- com.netflix.loadbalancer.BestAvailableRule:選擇併發較小的實例;
- com.netflix.loadbalancer.AvailabilityFilteringRule:先過濾掉故障實例,再選擇併發較小的實例;
- com.netflix.loadbalancer.ZoneAwareLoadBalancer:採用雙重過濾,同時過濾不是同一區域的實例和故障實例,選擇併發較小的實例。