SpringCloud- 第十一篇 Feign+Ribbon

1:概述

因为Spring Cloud Feign的客户端负载均衡是经过Spring Cloud Ribbon实现的,因此能够直接经过配置Ribbon客户端的方式来自定义各个服务客户端调用的参数

2:全局配置

ribbon.ConnectTimeout=500 
ribbon.ReadTimeOut=5000

3:指定服务配置

userService.ribbon.ConnectTimeout=500 
userService.ribbon.ReadTimeout=2000

4:重试机制

userService.ribbon.ConnectTimeout=500
userService.ribbon.ReadTimeout=2000
userService.ribbon.OkToRetryOnAllOperations=true
userService.ribbon.MaxAutoRetriesNextServer=2
userService.ribbon.MaxAutoRetries=1
Ribbon的超时与Hystrix的超时是两个概念。通常须要让hystrix的超时时间大于Ribbon的超时时间,不然Hystrix命令超时后,直接熔断,重试机制就没有任何意义了

5:参数绑定

经常使用绑定参数的方式java

  • @RequestParam 绑定单个请求参数值
  • @PathVariable 绑定URI模板变量值;
  • @RequestHeader 绑定请求头数据;
  • @RequestBody 绑定请求的内容区数据并能进行自动类型转换等
注意在定义各参数绑定的时候,@RequestParam和@RequestHeader等能够指定参数名称的注解,它们的value值千万不能少。在spring mvc程序中,这些注解会根据指定参数名来做为默认值,可是在fegin中绑定参数必须经过value属性来指明具体的参数名,否则会抛出IllegalStateException异常,value属性不能为空。

6:Feign的默认配置

  • 概述

Spring Cloud的Feign的一个中心概念就是客户端。 每一个Feign客户端都是组合的组件的一部分,它们一块儿工做以按需调用远程服务器,而且该集合具备将其做为使用@FeignClient注释的参数名称。
SpringCloud使用FeignClientsConfiguration建立一个新的集合,做为每一个命名客户端的ApplicationContext(应用上下文),这包含feign.Decoder,feign.Encoder和feign.Contract。spring

  • Spring Cloud Netflix默认为Feign提供如下bean:

Decoder feignDecoder:ResponseEntityDecoder(其中包含SpringDecoder)
Encoder feignEncoder:SpringEncoder
Logger feignLogger:Slf4jLogger
Contract feignContract:SpringMvcContract
Feign.Builder feignBuilder:HystrixFeign.Builder
Client feignClient:若是Ribbon启用,则为LoadBalancerFeignClient,不然将使用默认的feign客户端。
能够自定义FeignClientsConfiguration以彻底控制这一系列的配置。apache

7:自定义配置

写一个自定义配置类,注意不要放到当前ComponentScan的范围下,示例如:json

@Configuration
public class MyConf {
    @Bean
    public Contract feignContract() {
        return new feign.Contract.Default();
    }
}
定义的是new feign.Contract.Default(),全部在UserService接口中只能使用Feign本身的注解url方式,使用Spring MVC的注解就会报错
写好配置后,经过设置@FeignClient的configuration来使用,以下:
@FeignClient(value = "userService",configuration=MyConf.class)
能够为每一个Feign客户端都配置本身的默认配置

8: @FeignClient

@FeignClient标签的经常使用属性以下:api

  • name(value):指定FeignClient的名称,若是项目使用了Ribbon,name属性会做为微服务的名称,用于服务发现
  • url: url通常用于调试,能够手动指定@FeignClient调用的地址
  • configuration: Feign配置类,能够自定义Feign的Encoder、Decoder、LogLevel、Contract
  • fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口,并使用@Component注解
  • fallbackFactory: 工厂类,用于生成fallback类示例,经过这个属性咱们能够实现每一个接口通用的容错逻辑,减小重复的代码
  • path: 定义当前FeignClient的统一前缀,添加到Feign访问服务的访问路径上

