【Spring Cloud總結】20.Feign對Hystrix的支持

接上篇《19.Hystrix Health Indicator及Metrics Stream支持》  Spring Cloud版本爲Finchley.SR2版

上一篇我們簡單介紹了Hystrix的健康指數監控以及API監控,分別用來查看Hystrix斷路器的狀態,以及應用API服務的詳細監控情況。本篇我們來講解如何在Feign組件中使用Hystrix。
本部分官方文檔:https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html

一、回顧Feign組件

之前我們講過,Feign組件是用來實現聲明式服務調用功能的,換句話說就是Feign可以優雅的調用REST風格的服務。我們回顧一下之前的Feign組件的使用過程:
首先我們在Movie工程的Controller中通過userFeignClient接口對象,去調用findById方法,而此方法就是通過Feign組件進行遠程REST服務的調用:

@Autowired
private UserFeignClient userFeignClient;

@GetMapping("/movie/{id}")
@HystrixCommand(fallbackMethod = "findUserByIdFallback",
    commandProperties = {@HystrixProperty(name="execution.isolation.strategy",value="SEMAPHORE")})
public User findUserById(@PathVariable Long id){
    return userFeignClient.findById(id);
}

public User findUserByIdFallback(Long id){
    User user = new User();
    user.setId(0L);
    return user;
}

這裏UserFeignClient接口就封裝了Feign組件的實現:

package com.microserver.cloud;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import com.microserver.cloud.entity.User;
import com.microserver.config.TestFeignConfiguration;
import feign.Param;
import feign.RequestLine;

@FeignClient(name="microserver-provider-user",configuration = TestFeignConfiguration.class )
public interface UserFeignClient {
    
    @RequestLine("GET /findById/{id}")
    public User findById(@Param("id") Long id);
    
    @RequestLine("POST /postUser")
    public String postUser(@RequestBody User user);
}

這裏我們在接口頭部僅需要定義@FeignClient,以及要調用的遠程服務的實例名,配置類信息即可。在每個方法定義上,添加@RequestLine註解,來定義該服務的請求類型以及實際請求URL。
這樣實現了一個Feign組件調用遠程服務的效果。

在上面的例子中,我們加入Hystrix實現斷路器的方式是,在調用userFeignClient之前的Controller方法中添加@HystrixCommand以及降級方法fallbackMethod,其實如果我們要單純的處理findById方法的斷路降級問題,直接在UserFeignClient接口中,即在Feign組件中實現Hystrix斷路器即可。

下面我們在Feign中實現Hystrix斷路器。

二、在Feign組件中使用Hystrix

Spring Cloud默認已爲Feign整合了Hystrix,只要Hystrix在項目的classpath中,Feign默認就會用斷路器包裹所有方法。
如果要使用Feign的Hystrix支持,可以設置feign.hystrix.enabled=true,要禁用,設置爲false即可。

我們可以通過以下方式來實現Feign的Hystrix支持:
1、@FeignClient註解配置fallback參數,實現FeignClient接口
我們可以在之前的FeignClient接口上的@FeignClient添加fallback參數,該參數是一個FeignClient接口的實現類,在實現類中實現FeignClient接口中的各個方法即可。
當FeignClient接口中的服務調用失敗,觸發斷路器打開,請求轉移的降級服務,就是FeignClient接口實現類中的同名方法。

我們來實現這個效果。首先在Movie工程的application.yml配置文件中開啓Feign的Hystrix支持:

feign:
  hystrix:
    enabled: true

然後修改一下之前的Controller類以及UserFeignClient接口,使其實現Feign對Hystrix的支持:

@Autowired
private UserFeignClient userFeignClient;

@GetMapping("/movie/{id}")
public User findUserById(@PathVariable Long id){
    return userFeignClient.findById(id);
}

UserFeignClient接口:

package com.microserver.cloud;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import com.microserver.cloud.entity.User;
import com.microserver.config.TestFeignConfiguration;
import feign.Param;
import feign.RequestLine;

@FeignClient(name="microserver-provider-user",configuration = TestFeignConfiguration.class,
    fallback = FeignClientFallback.class )
