【微服務】- SpringCloud整合OpenFeign及OpenFeign簡單使用


簡介

位置:https://cloud.spring.io/spring-cloud-openfeign/2.2.x/reference/html/

Feign是一個聲明式WebService客戶端。 使用Feign能讓編寫Web Service客戶端更加簡單。

它的使用方法是定義一個服務接口然后在上面添加注解。Feign也支 持可拔插式的編碼器和解碼器。Spring Cloud對Feign進行了封裝使其支持了Spring MVC標准注解和HttpMessageConverters。Feign可以與Eureka和Ribbon組合使用以支持負載均衡。

圖片

概述

feign是一個聲明式web服務客戶端,讓編寫web客戶服務端變得非常簡單。只需要創建一個接口並在接口添加注解即可。

Feign的作用

Feign旨在使編寫Java Http客戶端變得更容易。

前面在使用Ribbon + RestTemplate時,利用RestTemplate對http請求的封裝處理, 形成了一套模版化的調用方法。但是在實際開發中,由於對服務依賴的調用可能不止一處,往往一個接口會被多 處調用,所以通常都會針對每個微服務自行封裝-些客戶端類來包裝這些依賴服務的調用。所以,** Feign在此基礎上做了進一步封裝, 由他來幫助我們定義和實現依賴服務接口的定義。**在Feign的實現下我們只需創建一個接口並使用注解的方式來配置它(以前是Dao接口 上面標注Mapper注解現在是一個微服務接口 上面標注一個Feign注解即可),即可完成對服務提供方的接口綁定,簡化了使用Spring cloud Ribbon時,自動封裝服務調用客戶端的開發量。

Feign集成了Ribbon

利用Ribbon維護了Payment的服務列表信息,並且通過輪詢實現了客戶端的負載均衡。而與Ribbon不同的是,通過feign只需要定義服務綁定接口且以聲明式的方法,優雅而簡單的實現了服務調用

Feign和OpenFeign的區別

圖片

SpringCloud集成OpenFeign

1.先准備測試用到的服務集群和Eureka集群

圖片

Eureka是服務注冊中心就不多說。8081和8082服務是兩個功能相同的項目,是一個服務集群,因為OpenFeign代替了Ribbon + RestTemplate的工作,故說明OpenFeign帶有Ribbon的依賴可以實現負載均衡。服務集群的功能很簡單,就是從數據庫中根據id進行查詢。

2.新建OpenFeign項目(空maven項目)

cloud-consumer-feign-order80

3.添加依賴

<dependencies>
    <dependency>
        <groupId>wf.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>1.0-SNAPSHOT</version>
        <scope>compile</scope>
    </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.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!--   引入eureka客戶端     -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--  open feign      -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

4.添加配置文件(application.yml)

server:
  port: 80

eureka:
  client:
    register-with-eureka: false #是否將自己注冊到注冊中心,集群必須設置為true配合ribbon
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka

5.寫主啟動類

package wf.springcloud
@SpringBootApplication
@EnableFeignClients
public class OrderFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderFeignMain80.class,args);
    }
}

注意@EnableFeignClients注解不能少,這表明在該服務中使用了OpenFeign。

6.寫service層

上面說過OpenFeign代替了Ribbon + RestTemplate的工作,即它還要承擔RestTemplate,而在OpenFeign中的代替方案就是建一個,接口並使用注解的方式來配置它。類似於SpringBoot項目中Dao層的工作。從其他地方查詢數據。不過此處項目小故用service來代替。

package wf.springcloud.service;
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
@Component
public interface PaymentFeignService {
    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}

接口中的方法其實就是要調用服務的controller層的類接口的形式。下面是服務層的controller

@RestController
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;
    @Value("${server.port}")
    private String serverport;
    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        Payment result = paymentService.getPaymentById(id);
        log.info("查詢結果:" + result);
        if (result != null){
            return new CommonResult<Payment>(200,"查詢成功! port:" + serverport,result);
        }else {
            return new CommonResult<Payment>(444,"查詢失敗!",null);
        }
    }
}

