新 Spring Cloud(四) 之 Fegin遠程調用

零、前言

0. 之前寫過兩篇Spring Cloud,但是感覺不夠具體,所以重新寫了一份。

新 Spring Cloud (一) 之 Eureka 服務註冊中心
新 SpringCloud (二) 之 Ribbon 負載均衡
新 Spring Cloud (三) 之 Hystrix熔斷保護
新 Spring Cloud (四) 之 Fegin遠程調用
新 Spring Cloud (五) 之 Zuul 網關

一、Fegin 簡介

上回書說道,我們在項目中繼承了Ribbon 實現了負載均衡,同時通過Hystrix 實現了熔斷保護。看似完美,實則美中不足,在我們進行請求的時候,我們會寫大量關於請求鏈接的地址。
如下 : 如果我們調用這個driver/takeOrder 100次,則我們需要重複寫100次,如果我們需要調用其他的接口,則也要重複書寫 restTemplate.postForObject("http://eureka-server-provider/xxxxx",multiValueMap,XXX.class); 這種類似的代碼,麻煩且不說,而且易錯。

String result = restTemplate.postForObject("http://eureka-server-provider/driver/takeOrder", multiValueMap, String.class);		// 麻煩易錯!!!!!

所以我們在這裏繼承Fegin,可以改變這個現狀。那麼什麼是Fegin呢?
Feign是Nettix開發的聲明式、模板化的HTTP客戶端,其靈感來自Retroft、JAXRS-2.0
以及WebSocket。Feign 可幫助我們更加便捷、優雅地調用HTTP API。在Spring Cloud中,使用Feign非常簡單一創建一 個接口, 並在接口上添加一些註解,代碼就完成了。Feign 支持多種註解,例如Feign自帶的註解或者JAX-RS註解等。Spring Cloud對Feign進行了增強,使Feign支持了Spring MVC註解,並整合了Ribbon和Eureka,從而讓Feign的使用更加方便。

簡而言之:
• Feign 採用的是基於接口的註解
• Feign 整合了ribbon
• Feign可以把Rest的請求進行隱藏,僞裝成類似SpringMVC的Controller一樣

二、項目搭建

1. 基礎使用

這裏的操作都是對服務消費者來說(EurekaServerConsumer)

  1. 首先我們需要引入對應依賴

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  2. 我們在啓動類上加上 @EnableFeignClients 註解用於開啓Fegin客戶端。因爲Fegin 內部自動集成了Ribbon負載均衡的RestTemplate,並且默認開啓了負載均衡,所以我們不需要再注入RestTemplate。也不需要使用 @LoadBalanced 註解來開啓負載均衡。

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients     // 開啓 Fegin客戶端
    public class EurekaServerConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerConsumerApplication.class, args);
        }
    }
    
  3. 我們需要創建一個Fegin接口,來代理服務提供者的服務(EurekaServerProvider)。看似很高大上是吧,其實簡單來說 Fegin就是對我們Ribbon的處理做了一個封裝,讓客戶端實現了RPC調用。類似Dubbo中暴露遠程服務的方式,區別在於Dubbo是基於私有二進制協議,而Feign本質上還是個HTTP客戶端。

    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    /**
     * @Data: 2019/10/25
     * @Des:
     */
    @FeignClient(value = "eureka-server-provider") // 標註該類是一個feign接口,其服務名是 eurake-server-provider
    @RequestMapping("driver")
    public interface DriverClient {
        /**
         *  司機接單服務
         * @param msg
         * @return
         */
        @RequestMapping("takeOrder")
        String takeOrder(@RequestParam("msg") String msg);
    }
    
  • 首先這是一個接口,Feign會通過動態代理,幫我們生成實現類。這點跟mybatis的mapper很像
  • @FeignClient,聲明這是一個Feign客戶端,類似@Mapper註解。同時通過value屬性指定服務名稱
  • 接口中的定義方法,完全採用SpringMVC的註解,Feign會根據註解幫我們生成URL,並訪問獲取結果
  1. 改造原來接口的調用邏輯如下:

    
        @Autowired
        private DriverClient driverClient ;	// 注入Fegin接口
    
        @RequestMapping("callTaxi")
        public String callTaxi(String msg) {
            // 通過Fegin接口訪問服務消費者的服務
            String result = driverClient.takeOrder(msg);
            System.out.println("乘客收到信息: " + result);
            return result;
        }
    
  2. 結束,調用可以,
    在這裏插入圖片描述

2. Fegin 負載均衡

Fegin內部集成了Ribbon,並默認開啓了負載均衡,所以對於負載均衡我們並不需要做什麼處理了。
對於負載均衡策略的配置,和集成 Ribbon 的配置相同,可以通過yml配置或者通過注入Bean配置。
如果不需要配置負載均衡策略,我們就不需要做任何事。

3. Fegin 集成 Hystrix

Fegin內部也集成了Hystrix。但是默認是不開啓, 所以我們需要通過配置開啓他。
以下:所有的配置都在服務消費者(EurekaServerConsumer)中

  1. 在yml文件中開啓 hystrix 熔斷功能
feign:
  hystrix:
    enabled: true   # 開啓Fegin的熔斷功能
  1. 我們在上一篇介紹Hystrix 的文章中將服務提供者的接口內容進行了修改,如下。改造之前的服務提供者服務(EurekaServerProvider),如下,不接待叫張三的人,目的是爲了在僞造某種請求失敗的狀況來觸發熔斷。也就是說,這裏如果請求參數是 張三,則請求失敗,如果是其它,則請求成功。

    在這裏插入圖片描述