public interface UserFeignClient {

    @RequestLine("GET /findById/{id}")
    public User findById(@Param("id") Long id);
    
    @RequestLine("POST /postUser")
    public String postUser(@RequestBody User user);
}

@Component
class FeignClientFallback implements UserFeignClient{

    @Override
    public User findById(Long id) {
        User user = new User();
        user.setId(0L);
        user.setName("FeignClient 降級服務");
        return user;
    }

    @Override
    public String postUser(User user) {
        return null;
    }
    
}

可以看到,我們在fallback中定義了降級實現類FeignClientFallback,然後編寫了該內部類,實現了UserFeignClient接口,然後實現接口中的每一個方法,定義降級服務的內容,其中findById的內容,和之前在Controller中的“findUserByIdFallback”方法內容相同,這裏我們將默認的user對象的name定義爲“FeignClient 降級服務”,爲了測試證明該服務是Feign組件觸發的。

這裏我們啓動之前的服務提供者user工程、服務消費者movie工程以及eureka Server註冊中心,訪問“movie/1”服務是好的:

然後關掉服務提供者user工程,再次訪問“movie/1”服務,可以看到此時進入了降級服務中:

打印的name內容就是之前降級服務中定義的內容,證明我們通過Feign調用Hystrix成功!


2、@FeignClient註解配置fallbackFactory參數,實現FallbackFactory接口
fallbackFactory參數指定一個fallback工廠,與指定fallback不同, 此工廠可以用來獲取到觸發斷路器的異常信息,fallback工廠類需要實現FallbackFactory類。我們修改一下之前的UserFeignClient,來實現FallbackFactory的斷路效果:

package com.microserver.cloud;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import com.microserver.cloud.entity.User;
import com.microserver.config.TestFeignConfiguration;
import feign.Param;
import feign.RequestLine;
import feign.hystrix.FallbackFactory;

@FeignClient(name="microserver-provider-user",configuration = TestFeignConfiguration.class,/*fallback = FeignClientFallback.class*/
    fallbackFactory=FeignClientFallbackFactory.class)
public interface UserFeignClient {
    
    @RequestLine("GET /findById/{id}")
    public User findById(@Param("id") Long id);
    
    @RequestLine("POST /postUser")
    public String postUser(@RequestBody User user);
}

@Component
class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient>{

    //日誌對象
    private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class);

    @Override
    public UserFeignClient create(Throwable cause) {
        return new UserFeignClient() {
            
            @Override
            public User findById(Long id) {
                // 日誌最好放在各個fallback方法中,而不要直接放在create方法中。
                // 否則在引用啓動時,就會打印該日誌
                FeignClientFallbackFactory.LOGGER.info("fallback; reason was: ", cause);
                
                User user = new User();
                user.setId(0L);
                user.setName("FeignClient 降級服務");
                return user;
            }

            @Override
            public String postUser(User user) {
                return null;
            }
        };
    }
}

可以看到,我們指定的fallbackFactory參數對應的內部類,實現了FallbackFactory<T>接口,泛型中的T即是我們的UserFeignClient接口。FallbackFactory<T>接口需要實現一個create方法,該方法引入了異常Throwable對象作爲參數,在Hystrix斷路器啓動後,觸發降級請求,此時create方法會返回一個定義了所有方法降級服務的UserFeignClient類,並且在Throwable對象中包裝了具體的異常信息,我們可以將異常信息打印到控制檯。

我們按照之前的方式,只啓動服務消費者movie工程和eureka Server註冊中心,不啓動服務提供者user工程,此時訪問“movie/1”服務:

然後我們在編譯器的控制檯可以看到:

說明請求不僅進入了降級服務,而且打印出了詳細的異常信息,這裏的異常主要是microserver-provider-user服務不可用,其實是我們的服務提供者沒有啓動造成的。

總的來說,fallback工廠類的優點是可以通過Throwable對象獲取到異常信息。

至此,Feign對支持Hystrix支持相關的知識就介紹到這裏了。


參考:《51CTO學院Spring Cloud高級視頻》

轉載請註明出處:https://blog.csdn.net/acmman/article/details/101864536

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章