decode404:当发生http 404错误时,若是该字段位true,会调用decoder进行解码,不然抛出FeignException服务器

  • serviceId属性如今已被弃用,有利于name属性。

之前,使用url属性,不须要name属性。如今须要使用namemvc

9:Feign和@Primary

9.1:概述

当使用Feign与Hystrix回退时,在同一类型的ApplicationContext中有多个bean。这将致使@Autowired不起做用,由于没有一个bean标记为主。
为了解决这个问题,Spring Cloud Netflix将全部Feign实例标记为@Primary,因此Spring Framework将知道要注入哪一个bean。在某些状况下,这多是不可取的。要关闭此行为,将@FeignClient的primary属性设置为false,如:
@FeignClient(name = "hello", primary = false)

10:Feign的HTTP Client

Feign在默认状况下使用的是JDK原生的URLConnection发送HTTP请求,没有链接池,可是对每一个地址会保持一个长链接,即利用HTTP的persistence connection 。
能够用Apache的HTTP Client替换Feign原始的http client, 从而获取链接池、超时时间等与性能息息相关的控制能力。Spring Cloud从Brixtion.SR5版本开始支持这种替换,首先在项目中声明Apache HTTP Client和feign-httpclient依赖: 
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>
<dependency>
    <groupId>com.netflix.feign</groupId>
    <artifactId>feign-httpclient</artifactId>
    <version>8.18.0</version>
</dependency>

而后在application.properties中添加: app

feign.httpclient.enabled=true

11: 自定义的Encode、Decode、ErrorDecode

  • Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder)完成的。同理,将HTTP响应数据反序列化为java对象是由解码器(Decoder)完成的。
  • 默认状况下,Feign会将标有@RequestParam注解的参数转换成字符串添加到URL中,将没有注解的参数经过Jackson转换成json放到请求体中。
  • 在Spring Cloud环境下,Feign的Encoder只会用来编码没有添加注解的参数。若是你自定义了Encoder, 那么只有在编码没有注解的参数时才会调用你的Encoder。
  • 对于Decoder, 默认会委托给SpringMVC中的MappingJackson2HttpMessageConverter类进行解码。只有当状态码不在200 ~ 300之间时ErrorDecoder才会被调用。ErrorDecoder的做用是能够根据HTTP响应信息返回一个异常,该异常能够在调用Feign接口的地方被捕获到。咱们目前就经过ErrorDecoder来使Feign接口抛出业务异常以供调用者处理。

12: FeignClient工做过程

FeignClient至关于Spring Cloud中的RPC,大体实现的过程以下:负载均衡

1:首先经过@EnableFeignCleints注解开启FeignCleint
2:根据Feign的规则实现接口,并加@FeignCleint注解
3:程序启动后,会进行包扫描,扫描全部的@FeignCleint的注解的类,并将这些信息注入到IoC容器中
4:当接口的方法被调用,经过JDK的代理,来生成具体的RequestTemplate
5:RequestTemplate再生成调用的Request
6:Request交给Client去处理,其中Client能够是HttpUrlConnection、HttpClient也能够是Okhttp
7:最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon作到了负载均衡,真正发送请求出去

13:特性继承

13.1:概述

当使用SpringMVC的注解来绑定服务接口时候,几乎能够彻底从服务提供方的Controller中复制操做,构建出相应的服务客户端绑定接口。既然存在这么多复制操做,咱们天然须要考虑这部份内容是否能够获得进一步的抽象。Spring Cloud Feign中,针对该问题提供了继承特性来帮助解决这些复制操做,以进一步减小编码量。

13.2:基本方法

  • 就是把接口提出来,把model提出来,而后provider和client都使用这个工程
  • Provider这边在Controller中再也不包含以往会定义的映射注解@RequestMapping,而参数的注解定义在重写的时候自动带过来了,这个类中,除了要实现接口逻辑以外,只须要增长了@RestController注解使该类成为一个REST接口类。
  • Consumer这边直接注入Feign标注的接口,彻底像调用本地接口同样。