1. 通過Fallback來進行熔斷

  1. 在DriverClient 熔斷類的 @FeignClient 註解指定熔斷類爲 DriverClientFallBack。注意,@RequestMapping一定不要寫在類上面,在方法上拼接,否則會出現異常,提示DriverClient 注入了多個實例(找了一下午才找到的原因)

    @FeignClient(value = "eureka-server-provider", fallback = DriverClientFallBack.class) // 標註該類是一個feign接口,其服務名是 eurake-server-provider,fallback 指定熔斷類
    public interface DriverClient {
        /**
         *  司機接單服務
         * @param msg
         * @return
         */
        @RequestMapping("driver/takeOrder")
        String takeOrder(@RequestParam("msg") String msg);
    }
    
  2. DriverClientFallBack 類是一個實現了 DriverClient 接口的類,並注入Spring容器中,如下。當調用driver/takeOrder 出現異常時,會進入 takeOrder 該熔斷方法內。

    @Component
    public class DriverClientFallBack implements DriverClient {
        @Override
        public String takeOrder(String msg) {
            return "DriverServiceFallBack  服務正忙,請稍後再試";
        }
    }
    
  3. 調用結果如下,張三會走到熔斷方法,其餘參數正常調用:
    在這裏插入圖片描述
    在這裏插入圖片描述

2. 通過FallbackFactory來進行熔斷

通過FallbackFactory 可以進行熔斷,但是我們沒有辦法看到是爲什麼熔斷,如果想看到異常信息,可以使用Fallback的增強版 FallbackFactory。

  1. 創建一個 DriverClientFallBackFactory 類 繼承 FallbackFactory 類,

    import feign.hystrix.FallbackFactory;
    import org.springframework.stereotype.Component;
    
    @Component
    public class DriverClientFallBackFactory implements FallbackFactory<DriverClient> {
    
        @Override
        public DriverClient create(Throwable throwable) {
            System.out.println("DriverServiceFallBackFactory     " + throwable.getMessage());
            return new DriverClient() {
                @Override
                public String takeOrder(String msg) {
                    return "DriverServiceFallBackFactory  服務正忙,請稍後再試";
                }
            };
        }
    }
    
  2. 修改DriverClient 方法,使用fallbackFactory 指定熔斷工廠類:

    @FeignClient(value = "eureka-server-provider", fallbackFactory = DriverClientFallBackFactory.class) // 標註該類是一個feign接口,其服務名是 eurake-server-provider
    public interface DriverClient {
        /**
         *  司機接單服務
         * @param msg
         * @return
         */
        @RequestMapping("driver/takeOrder")
        String takeOrder(@RequestParam("msg") String msg);
    }
    
  3. 調用可以看到,錯誤信息。
    在這裏插入圖片描述

3. Hystrix局部配置

一個服務中肯定會有多個Fegin客戶端,而有的服務需要服務降級,有的不需要,這時就不能僅僅通過yml的全局配置來決定了。
比如滴滴平臺上有多位註冊司機,有的司機說,我不願意接離跑太遠的乘客,那麼我們可以給他配置Hystrix熔斷,超過一定“距離“ 熔斷,有的司機願意接遠距離乘客,那麼我們就沒必要給他配置熔斷(例子不太合適,方便理解一下而已)。

首先我們先來看一下@FeignClient 註解參數的意義:

參數 意義
name 指定FeignClient的名稱,如果項目使用了Ribbon,name屬性會作爲微服務的名稱,用於服務發現
decode404 當發生http 404錯誤時,如果該字段位true,會調用decoder進行解碼,否則拋出FeignException
url url一般用於調試,可以手動指定@FeignClient調用的地址
configuration Feign配置類,可以自定義Feign的Encoder、Decoder、LogLevel、Contract
fallback 定義容錯的處理類,當調用遠程接口失敗或超時時,會調用對應接口的容錯邏輯,fallback指定的類必須實現@FeignClient標記的接口
fallbackFactory 工廠類,用於生成fallback類示例,通過這個屬性我們可以實現每個接口通用的容錯邏輯,減少重複的代碼
path 定義當前FeignClient的統一前綴
  1. 編寫配置類

    @Configuration
    public class DriverConfiguration {
        /**
         *  配置日誌級別
         *  - NONE:不記錄任何日誌信息,這是默認值。
         * - BASIC:僅記錄請求的方法,URL以及響應狀態碼和執行時間
         * - HEADERS:在BASIC的基礎上,額外記錄了請求和響應的頭信息
         * - FULL:記錄所有請求和響應的明細,包括頭信息、請求體、元數據。
         * @return
         */
        @Bean
        Logger.Level feignLoggerLevel(){
            return Logger.Level.FULL;
        }
    
        /**
         * 配置不進行熔斷
         * @return
         */
        @Bean
        public Feign.Builder feignBuilder() {
            return Feign.builder();
        }
    }
    
  2. 指定配置類對應的FeginClient
    在這裏插入圖片描述

  3. 再次訪問,發現DriverClient已經關閉了Hystix 熔斷。
    在這裏插入圖片描述
    以上:內容部分參考
    https://www.cnblogs.com/shmilyToHu/p/10725944.html
    https://blog.csdn.net/a15514920226/article/details/78924483
    如有侵擾,聯繫刪除。 內容僅用於自我記錄學習使用。如有錯誤,歡迎指正

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