前文介绍了实现客户端负载均衡的Ribbon,但直接使用Ribbon的API来实现服务间的调用相对较为繁琐,服务间的调用能否像本地接口调用一样便捷、透明,更符合编程习惯呢?Feign就是用来干这事的。

Feign

Feign是一个声明式的Web服务客户端,让服务之间的调用变得非常简单——定义带@FeignClient注解的接口,本地直接@Autowired 接口,通过调用接口的方法来实现远程服务的调用。

支持的注解包括Feign注解与JAX-RS(Java API for RESTful Web Services)注解。

每一个Feign的客户端都包含一系列对应的组件,Spring Cloud通过FeignClientsConfiguration 为每一个命名的Feign客户端创建一个组件集合,包括feign.Decoder,feign.Encoder,feign.Contract等。

Feign提供的默认bean实现及说明

Bean类型 默认实现类 说明
Decoder ResponseEntityDecoder ResponseEntityDecoder封装了SpringDecoder,解码器,将服务的响应消息进行解码
Encoder SpringEncoder 编码器
Logger Slf4jLogger 日志框架
Contract SpringMvcContract 支持注解契约,使用SpringMvcContract可以对Spring MVC注解提供支持
Feign.Builder HystrixFeign.Builder 使用断路器来装饰Feign接口
Client LoadBalancerFeignClient 如果是ribbon则 LoadBalancerFeignClient, 如果是spring cloud LoadBalancer 则 FeignBlockingLoadBalancerClient,默认ribbon

跟Ribbon类似,可以通过配置类来自定义Feign客户端,如

@FeignClient(name = "hello-service", configuration = CustomConfiguration.class)
public interface StoreClient {
//..
} public class CustomConfiguration {
@Bean
public Contract feignContract() {
return new feign.Contract.Default();
}
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("user", "password");
}
}

这样Feign客户端就包含了FeignClientsConfiguration 与CustomConfiguration 中定义的组件,并且后者会覆盖前者(即自定义配置的优先级高于默认配置)。

自定义配置类不需要加注解@Configuration,如果加了且被@ComponentScan扫描到,则将成为所有Feign客户端的默认配置

同样Feign客户端也支持通过配置文件来配置

feign:
client:
config:
feignName:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example.SimpleRetryer
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
decode404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract

对于应用于所有Feign客户端的全局默认配置,也可以通过两种方式

  1. 通过@EnableFeignClients 的defaultConfiguration 属性指定默认配置类

  2. 在配置文件中通过名称为default的配置实现

    feign:
    client:
    config:
    default:
    connectTimeout: 5000
    readTimeout: 5000
    loggerLevel: basic

优先级同Ribbon, 配置文件>自定义配置类>默认的FeignClientsConfiguration


案例演示

本文案例演示基于前面搭建的springcloud-eureka 与 springcloud-eureka-client 两个示例项目。

  1. 新建springcloud-feign项目,pom.xml中加入依赖

    <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>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    spring-cloud-starter-openfeign 包含了spring-cloud-starter-netflix-ribbon 与 spring-cloud-starter-loadbalancer。

  1. 启动类加上@EnableFeignClients 注解

    @SpringBootApplication
    @EnableFeignClients
    public class FeignApplication { public static void main(String[] args) {
    SpringApplication.run(FeignApplication.class, args);
    }
    }
  2. 定义Feign client(feign client支持继承)

    @FeignClient("hello-service")
    public interface HelloClient extends BaseHelloClient{ @RequestMapping("hello/param")
    String hello(@SpringQueryMap QueryParam param);
    }
  3. 调用Feign client

    @RestController
    public class FeignController { @Autowired
    private HelloClient helloClient; @RequestMapping("feign")
    public String feignTest(){
    return "调用Hello-service返回:" + helloClient.hello();
    } @RequestMapping("feign/param")
    public String feignTestParam(QueryParam param) {
    return "调用Hello-service返回:" + helloClient.hello(param);
    }
    }

依次启动三个项目,调用http://localhost:8083/feign 能正常返回调用hello-service的结果。

本示例项目还通过@SrpingQueryMap 注解实现了Feign对 pojo用于GET请求参数的支持。如果不加@SrpingQueryMap, 则pojo参数是无法通过Feign client传递的,可去掉注解自行验证下。


一些知识点

  1. 如果需要定制化产生的查询参数map,可以实现并注入一个自定义的 QueryMapEncoder bean

  2. Feign client的日志可通过feign client接口的全路径名进行配置,如logging.level.project.user.UserClient: DEBUG,默认为NONE(即不打印日志)。全局设置

    @Configuration
    public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
    return Logger.Level.FULL;
    }
    }

    可设置的level值

    • NONE:不记录日志 ,默认

    • BASIC:只记录请求方法,url,以及响应状态码与执行时间

    • HEADERS:包括BASIC与请求、响应头

    • FULL:包括请求与响应的headers,body,metadata

  1. Feign默认使用Ribbon来做负载均衡,可通过配置spring.cloud.loadbalancer.ribbon.enabled=false 来使用spring cloud loadbalancer(目前Ribbon处于维护状态,近期内不做更新)

  2. 可通过配置feign.okhttp.enabled=true 或 feign.httpclient.enabled=true 来使用OkHttpClient 或ApacheHttpClient, 默认使用的是JDK 原生的URLConnection 发送HTTP请求,没有连接池

  3. 如果需要在RequestInterceptor 中使用ThreadLocal中的变量, 那么要么禁用Hystrix,要么设置hystrix的线程隔离策略为SEMAPHORE

    feign:
    hystrix:
    enabled: false
    # 或者
    hystrix:
    command:
    default:
    execution:
    isolation:
    strategy: SEMAPHORE
  4. 使用有Hystrix fallback的Feign时,会在ApplicationContext中存在多个同类型bean, 导致@Autowired 失效。为了解决这个问题,Spring cloud netflix 将所有feign实例标为@Primary,如果要关闭该特性, 可将@FeignClient的 primary属性置为false。

    @FeignClient(name = "hello", primary = false)
    public interface HelloClient {
    // ...
    }

