Spring Cloud(三):Web服务客户端之Feign

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

Feign

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

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

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

 

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

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客户端的默认配置app

 

一样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

 


 

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

 

 

 

原文出处:https://www.cnblogs.com/spec-dog/p/12217166.html

相关文章
相关标签/搜索