专栏首页JMCuiSpring Cloud 之 Feign.

Spring Cloud 之 Feign.

一、概述

 前面的文章中提到,如果我们要调用其它应用的服务,只能够通过 RestTemplate 的方式,这在我们实际的开发中很不方便。那么有没有类似于 Dubbo 中 @Reference 这样的注解直接调用呢?这就是我们今天要讲的 Spring Cloud Feign。

 Spring Cloud Feign 基于 Netflix Feign 实现,整合了 Spring Cloud Ribbon 与 Spring Cloud Hystrix,除了提供这两者的强大功能之外,它还提供了一种声明式的 Web 服务客户端定义方式。

 Spring Cloud Feign 具备可插拔的注解支持,包括 Feign 注解和 JAX-RS 注解。同时,为了适应 Spring 的广大用户,它在 Netflix Feign 的基础上扩展了对 Spring MVC 的注解支持。

二、Feign 实战

SpringBoot 版本号:2.1.6.RELEASE SpringCloud 版本号:Greenwich.RELEASE

1. pom.xml

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

2. application.yml

server:
  port: 2032

spring:
  application:
    name: cloud-feign-consumer


eureka:
  client:
    service-url:
      defaultZone: http://user:password@localhost:1111/eureka/

3. FeignApplication.java

// 开启 Spring Cloud Feign 的支持功能
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FeignApplication {

    public static void main(String[] args) {
        SpringApplication.run(FeignApplication.class, args);
    }
}

4. 接口定义

@FeignClient(value = "cloud-eureka-client")
public interface FeignService {

    @RequestMapping("/hello")
    String hello();
}

这里我们定义了一个接口(方法名和注解与服务提供方一致),并通过 @FeignClient 注解绑定到服务提供方。当调用 FeignService.hello() 的时候,Feign 会把请求包装成 "http://cloud-eureka-client/hello" 的样子,通过 RestTemplate 调用并返回结果。

对于 Spring Cloud Feign 的参数绑定,就是当调用方法需要有参数的时候,参数格式只需按照 Spring MVC 的注解即可。区别是:在定义各参数绑定时,@RequestParam、@RequestHeader 等可以指定参数名称的注解,它们的 value 千万不能少。在 SpringMVC 程序中,这些注解会根据参数名来作为默认值,但是在 Feign 中绑定参数必须通过 value 属性来指明具体的参数名。

对于在服务提供方和服务调用方都维护一份接口定义的做法着实不提倡,原因很简单,修改了一个方法,需要同时在两个地方做出改变。比较好的做法是:服务提供方暴露一个 xxx-interface 的 jar 包供服务调用方引用。这样,服务调用方,直接引用 xxx-interface 的方法,不维护接口定义,不关心实现。

5. Spring Cloud Feign 中的 Ribbon 配置

由于 Spring Cloud Feign 的客户端负载均衡是通过 Spring Cloud Ribbon 实现的,所以我们可以直接通过配置 Ribbon 客户端的方式来定义各个服务客户端调用的参数。

# 全局配置
ribbon:
  # 连接超时时间
  ConnectTimeout: 500
  # 调用超时时间
  ReadTimeout: 2000

# 针对单个服务的 Ribbon 配置
cloud-eureka-client:
  ribbon:
    # 重试次数
    MaxAutoRetries: 2

我们需要让 Hystrix 的超时时间大于 Ribbon 的超时时间,否则 Hystrix 命令超时后,该命令直接熔断,重试机制就没有任何意义了。

配置参数可以在 CommonClientConfigKey.java 中查询到,具体每个参数的含义,就不在这里细讲了。

6. Spring Cloud Feign 中的 Hystrix 配置

默认情况下,Spring Cloud Feign 会为将所有 Feign 客户端的方法都封装到 Hystrix 命令中进行服务保护。当然,可以在配置文件中选择开启或者关闭 Hystrix:

feign:
  hystrix:
    enabled: true

如果我们仅要在某个服务中关闭 Hystrix 呢?那么我们就要自定义一个配置类了:

@Configuration
public class DisableHystrixConfig {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Feign.Builder feignBuilder() {
        return new Feign.Builder();
    }

}

然后再 @FeignClient 注解中引用:

@FeignClient(value = "cloud-eureka-client", configuration = DisableHystrixConfig.class)

上一篇文章 我们看到 Hystrix 中有很多的配置参数,那么在 Feign 中如何配置它们呢?