13.3:注意

  • Feign接口只能支持一层继承,并且不能多继承
  • 官方不建议在服务器和客户端之间共享接口,由于它引入了紧耦合,而且实际上并不适用于当前形式的Spring MVC(方法参数映射不被继承)。

image.png

14:Hystrix配置

14.1: 概述

Spring Cloud Feign中集成了Hystrix,Spring Cloud Feign客户端的方法都封装到Hystrix命令中进行服务保护。ide

14.2:全局配置

直接使用它的默认配置前缀hystrix.command.default就能够进行设置,好比设置全局的超时时间, Hystrix默认的超时时间是1秒:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000 在对hystrix进行设置以前,须要确认Feign的Hystrix功能是开启的。

14.3: 禁用hystrix

能够经过设置feign.hystrix.enabled为false,或者使用hystrix.command.default.execution.timeout.enabled=false来关闭熔断功能
若是不想全局地关闭Hystrix支持,而只想针对某个服务客户端关闭Hystrix支持时,须要经过使用@Scope(“protototype”)注解为指定的客户端配置Feign.Builder实例,如:

@Configuration
public class DisableHystrixConfigutation {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
    return Feign.builder();
}}

在该服务的Feign接口中引入该配置:

@FeignClient(value = "user-service",configuration = DisableHystrixConfigutation.class) ...

14.4: 指定命令配置

在实际应用中可能会根据实际业务状况制定出不一样的配置方案,能够采用hystrix.command.<commandKey>做为前缀。而<commandKey>默认状况下会采用feign客户端中的方法名做为标识。须要注意的是,因为方法名有可能会重复,这个时候相同的方法名的hystrix配置会共用,因此在进行方法与配置的时候须要作好必定的规划。

14.5: 服务降级配置

Spring Cloud Feign在定义服务客户端的时候与Spring cloud Ribbon有很大的差异,因为HystrixCommand定义被封装起来,没法经过@HystrixCommand注解的fallback参数那样来指定具体的服务降级处理方法。Spring Cloud Feign提供了另一种简单的方式。
方法大体是:定义一个Feign客户端的服务降级类UserServiceFallback,实现UserService接口,其中每一个重写方法的实现逻辑均可以用来定义相应的服务降级逻辑;在服务绑定接口中,经过@FeignClient注解的fallback属性来指定对应的服务降级实现类。

14.6: 请求压缩

Spring Cloud Feign支持对请求与响应进行GZIP压缩,以减小通讯过程当中的性能损耗,只须要经过下面的两个参数设置,就能开启请求与相应的压缩功能:

feign.compression.request.enabled=true 
feign.compression.response.enabled=true

同时,还能够对请求压缩作一些更细致的设置,好比下面的配置内容指定压缩的请求数据类型,并设置了请求压缩的大小下限,只有超过这个大小的请求才会进行压缩:

feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048

15:日志配置

Spring Cloud Feign在构建被@FeignClient注解修饰的服务客户端时,会为每个客户端都建立一个feign.Logger实例,能够配置logging.level.<feignClient>的参数配置格式来开启指定feign客户端的debug日志,其中<feignClient>为feign客户端定义接口的完整路径,例如:

logging.level.com.cc.springcloud_feign_api.UserService2=debug

注意,只添加该配置还没法实现对debug日志的输出。这是由于feign客户端默认的Logger.Level对象定义为NONE级别,该级别不会记录任何Feign调用过程当中的信息,因此须要调整它的级别,针对全局的日志级别,能够在应用主类中加入:

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

也能够实现配置类,而后在Feign客户端来指定配置类以实现不一样的日志级别。
对于Feign的Logger级别主要有下面4类,可根据实际须要进行调整使用:

  • none:不记录任何信息
  • basic:仅记录请求方法,url以及响应状态码和执行时间
  • headers:除了记录basic级别的信息以外,还会记录请求和响应的头信息。
  • FULL:记录全部请求与响应的明细,包括头信息,请求体,元数据等。
相关文章
相关标签/搜索