天天看點

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結

思維導圖

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結
文章已收錄Github精選,歡迎Star: https://github.com/yehongzhi/learningSummary

前言

目前在SpringCloud技術棧中,調用服務用得最多的就是OpenFeign,是以這篇文章講一下OpenFeign,希望對大家有所幫助。

一、建構工程

使用Nacos作為注冊中心,不會搭建Nacos的話,可以參考上一篇注冊中心的文章。

首先父工程parent引入依賴。

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>0.2.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-openfeign</artifactId>
            <version>2.0.1.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency><!-- SpringCloud nacos服務發現的依賴 -->
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
        <version>1.2.0</version>
    </dependency>
</dependencies>           

搭建提供者provider工程和消費者consumer工程。

provider工程繼承父工程的pom檔案,編寫啟動類如下:

@SpringBootApplication
@EnableDiscoveryClient//注冊中心
public class ProviderApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(ProviderApplication.class, args);
    }
}           

provider工程的配置檔案如下:

server:
  port: 8080
spring:
  application:
    name: provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}           

提供接口,Controller如下:

@RestController
public class ProviderController {
    @RequestMapping("/provider/list")
    public List<String> list() {
        List<String> list = new ArrayList<>();
        list.add("java技術愛好者");
        list.add("SpringCloud");
        list.add("沒有人比我更懂了");
        return list;
    }
}           

消費者consumer工程也繼承parent的pom檔案,加上Feign依賴:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
        <!-- 版本在parent的pom檔案中指定了 -->
    </dependency>
</dependencies>           

編寫啟動類,如下:

@SpringBootApplication
@EnableDiscoveryClient
//開啟feign接口掃描,指定掃描的包
@EnableFeignClients(basePackages = {"com.yehongzhi.springcloud"})
public class ConsumerApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}           

環境搭建完成後,接下來講兩種實作使用方式。

二、聲明式

這種很簡單,消費者consumer工程增加一個ProviderClient接口。

@FeignClient(name = "provider")
//會掃描指定包下,标記FeignClient注解的接口
//會根據服務名,從注冊中心找到對應的IP位址
public interface ProviderClient {
    //這裡跟提供者接口的URL一緻
    @RequestMapping("/provider/list")
    String list();
}           

然後再用消費者工程的ConsumerController接口來測試。

@RestController
public class ConsumerController {
    //引入Feign用戶端
    @Resource
    private ProviderClient providerClient;

    @RequestMapping("/consumer/callProvider")
    public String callProvider() {
        //使用Feign用戶端調用其他服務的接口
        return providerClient.list();
    }
}           

最後我們啟動提供者工程,消費者工程,注冊中心,測試。

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結

然後調用消費者的ConsumerController接口。

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結

三、繼承式

細心的同學可能發現,其實聲明式會寫多一次提供者接口的定義,也就是有重複的代碼,既然有重複的定義,那我們就可以抽取出來,是以就有了繼承式。

第一步,建立一個普通的Maven項目api工程,把接口定義在api中。

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結

第二步,服務提供者工程的ProviderController實作Provider接口。

@RestController
public class ProviderController implements ProviderApi {
    
    public String list() {
        List<String> list = new ArrayList<>();
        list.add("java技術愛好者");
        list.add("SpringCloud");
        list.add("沒有人比我更懂了");
        return list.toString();
    }
}           

第三步,消費者工程的ProviderClient無需定義,隻需要繼承ProviderApi,然後加上@FeignClient即可。

@FeignClient(name = "provider")
public interface ProviderClient extends ProviderApi {
}           

其他不用變了,最後啟動服務提供者,消費者,注冊中心測試一下。

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結

測試成功!上面繼承式的好處就在于,隻需要在api工程定義一次接口,服務提供者去實作具體的邏輯,消費者則繼承接口貼個注解即可,非常友善快捷。

缺點就在于如果有人動了api的接口,則會導緻很多服務消費者、提供者出現報錯,耦合性比較強。api工程相當于一個公共的工程,消費者和服務者都會依賴此工程,是以一般要求不能随便删api上面的接口。

四、Feign的相關配置

下面講一下Feign的一些常用的相關配置。

4.1 請求逾時設定

Feign底層其實還是使用Ribbon,預設是1秒。是以超過1秒就報錯。

接下來試驗一下。我在服務提供者的接口加上一段休眠1.5秒的代碼,然後用消費者去消費。