# 配置全局的超时时间
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutinMilliseconds: 5000

    # 针对某个 commandKey 做配置,而 commandKey 默认取得是客户端中的方法名作为标识。所以如果存在相同方法名会共用配置。
    hello:
      execution:
        isolation:
          thread:
            timeoutinMilliseconds: 5000

Hystrix 的配置参数可以在 HystrixCommandProperties.java 中找到。

7. 服务降级

在 Hystrix 中服务降级我们通过 fallbackMethod 来实现,那么 Feign 中没法直接使用 @HystrixCommand 注解,要怎么配置服务降级呢?首先。我们要实现一个需要降级的接口,并提供降级实现:

@Component
public class FeignServiceFallback implements FeignService {

    @Override
    public String hello() {
        return "error";
    }
}

然后再 @FeignClient 注解中引用:

@FeignClient(value = "cloud-eureka-client", configuration = DisableHystrixConfig.class, fallback = FeignServiceFallback.class)

8. 日志配置

Spring Cloud Feign 在构建被 @FeignClient 注解修饰的服务客户端时,会为每一个客户端都创建一个 Logger.Level 实例,我们可以利用该日志对象的 DEBUG 模式来帮助分析 Feign 的请求细节。

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

Logger.Level 有四种级别:

  • NONE: 不记录任何信息。
  • BASIC: 仅记录请求方法、URL以及响应状态码和执行时间。
  • HEADERS: 除了记录 BASIC 级别的信息之外,还会记录请求和响应的头信息。
  • FULL: 记录所有请求与响应的明细,包括头信息、请求体、元数据等。

tips:该配置项只有 Spring 的日志级别为 Debug 时才生效。

9. 其他配置

Spring Cloud Feign 支持对请求与响应进行 GZIP 压缩,以减少通信过程中的性能损耗。

feign:
  compression:
    # 开启请求和响应的压缩功能
    request:
      enabled: true
      # 超过 2M 才开始压缩
      min-request-size: 2048
      # 压缩类型
      mime-types: {"text/xml", "application/xml", "application/json"}
    response:
      enabled: true

演示源代码 :https://github.com/JMCuixy/spring-cloud-demo

内容参考:《Spring Cloud 微服务实战》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 前后端分离开发思路探讨

    但是毕竟要从前后端不分变为前后端分离,思维的变化还是比较大的,因此,今天我们就再来说说一说这个话题。

    江南一点雨
  • 你是一直认为 count(1) 比 count(*) 效率高么?

    有 Where 条件的 count,会根据扫码结果count 一下所有的行数,其性能更依赖于你的 Where 条件,所以文章我们仅针对没有 Where 的情况进...

    Fayson
  • 解读年度数据库PostgreSQL:如何处理并发控制(一)

    原文:http://www.enmotech.com/web/detail/1/748/1.html

    数据和云01
  • Vue教程01(基础入门)

      因为最近需要使用到Vue,所以打算将Vue的学习资料详细整理一份,感兴趣的小伙伴可以一起来哦。

    用户4919348
  • 都9102年了,你还不会准备Android面试?进来这里告诉你

    在老东家呆了将近四年光景,受益颇多,无奈在技能上遇到瓶颈,深感自己技能上不能再进步,毅然离职,加入求职大军。说实话,遇上18年的金融危机、互联网寒冬、裁员,大量...

    CCCruch
  • @ResponseBody 总是乱码?这个问题得好好捋一捋!

    在这篇文章的最后,松哥提了一句,“还有一些非常偶尔的情况可能会用到 @RequestMapping 注解中的 produces 属性”,但是对于这个问题并没有展...

    江南一点雨
  • 『高级篇』docker容器来说软件架构的进化(二)

    IT故事会
  • 『互联网架构』软件架构-深入理解Feign(94)

    PS:dubbo是CP(一致性,容错),eureka是AP(高可用,容错),Feign是方便调用的框架,Ribbon是客户端的负载均衡。

    IT故事会
  • 详述一次大量删除导致MySQL慢查的过程

    墨墨导读:本文记录一次大量删除导致MySQL慢查的分析,大家有没有遇到过这种问题?

    数据和云
  • 美团技术四面经历,作者已拿到Offer!

    blog.csdn.net/csuliyajin2012/article/details/49430659

    Java技术栈

扫码关注云+社区

领取腾讯云代金券