本文示例代码:https://github.com/ronwxy/springcloud-demos


认真生活,快乐分享
欢迎关注微信公众号:空山新雨的技术空间

Spring Cloud(三):Web服务客户端之Feign的更多相关文章

  1. Spring Cloud(三):服务提供与调用

    上一篇文章我们介绍了eureka服务注册中心的搭建,这篇文章介绍一下如何使用eureka服务注册中心,搭建一个简单的服务端注册服务,客户端去调用服务使用的案例. 案例中有三个角色:服务注册中心.服务提 ...

  2. spring cloud 学习之服务消费者(Feign)

    一.Feign简介 Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单.使用Feign,只需要创建一个接口并注解.它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注 ...

  3. spring cloud 声明式rest客户端feign调用远程http服务

    在Spring Cloud Netflix栈中,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端.Feign就是Spring Cloud提供的一种声明式R ...

  4. Spring Boot + Spring Cloud 构建微服务系统(三):服务消费和负载(Feign)

    Spring Cloud Feign Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端.它使得编写Web服务客户端变得更加简单.我们只需要通过创建接口 ...

  5. Spring Cloud(二):Web服务客户端之Ribbon

    上文介绍了服务如何通过Eureka实现注册,以及如何从Eureka获取已经注册的服务列表.那么拿到注册服务列表后, 如何进行服务调用?一个简单的实现是可以从被调用服务的实例列表中选择一个服务实例,通过 ...

  6. spring cloud 入门系列五:使用Feign 实现声明式服务调用

    一.Spring Cloud Feign概念引入通过前面的随笔,我们了解如何通过Spring Cloud ribbon进行负责均衡,如何通过Spring Cloud Hystrix进行服务断路保护,两 ...

  7. Spring Cloud 声明式服务调用 Feign

    一.简介 在上一篇中,我们介绍注册中心Eureka,但是没有服务注册和服务调用,服务注册和服务调用本来应该在上一章就应该给出例子的,但是我觉得还是和Feign一起讲比较好,因为在实际项目中,都是使用声 ...

  8. Spring Cloud 新一代Web框架微服务翘楚(一)

    序言 springcloud是微服务架构的集大成者,将一系列优秀的组件进行了整合.基于springboot构建,对我们熟悉spring的程序员来说,上手比较容易. 通过一些简单的注解,我们就可以快速的 ...

  9. Spring Cloud构建微服务架构(三)消息总线

     注:此文不适合0基础学习者直接阅读,请先完整的将作者关于微服务的博文全部阅读一遍,如果还有疑问,可以再来阅读此文,地址:http://blog.csdn.net/sosfnima/article/d ...

随机推荐

  1. 一道非常棘手的 Java 面试题:i++ 是线程安全的吗

    转载自  一道非常棘手的 Java 面试题:i++ 是线程安全的吗 i++ 是线程安全的吗? 相信很多中高级的 Java 面试者都遇到过这个问题,很多对这个不是很清楚的肯定是一脸蒙逼.内心肯定还在质疑 ...

  2. H3C查看保存的配置文件

  3. IdentityServer4 sign-in

    原文地址 Sign-in IdentityServer 代表 user 分配token之前,user必须登录IdentityServer Cookie authentication 使用 cookie ...

  4. 由Request Method:OPTIONS初窥CORS

    刚接触前端的时候,以为HTTP的Request Method只有GET与POST两种,后来才了解到,原来还有HEAD.PUT.DELETE.OPTIONS…… 目前的工作中,HEAD.PUT.DELE ...

  5. C语言中的关键字总结

    1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...

  6. IPv4数据报格式及其语义

    一.IP数据报的格式如下图所示 版本 首部长度 服务类型 数据报长度 16比特标识 标志 13比特片偏移 寿命 上层协议 首部检验和 32比特源IP地址 32比特目的IP地址 选项(如果有的话) 数据 ...

  7. c++ 知道旋转前后矩阵向量值 求旋转矩阵c++/c#代码 知道两个向量求他们的旋转矩阵

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/12115244.html 知道旋转前后矩阵向量值 如何去求旋转矩阵R 的c++/c#代码??? ...

  8. 记一次linux磁盘清理 - 已经删除的文件占用了大量磁盘空间

    今天开发环境磁盘占满了,导致开发环境上的 nginx .redis 等组件总是报异常. 跳到系统根目录下 cd / 检查磁盘占用情况 df -h 哇,40G硬盘全用完了.看看是哪些文件占了那么多内存. ...

  9. Linux忘记root密码后如何在grub界面中以单用户模式进入系统并重置密码的方法

    本文将介绍在Linux系统中忘记root用户密码的情况下,如何在gurb界面进入单用户模式并重置root用户密码.在单用户模式下,用户不需要输入任何密码即可进入系统并可以修改密码.实验步骤如下: 1. ...

  10. 【他山之石】mybatis打印sql日志 相关配置

    背景:mybatis的sql日志打印对我来说一直比较迷,哪怕看过网上很多博客后还是这样,这两天刚好又遇到了问题,要查sql不得已又来查阅,这次终于搞定了. mybatis是有提供日志功能支持的,目前支 ...