此處就表明了OpenFeign中的一個特性支持SpringMVC的注解。
要注意的是服務層@GetMapping(value = “/payment/get/{id}”)是controller中url的全拼,此處沒在PaymentController類上沒加類似@RequestMapping(value = “/xx”)。故conroller中的@GetMapping(value = “/payment/get/{id}”)與service中的相同。

如果在類中加相關mapping如

@RestController
@Slf4j
@RequestMapping(value = "/a")
public class OrderFeignController {
    @Resource
    private PaymentFeignService paymentFeignService;
    @GetMapping(value = "/b")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        return paymentFeignService.getPaymentById(id);
    }
}

那么在service中的@GetMapping的值就是/a/b。而不是直接和方法上@GetMapping相同的/b。
如果寫成/b回報

feign.FeignException$NotFound: status 404 reading PaymentFeignService#getPay

錯誤找不到相關方法。

7.寫controller

@RestController
@Slf4j
public class OrderFeignController {
    @Resource
    private PaymentFeignService paymentFeignService;
    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        return paymentFeignService.getPaymentById(id);
    }
}

就像普通項目中調用service就可完成需要的功能。

8.測試結果

訪問http://localhost/consumer/payment/get/5

圖片

圖片

可以看到負載均衡起作用了。

9.總結

圖片

OpenFeign的超時控制

OpenFeign默認調用的服務超時時間為1s,如果超過會報錯

下面是演示:

1.在8081和8082中添加一個超時的方法

@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeout(){
    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return serverport;
}

2.在Feign的服務中添加相關方法

在service的接口中添加

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

在controller中添加

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

此時啟動項目服務,訪問http://localhost/consumer/payment/feign/timeout會出現

This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri Apr 10 22:52:28 CST 2020
There was an unexpected error (type=Internal Server Error, status=500).
Read timed out executing GET http://CLOUD-PAYMENT-SERVICE/payment/feign/timeout
feign.RetryableException: Read timed out executing GET http://CLOUD-PAYMENT-SERVICE/payment/feign/timeout
	at feign.FeignException.errorExecuting(FeignException.java:213)
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:115)
...

超時錯誤。想要對Feign的超時進行控制只需要在yml文件添加相關配置即可

對feign的超時控制

在application.yml添加

server:
  port: 80

eureka:
  client:
    register-with-eureka: false #是否將自己注冊到注冊中心,集群必須設置為true配合ribbon
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
#設置feign客戶端超時時間(openFeign默認支持ribbon)
ribbon:
  #指的是建立連接所用的時間,適用於網絡狀況iE常的情況下兩端連接所用的時間
  ReadTimeout: 5000
  #指的是建立連接后從服務器讀取到可用資源所用的時間
  ConnectTimeout: 5000

啟動項目會發現,超時錯誤消失。程序可以正常訪問。

OpenFeign的日志打印功能

是什么

Feign提供了日志打印功能,我們可以通過配置來調整日志級別,從而了解Feign中Http請求的細節說白了就是對Feign接口的調用情況進行監控和輸出

2.OpenFeign的日志級別

  • NONE:默認的,不顯示任何日志;
  • BASIC:僅記錄請求方法、URL、 響應狀態碼及執行時間;
  • HEADERS:除了BASIC 中定義的信息之外,還有請求和響應的頭信息;
  • FULL:除了HEADERS中定義的信息之外,還有請求和響應的正文及元數據。

3.如何啟用日志打印功能

1.添加配置類

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/** * @Description TODO * @Author gyhdx * @Date 2020/4/10 23:05 */
@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

注意此處的Logger要使用feign中的。
2.在yml文件中添加相關配置

logging:
  level:
    # feign日志以什么級別監控哪個接口
    wf.springcloud.service.PaymentFeignService: debug

注意添加成功后都是藍顏色的除了debug
圖片

3.訪問PaymentFeignService接口中存在的方法

圖片

配置成功


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM