Spring Cloud Feign 中使用Hystrix進行請求降級和快速失敗
前言
微服務中經常會用到熔斷器來增強服務依賴的穩定性,他可以在網路連線緩慢,資源繁忙,暫時不可用,服務離線等情況中進行服務的快速失敗,並可自我恢復,以避免請求執行緒的堆積造成大量資源的浪費。
相信讀者看這篇文章的目的都是解決實際問題,並不是來看我分析原始碼的,如果對原始碼感興趣的我推薦《重新定義》,所以我們直接上乾貨,下面我們就簡單的利用Feign中整合的Hystrix進行快速失敗和請求降級處理。
正文
首先準備一個父專案,裡面只有各個服務所需的依賴包,下面就是父專案的pom,可以看到我這次演練的專案有三個,分別是eureka-server,consumer-service,provider-service
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>cn.springcloud.book</groupId> <artifactId>ch6-2</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>ch6-2-eureka-server</module> <module>ch6-2-consumer-service</module> <module>ch6-2-provider-service</module> </modules> <!-- 管理依賴 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <!--注意: 這裡必須要新增, 否者各種依賴有問題 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
下面建立eureka-server服務
下面依次是pom,yml,和啟動類的程式碼,這裡不做解釋了,前幾個部落格已經介紹過類似的內容。
<parent> <groupId>cn.springcloud.book</groupId> <artifactId>ch6-2</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>ch6-2-eureka-server</artifactId> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://localhost:8761/eureka/
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
接下來建立一個被feign呼叫的服務:provider-service。
這裡很簡單,就是定一個請求地址,用來對映到feign介面上的URl。
下面程式碼依次是provider-service中的controller、啟動類、pom、yml
這裡其實重點就是利用了spring-cloud-starter-netflix-hystrix,別的都沒什麼可解釋的。
@RestController
public class TestController {
@RequestMapping(value = "/getUser",method = RequestMethod.GET)
public String getUser(@RequestParam("username") String username){
return "This is real user";
}
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
<parent>
<groupId>cn.springcloud.book</groupId>
<artifactId>ch6-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ch6-2-provider-service</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.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-netflix-hystrix</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
最後建立一個consumer-service工程,這裡的程式碼相對上兩個服務要多一些,不過我會按照一定的順序給大家展示,
首先是controller、Feign介面,Feign的快速返回/降級方法、pom、yml,一共五塊程式碼
@RestController
public class TestController {
@Autowired
private IUserService userService;
@RequestMapping(value = "/getUser",method = RequestMethod.GET)
public String getUser(@RequestParam("username") String username) throws Exception{
return userService.getUser(username);
}
@FeignClient(name = "sc-provider-service", fallback = UserServiceFallback.class)
public interface IUserService {
@RequestMapping(value = "/getUser",method = RequestMethod.GET)
String getUser(@RequestParam("username") String username);
}
@Component
public class UserServiceFallback implements IUserService{
/**
* 出錯則呼叫該方法返回友好錯誤
* @param username
* @return
*/
public String getUser(String username){
return "The user does not exist in this system, please confirm username";
}
}
<parent>
<groupId>cn.springcloud.book</groupId>
<artifactId>ch6-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ch6-2-consumer-service</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.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-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
server:
port: 8888
spring:
application:
name: sc-consumer-service
eureka:
client:
serviceUrl:
defaultZone: http://${eureka.host:127.0.0.1}:${eureka.port:8761}/eureka/
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
好了,五塊程式碼貼上完畢,下面是對上面程式碼的解釋,
首先controller是我們對外暴露的請求入口,呼叫了當前服務的Feign介面,重點是這句話@FeignClient(name = "sc-provider-service", fallback = UserServiceFallback.class),name引數代表請求對映的服務spring. application.name,fallback引數指定的是一個類,這個類必須要實現當前的Feign接口才可以,用於feign呼叫sc-provider-service服務時失敗的快速返回類。然後就是UserServiceFallback類一定注入spring容器。
同樣,這個工程也需要spring-cloud-starter-netflix-hystrix 依賴,另外這裡我用了openfeign你可以理解為feign的升級版。
還有一點需要注意的是高版本中feign的hystrix是預設關閉的,所有我們要手動開啟
三個服務分別啟動,首先eureka-service先啟動。
我們可以看到消費者工程和生產者工程分別註冊上了eureka,我們訪問http://localhost:8888/getUser?username=1
可以看到通過feign訪問到了provider-service工程的controller方法了,
下面我們把provider-service工程手動關閉,同樣訪問http://localhost:8888/getUser?username=1,當然是訪問不到的了,但是返回
我們知道這句話是我fallback引數指定類的方法返回的,
這樣一個簡單的利用feign 整合的熔斷器實現快速返回的例子。
注:對本文有異議或不明白的地方微信探討,wx:15524579896