@RestController
public class ProviderController implements ProviderApi {
    public String list() {
        List<String> list = new ArrayList<>();
        list.add("java技術愛好者");
        list.add("SpringCloud");
        list.add("沒有人比我更懂了");
        try {
            //休眠1.5秒
            Thread.sleep(1500);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list.toString();
    }
}           

消費者調用後,由于超過1秒,可以看到控制台報錯。

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結

如果想調整逾時時間,可以在消費者這邊,加上配置:

ribbon:
  ReadTimeout:  5000 #請求時間5秒
  ConnectTimeout: 5000 #連接配接時間5秒           

為了顯示出效果,我們在消費者的代碼裡加上耗時計算:

@RestController
public class ConsumerController {

    @Resource
    private ProviderClient providerClient;

    @RequestMapping("/consumer/callProvider")
    public String callProvider() throws Exception {
        long star = System.currentTimeMillis();
        String list = providerClient.list();
        long end = System.currentTimeMillis();
        return "響應結果:" + list + ",耗時:" + (end - star) / 1000 + "秒";
    }
}           

最後啟動測試,可以看到,超過1秒也能請求成功。

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結

4.2 日志列印功能

首先需要配置Feign的列印日志的級别。

@Configuration
public class FeignConfig {
    /**
     * NONE:預設的,不顯示任何日志
     * BASIC:僅記錄請求方法、URL、響應狀态碼及執行時間
     * HEADERS:出了BASIC中定義的資訊之外,還有請求和響應的頭資訊
     * FULL:除了HEADERS中定義的資訊之外,還有請求和響應的正文及元素
     */
    @Bean
    public Logger.Level feginLoggerLevel() {
        return Logger.Level.FULL;
    }
}           

第二步,需要設定列印的Feign接口。Feign為每個用戶端建立一個logger。預設情況下,logger的名稱是Feigh接口的完整類名。需要注意的是,Feign的日志列印隻會對DEBUG級别做出響應。

#與server同級
logging:
  level:
    com.yehongzhi.springcloud.consumer.feign.ProviderClient: debug           

設定完成後,控制台可以看到詳細的請求資訊。

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結

4.3 Feign實作熔斷

openFeign實際上是已經引入了hystrix的相關jar包,是以可以直接使用,設定逾時時間,逾時後調用FallBack方法,實作熔斷機制。

首先在消費者工程添加Maven依賴。

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

第二步,在配置中開啟熔斷機制,添加逾時時間。

#預設是不支援的,是以這裡要開啟,設定為true
feign:
  hystrix:
    enabled: true
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000           

第三步,編寫FallBack類。

//ProviderClient是貼了@FeignClient注解的接口
@Component
public class ProviderClientFallBack implements ProviderClient {
    @Override
    public String list() {
        return Arrays.asList("調用fallBack接口", "傳回未知結果").toString();
    }
}           

第四步,在對應的Feign接口添加fallback屬性。

//fallback屬性,填寫剛剛編寫的FallBack回調類
@Component
@FeignClient(name = "provider", fallback = ProviderClientFallBack.class)
public interface ProviderClient extends ProviderApi {
}           

最後可以測試一下,超過設定的3秒,則會熔斷,調用FallBack方法傳回。

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結

4.4 設定負載均衡

前面說過OpenFeign底層是使用Ribbon,Ribbon是負責做負載均衡的元件。是以是可以通過配置設定負載均衡的政策。

預設的是輪詢政策。如果要換成其他政策,比如随機,怎麼換呢。

很簡單,改一下配置即可:

#服務名稱
provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置規則 随機
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置規則 輪詢
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置規則 重試
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置規則 響應時間權重
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule #配置規則 最空閑連接配接政策           

總結

OpenFeign把RestTemplete,Ribbon,Hystrix糅合在了一起,在使用時就可以更加友善,優雅地完成整個服務的暴露,調用等。避免做一些重複的複制粘貼接口URL,或者重複定義接口等。還是非常值得去學習的。

以前我在的公司搭建的SpringCloud微服務就沒有使用Feign,架構師自己寫了一個AOP代理類進行服務調用,逾時時間5秒寫死在代碼裡,當時有個微服務接口要上傳檔案,總是逾時,又改不了逾時時間,一逾時就調熔斷方法傳回服務請求逾時,導緻非常痛苦。

如果當時使用Feign,插拔式,可配置的方式,也許就沒那麼麻煩了。

那麼feign就講到這裡了,上面所有例子的代碼都上傳Github了:

https://github.com/yehongzhi/example

覺得有用就點個贊吧,你的點贊是我創作的最大動力~

拒絕做一條鹹魚,我是一個努力讓大家記住的程式員。我們下期再見!!!

詳細講解OpenFeign的使用姿勢!思維導圖前言一、建構工程二、聲明式三、繼承式四、Feign的相關配置總結
能力有限,如果有什麼錯誤或者不當之處,請大家批評指正,一起學習交流!

繼續閱讀