微服務Spring Cloud17_Feign9

花溪月影發表於2024-05-08

在前面的學習中,使用了Ribbon的負載均衡功能,大大簡化了遠端呼叫時的程式碼: 如果就學到這裡,你可能以後需要編寫類似的大量重複程式碼,格式基本相同,無非引數不一樣。有沒有更優雅的方 式,來對這些程式碼再次最佳化呢? 這就是接下來要學的Feign的功能了。

一、簡介 Feign也叫偽裝: Feign可以把Rest的請求進行隱藏,偽裝成類似SpringMVC的Controller一樣。你不用再自己拼接url,拼接引數等等 操作,一切都交給Feign去做。 專案主頁:https://github.com/OpenFeign/feign

1.2. 快速入門 1.2.1. 匯入依賴 在 consumer-demo 專案的 pom.xml 檔案中新增如下依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

1.2.2. Feign的客戶端

在 consumer-demo 中編寫如下Feign客戶端介面類:

package com.itheima.consumer.client;
import com.itheima.consumer.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("user-service")
public interface UserClient {
    @GetMapping("/user/{id}")
    User queryById(@PathVariable("id") Long id);
}

首先這是一個介面,Feign會透過動態代理,幫我們生成實現類。這點跟mybatis的mapper很像 @FeignClient ,宣告這是一個Feign客戶端,同時透過 value 屬性指定服務名稱 介面中的定義方法,完全採用SpringMVC的註解,Feign會根據註解幫我們生成URL,並訪問獲取結果 @GetMapping中的/user,請不要忘記;因為Feign需要拼接可訪問的地址 編寫新的控制器類 ConsumerFeignController ,使用UserClient訪問:

package com.itheima.consumer.controller;
import com.itheima.consumer.client.UserClient;
import com.itheima.consumer.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/cf")
public class ConsumerFeignController {
    @Autowired
    private UserClient userClient;
    @GetMapping("/{id}")
    public User queryById(@PathVariable Long id){
        return userClient.queryById(id);
   }
}

1.2.3. 開啟Feign功能 在 ConsumerApplication 啟動類上,新增註解,開啟Feign功能

package com.itheima.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/*@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker*/
@SpringCloudApplication
@EnableFeignClients//開啟Feign功能
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
   }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
   }
}

Feign中已經自動整合了Ribbon負載均衡,因此不需要自己定義RestTemplate進行負載均衡的配置。

1.2.4. 啟動測試 訪問介面:http://localhost:8080/cf/2

正常獲取到了結果。

1.3. 負載均衡 Feign中本身已經整合了Ribbon依賴和自動配置:

因此不需要額外引入依賴,也不需要再註冊 RestTemplate 物件。Fegin內建的ribbon預設設定了請求超時時長,預設是1000,我們可以透過手動配置來修改這個超時時長:

ribbon:
 ReadTimeout: 2000 # 讀取超時時長
 ConnectTimeout: 1000 # 建立連結的超時時長

因為ribbon內部有重試機制,一旦超時,會自動重新發起請求。如果不希望重試,可以新增配置: 修改 consumer-demo\src\main\resources\application.yml 新增如下配置:

ribbon:
 ConnectTimeout: 1000 # 連線超時時長
 ReadTimeout: 2000 # 資料通訊超時時長
 MaxAutoRetries: 0 # 當前伺服器的重試次數
 MaxAutoRetriesNextServer: 0 # 重試多少次服務
 OkToRetryOnAllOperations: false # 是否對所有的請求方式都重試

重新給UserService的方法設定上執行緒沉睡時間2秒可以測試上述配置

1.4. Hystrix支援(瞭解) Feign預設也有對Hystrix的整合:

只不過,預設情況下是關閉的。需要透過下面的引數來開啟; 修改 consumer-demo\src\main\resources\application.yml 新增如下配置:

feign:
 hystrix:
   enabled: true # 開啟Feign的熔斷功能

但是,Feign中的Fallback配置不像Ribbon中那樣簡單了。 1)首先,要定義一個類,實現剛才編寫的UserFeignClient,作為fallback的處理類

package com.itheima.consumer.client.fallback;
import com.itheima.consumer.client.UserClient;
import com.itheima.consumer.pojo.User;
import org.springframework.stereotype.Component;
@Component
public class UserClientFallback implements UserClient {
    @Override
    public User queryById(Long id) {
        User user = new User();
        user.setId(id);
        user.setName("使用者異常");
        return user;
   }
}

2)然後在UserFeignClient中,指定剛才編寫的實現類

@FeignClient(value = "user-service", fallback = UserClientFallback.class)
public interface UserClient {
    @GetMapping("/user/{id}")
    User queryById(@PathVariable("id") Long id);
}

3)重啟測試 重啟啟動 consumer-demo 並關閉 user-service 服務,然後在頁面訪問:http://localhost:8080/cf/8

1.5. 請求壓縮(瞭解) Spring Cloud Feign 支援對請求和響應進行GZIP壓縮,以減少通訊過程中的效能損耗。透過下面的引數即可開啟請求 與響應的壓縮功能:

feign:
 compression:
   request:
     enabled: true # 開啟請求壓縮
   response:
     enabled: true # 開啟響應壓縮

同時,我們也可以對請求的資料型別,以及觸發壓縮的大小下限進行設定:

feign:
 compression:
   request:
     enabled: true # 開啟請求壓縮
     mime-types: text/html,application/xml,application/json # 設定壓縮的資料型別
     min-request-size: 2048 # 設定觸發壓縮的大小下限

注:上面的資料型別、壓縮大小下限均為預設值。

1.6. 日誌級別(瞭解) 前面講過,透過 logging.level.xx=debug 來設定日誌級別。然而這個對Fegin客戶端而言不會產生效果。因為 @FeignClient 註解修改的客戶端在被代理時,都會建立一個新的Fegin.Logger例項。我們需要額外指定這個日誌的 級別才可以。 1)在 consumer-demo 的配置檔案中設定com.itheima包下的日誌級別都為 debug 修改 consumer-demo\src\main\resources\application.yml 新增如下配置:

logging:
 level:
   com.itheima: debug

2)在 consumer-demo 編寫FeignConfig配置類,定義日誌級別

package com.itheima.consumer.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(){
        //記錄所有請求和響應的明細,包括頭資訊、請求體、後設資料
        return Logger.Level.FULL;
   }
}

這裡指定的Level級別是FULL,Feign支援4種級別: NONE:不記錄任何日誌資訊,這是預設值。 BASIC:僅記錄請求的方法,URL以及響應狀態碼和執行時間 HEADERS:在BASIC的基礎上,額外記錄了請求和響應的頭資訊 FULL:記錄所有請求和響應的明細,包括頭資訊、請求體、後設資料。

3)在 consumer-demo 的 UserClient 介面類上的@FeignClient註解中指定配置類:

package com.itheima.consumer.client;
import com.itheima.consumer.client.fallback.UserClientFallback;
import com.itheima.consumer.config.FeignConfig;
import com.itheima.consumer.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "user-service", fallback = UserClientFallback.class,
configuration = FeignConfig.class)
public interface UserClient {
    @GetMapping("/user/{id}")
    User queryById(@PathVariable Long id);
}

4)重啟專案,訪問:http://localhost:8080/cf/8 ;即可看到每次訪問的日誌:

相關文章