Feign遠(yuǎn)程調(diào)用

代碼參考

Gitee:[https://gitee.com/xn2001/cloudcode/tree/master/06-cloud-feign](https://gitee.com/xn2001/cloudcode/tree/master/06-cloud-feign)

GitHub:[https://github.com/lexinhu/cloudcode/tree/master/06-cloud-feign](https://github.com/lexinhu/cloudcode/tree/master/06-cloud-feign)

我們以前利用 RestTemplate 發(fā)起遠(yuǎn)程調(diào)用的代碼:


  • 代碼可讀性差,編程體驗(yàn)不統(tǒng)一
  • 參數(shù)復(fù)雜URL難以維護(hù)

Feign 是一個(gè)聲明式的 http 客戶端,官方地址:https://github.com/OpenFeign/feign

其作用就是幫助我們優(yōu)雅的實(shí)現(xiàn) http 請(qǐng)求的發(fā)送,解決上面提到的問題。

Feign使用

引入依賴

我們?cè)?order-service 引入 feign 依賴:

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

添加注解

在 order-service 啟動(dòng)類添加注解開啟 Feign

請(qǐng)求接口

在 order-service 中新建一個(gè)接口,內(nèi)容如下

package com.xn2001.order.client;

import com.xn2001.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("userservice")
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

@FeignClient("userservice"):其中參數(shù)填寫的是微服務(wù)名
@GetMapping("/user/{id}"):其中參數(shù)填寫的是請(qǐng)求路徑
這個(gè)客戶端主要是基于 SpringMVC 的注解 @GetMapping 來聲明遠(yuǎn)程調(diào)用的信息
Feign 可以幫助我們發(fā)送 http 請(qǐng)求,無需自己使用 RestTemplate 來發(fā)送了。

測(cè)試

@Autowired
private UserClient userClient;

public Order queryOrderAndUserById(Long orderId) {
    // 1.查詢訂單
    Order order = orderMapper.findById(orderId);
    // TODO: 2021/8/20 使用feign遠(yuǎn)程調(diào)用
    User user = userClient.findById(order.getUserId());
    // 3. 將用戶信息封裝進(jìn)訂單
    order.setUser(user);
    // 4.返回
    return order;
}

自定義配置

Feign 可以支持很多的自定義配置,如下表所示:



一般情況下,默認(rèn)值就能滿足我們使用,如果要自定義時(shí),只需要?jiǎng)?chuàng)建自定義的 @Bean 覆蓋默認(rèn) Bean 即可。下面以日志為例來演示如何自定義配置。

基于配置文件修改 feign 的日志級(jí)別可以針對(duì)單個(gè)服務(wù):

feign:  
  client:
    config: 
      userservice: # 針對(duì)某個(gè)微服務(wù)的配置
        loggerLevel: FULL #  日志級(jí)別 

也可以針對(duì)所有服務(wù):

feign:  
  client:
    config: 
      default: # 這里用default就是全局配置,如果是寫服務(wù)名稱,則是針對(duì)某個(gè)微服務(wù)的配置
        loggerLevel: FULL #  日志級(jí)別 

而日志的級(jí)別分為四種:

  • NONE:不記錄任何日志信息,這是默認(rèn)值。
  • BASIC:僅記錄請(qǐng)求的方法,URL以及響應(yīng)狀態(tài)碼和執(zhí)行時(shí)間
  • HEADERS:在BASIC的基礎(chǔ)上,額外記錄了請(qǐng)求和響應(yīng)的頭信息
  • FULL:記錄所有請(qǐng)求和響應(yīng)的明細(xì),包括頭信息、請(qǐng)求體、元數(shù)據(jù)

也可以基于 Java 代碼來修改日志級(jí)別,先聲明一個(gè)類,然后聲明一個(gè) Logger.Level 的對(duì)象


public class DefaultFeignConfiguration  {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志級(jí)別為BASIC
    }
}

如果要全局生效,將其放到啟動(dòng)類的 @EnableFeignClients 這個(gè)注解中:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class) 

如果是局部生效,則把它放到對(duì)應(yīng)的 @FeignClient 這個(gè)注解中:

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class) 

性能優(yōu)化

Feign 底層發(fā)起 http 請(qǐng)求,依賴于其它的框架。其底層客戶端實(shí)現(xiàn)有:

  • URLConnection:默認(rèn)實(shí)現(xiàn),不支持連接池
  • Apache HttpClient :支持連接池
  • OKHttp:支持連接池

因此提高 Feign 性能的主要手段就是使用連接池代替默認(rèn)的 URLConnection

另外,日志級(jí)別應(yīng)該盡量用 basic/none,可以有效提高性能。

這里我們用 Apache 的HttpClient來演示連接池。

在 order-service 的 pom 文件中引入 HttpClient 依賴

<!--httpClient的依賴 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

配置連接池

在 order-service 的 application.yml 中添加配置

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志級(jí)別,BASIC就是基本的請(qǐng)求和響應(yīng)信息
  httpclient:
    enabled: true # 開啟feign對(duì)HttpClient的支持
    max-connections: 200 # 最大的連接數(shù)
    max-connections-per-route: 50 # 每個(gè)路徑的最大連接數(shù)

最佳實(shí)踐

繼承方式

一樣的代碼可以通過繼承來共享:

1)定義一個(gè) API 接口,利用定義方法,并基于 SpringMVC 注解做聲明

2)Feign 客戶端、Controller 都集成該接口

優(yōu)點(diǎn)

  • 簡(jiǎn)單
  • 實(shí)現(xiàn)了代碼共享

缺點(diǎn)

  • 服務(wù)提供方、服務(wù)消費(fèi)方緊耦合
  • 參數(shù)列表中的注解映射并不會(huì)繼承,因此 Controller 中必須再次聲明方法、參數(shù)列表、注解

抽取方式

將 FeignClient 抽取為獨(dú)立模塊,并且把接口有關(guān)的 pojo、默認(rèn)的 Feign 配置都放到這個(gè)模塊中,提供給所有消費(fèi)者使用。

例如:將 UserClient、User、Feign 的默認(rèn)配置都抽取到一個(gè) feign-api 包中,所有微服務(wù)引用該依賴包,即可直接使用。

接下來我們就用該方法在代碼中實(shí)現(xiàn)

首先創(chuàng)建一個(gè) module,命名為 feign-api


在 feign-api 中然后引入依賴

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

order-service中 的 UserClient、User 都復(fù)制到 feign-api 項(xiàng)目中

接下來在 order-service 中使用 feign-api

由于我們已經(jīng)將 UserClient、User 放在 fegin-api 中共享了 ,所以可以刪除 order-service 中的 UserClient、User,然后在 order-service 中引入 feign-api

<dependency>
    <groupId>com.xn2001.feign</groupId>
    <artifactId>feign-api</artifactId>
    <version>1.0</version>
</dependency>

修改注解

當(dāng)定義的 FeignClient 不在 SpringBootApplication 的掃描包范圍下時(shí),這些 FeignClient 就不能使用。

修改 order-service 啟動(dòng)類上的 @EnableFeignClients 注解

@EnableFeignClients(basePackages = "com.xn2001.feign.clients")
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容