天天看點

Spring Cloud(08)——Feign服務接口調用Spring Cloud(08)——Feign服務接口調用

文章目錄

  • Spring Cloud(08)——Feign服務接口調用
    • 1、Feign簡介
    • 2、OpenFeign使用步驟
    • 3、OpenFeign的逾時控制
    • 4、OpenFeign日志列印功能

Spring Cloud(08)——Feign服務接口調用

在Spring Cloud(07)——Ribbon負載均衡服務的介紹和使用中,我們使用Ribbon+RestTemplate時,利用RestTemplate對http請求的封裝處理,形成了一套模闆化的調用方法。但是在實際開發中,由于對微服務依賴的調用可能不止一處,往往一個接口會被多處調用,是以通常都會針對每個微服務自行封裝一些用戶端類來包裝這些依賴服務的調用。是以下面我們使用Feign來幫助我們定義和實作依賴服務接口的定義,就像Java程式員熟悉的面向接口的程式設計思想。

1、Feign簡介

  • Feign 是一個聲明式的 REST 用戶端,它能讓 REST 調用更加簡單。Feign 提供了 HTTP 請求的模闆,通過編寫簡單的接口和插入注解,就可以定義好 HTTP 請求的參數、格式、位址等資訊。
  • Feign可以幫助我們更快捷、優雅地調用HTTP API。
  • Feign 是一個使用起來更加友善的用戶端,它讓微服務之間的調用變得更簡單了,類似controller調用service,用起來就好像調用本地方法一樣,完全感覺不到是調用遠端方法。
  • Feign 可以與 Eureka 和 Ribbon 組合使用以支援負載均衡。
  • Feign 中內建了Ribbon
Feign與OpenFeign的差別
Spring Cloud(08)——Feign服務接口調用Spring Cloud(08)——Feign服務接口調用

2、OpenFeign使用步驟

使用OpenFeign隻需建立一個接口,并在接口上添加注解(

@FeignClient

)即可。

1、建立cloud-consumer-feign-order80子產品

2、導入pom依賴

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

    <dependency>
        <groupId>com.cheng.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
</dependencies>
           

3、編寫yml配置檔案

server:
  port: 80

eureka:
  client:
    register-with-eureka: false  # 不向eureka注冊中心注冊自己
    service-url: 
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/  #Eureka叢集
           

4、主啟動類

@SpringBootApplication
@EnableFeignClients  //開啟feign的功能
public class OrderFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderFeignMain80.class,args);
    }
}
           

5、建立PaymentFeignService接口,并添加@FeignClient注解,該接口用于定義并實作Feign的功能

package com.cheng.springcloud.service;

import com.cheng.springcloud.pojo.CommonResult;
import com.cheng.springcloud.pojo.Payment;
import feign.Param;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE") //綁定要通路的服務名
public interface PaymentFeignService {

    //上面綁定服務名後, 通過調用接口/payment/get/{id},通路裡面具體的服務
    @GetMapping(value = "/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id);
}

           

6、編寫controller

package com.cheng.springcloud.controller;

import com.cheng.springcloud.pojo.CommonResult;
import com.cheng.springcloud.pojo.Payment;
import com.cheng.springcloud.service.PaymentFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderFeignController {

    @Resource
    private PaymentFeignService paymentFeignService;


    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        //調用該接口後,會通過定義好的feign功能接口PaymentFeignService,去通路服務提供者裡的服務,
        // 不需要服務消費者自己去通路服務提供者
        return paymentFeignService.getPaymentById(id);
    }
}
           

7、測試

  1. 啟動cloud-eureka-server7001和cloud-eureka-server7002子產品
  2. 啟動cloud-provider-payment8001和cloud-provider-payment8002子產品
  3. 啟動cloud-consumer-feign-order80子產品

通路請求:http://localhost/consumer/payment/get/1

第一次通路:

Spring Cloud(08)——Feign服務接口調用Spring Cloud(08)——Feign服務接口調用

第二次通路:

Spring Cloud(08)——Feign服務接口調用Spring Cloud(08)——Feign服務接口調用

繼續通路,8002和8001輪流使用,Feign預設實作了輪詢的負載均衡算法。

因為Spring Cloud Feign是基于Netflix feign實作,整合了Spring Cloud Ribbon。

3、OpenFeign的逾時控制

故意設定逾時,示範出錯情況

1、在cloud-provider-payment8001服務提供者子產品的controller中設定逾時方法:

@GetMapping(value = "/payment/feign/timeout")
public String PaymentFeignTimeout(){

    try {
        //TimeUnit是java.util.concurrent包下面的一個類,TimeUnit提供了可讀性更好的線程暫停操作。  SECOND秒
        TimeUnit.SECONDS.sleep(3);//線程暫停3秒
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return serverPort;


}
           

2、在cloud-consumer-feign-order80子產品的feign接口中添加逾時方法:

@GetMapping(value = "/payment/feign/timeout")
public String PaymentFeignTimeout();
           

3、在cloud-consumer-feign-order80子產品的controller中通路逾時方法:

@GetMapping(value = "/consumer/payment/feign/timeout")
public String PaymentFeignTimeout(){
    return paymentFeignService.PaymentFeignTimeout();
}
           

4、測試

  1. 啟動cloud-eureka-server7001和cloud-eureka-server7002子產品
  2. 啟動cloud-provider-payment8001子產品
  3. 啟動cloud-consumer-feign-order80子產品

自測:通路請求:http://localhost:8001/payment/feign/timeout 延遲三秒後,通路成功,自測沒問題!

再用openfeign調用服務接口進行測試:

通路請求:http://localhost/consumer/payment/feign/timeout

報錯:

Spring Cloud(08)——Feign服務接口調用Spring Cloud(08)——Feign服務接口調用

預設Feign用戶端隻等待一秒鐘,但是服務端處理需要超過1秒鐘,導緻Feign用戶端不再等待,直接傳回報錯。

為了避免這樣的情況,有時候我們需要設定Feign用戶端的逾時控制。

cloud-consumer-feign-order80子產品yml配置檔案添加:

#設定feign用戶端逾時時間
ribbon:
#建立連接配接所用的時間
  ReadTimeout: 5000
#建立連接配接後從伺服器讀取到可用資源的時間
  ConncetTimeout: 5000
           

重新開機cloud-consumer-feign-order80子產品測試:通路請求:http://localhost/consumer/payment/feign/timeout

延遲三秒後成功通路到服務。

Spring Cloud(08)——Feign服務接口調用Spring Cloud(08)——Feign服務接口調用

4、OpenFeign日志列印功能

有時候我們遇到 Bug,比如接口調用失敗、參數沒收到等問題,或者想看看調用性能,就需要配置 Feign 的日志列印功能,以此讓 Feign 把請求資訊輸出來。

到日志等級有 4 種,分别是:

  • NONE:不輸出日志。
  • BASIC:隻輸出請求方法的 URL 和響應的狀态碼以及接口執行的時間。
  • HEADERS:将 BASIC 資訊和請求頭資訊輸出。
  • FULL:輸出完整的請求資訊

首先定義一個配置類,代碼如下所示。

package com.cheng.springcloud.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfiguration {

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
           

然後在yml檔案裡配置feign的日志功能:

logging:
  level:
#    feign日志以什麼級别監控哪個接口
    com.cheng.springcloud.service.PaymentFeignService: debug
           

重新開機cloud-consumer-feign-order80子產品測試:通路請求:http://localhost/consumer/payment/get/1,檢視背景日志輸出:

Spring Cloud(08)——Feign服務接口調用Spring Cloud(08)——Feign服務接口調用

繼續閱讀