Spring Cloud About OpenFeign

Spring Cloud About OpenFeign

一、Feign和OpenFeign简介

Feign是一个Netflix开源的声明式HTTP Client,它使得编写Web服务更加容易。在使用Ribbon+RestTempla时,里用RestTemplate请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,对于服务依赖的调用可能有多处,因此通常会针对每个微服务自行封装一些客户端类来包装这些服务依赖调用。所以,Feign就在此基础上进行了包装(所以Feign是集成Ribbon的),Feign只需要定义服务绑定接口且以声明式的方法优雅而简单的实现了服务调用。Feign可以用来做客户端负载均衡,去调用服务注册中心的服务,而OpenFeign是在Feign的基础上支持了Spring MVC的注解。

二、OpenFeign使用

pom文件引入feign

 <dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
1.feign的日志级别

feign的日志级别有4种,分别是:

级别解释
NONE不输出日志,默认
BASIC只输出请求方法的URL、响应状态码、执行时间,适用生产环境
HEADERS将BASIC信息和请求头信息输出
FULL输出完整的信息,适合开发环境
2.细粒度的feign日志级别配置

(1)首先设置一个配置类

/**
 * 这个配置类不能加@Configuration注解,否则需要像Ribbon一样放在主启动类所在的包外
 * 原因也是Spring父子上下文重叠
 */
public class FeignConfig {

    @Bean
    public Logger.Level level() {
        //这里使用FULL级别的feign日志
        return Logger.Level.FULL;
    }
}

如果不用配置类,也可以在配置文件配置

feign:
  client:
    config:
      # 要调用服务的名称
      user-center:
        loggerLevel: full

如果使用配置类,还需要在@FeignClient接口加上配置类信息,一般建议一个服务对应一个接口,否则还需要额外的配置。

@FeignClient(name = "user-center", configuration = FeignConfig.class)
public interface UserCenterFeignClient {

    @GetMapping("/user/{id}")
    UserDTO findById(@PathVariable(value = "id") Integer id);
}

(2)再去配置文件配置接口的日志级别,这个日志级别配置是属于spring的,也就是说,feign的日志级别是建立spring的日志级别为debug级别的基础上的

# 设置接口的spring日志级别
logging:
  level:
    # 需要接口的相对路径,debug为日志级别
    com.shanganba.test_spring_cloud_alibaba.feignclient.UserCenterFeignClient: debug
3.全局feign日志级别配置

(1)设置一个配置类

/**
 * 这个配置类不能加@Configuration注解,否则需要像Ribbon一样放在主启动类所在的包外
 * 原因也是Spring父子上下文重叠
 */
public class FeignConfig {

    @Bean
    public Logger.Level level() {
        //这里使用FULL级别的feign日志
        return Logger.Level.FULL;
    }
}

如果不使用配置类,也可以在配置文件配置

# 配置feign的日志级别
feign:
  client:
    config:
    # 全局日志级别配置
      default:
        loggerLevel: full

如果使用配置类,还需要在主启动类加上配置类信息

@EnableFeignClients(defaultConfiguration = FeignConfig.class)
@EnableDiscoveryClient
@SpringBootApplication
public class TestMain8002 {
    public static void main(String[] args) {
        SpringApplication.run(TestMain8002.class, args);
    }
}

(2)再去配置文件配置接口的spring日志级别

# 设置接口的spring日志级别
logging:
  level:
    # 需要接口的相对路径,debug为日志级别
    com.shanganba.test_spring_cloud_alibaba.feignclient.UserCenterFeignClient: debug
4.feign调用非注册中心的服务

feign可以调用非注册中心列表里包含的服务,只需要在@FeignClient中指定name(这个name是随意的),然后同时指明调用的地址url,然后在接口中写调用方法。

//FeignClient的name可以支持读取配置文件的值
//@FeignClient(name = "${baidu}", url = "www.baidu.com")
@FeignClient(name = "baidu", url = "www.baidu.com")
public interface BaiduFeignClient {

    @GetMapping("")
    String getIndex();
}

这种方法不是调用注册中心里的服务,显然不能使用Ribbon负载均衡。

三、扩展

1.配置Feign的超时时间
public class FeignConfiguration {
    @Bean
    public Request.Options options() {
        //第一次参数是连接超时时间,第二个参数是读取超时时间,单位都是ms
        return new Request.Options(5000, 10000);
    }
}
2.feign还包含了编码器和解码器、契约的功能,这里不展开。
3.feign接口可以抽取出来单独作为一个model,然后在服务提供者和服务消费者中引入,服务消费者可以直接调用,而服务提供者只需要实现改接口,就能被消费者调用。官方文档不建议这样,实际上这样做是加强了耦合度。
4.多参数请求构造,建议还是使用Spring MVC的@RequstParam和@RequstBody
5.优化feign的性能,可以通过设置它的连接池,通过压测得到最合适的连接数;也可以通过设置日志级别,尽量打印少量的日志。

设置feign的调用客户端和连接池

(1)引入http client

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

(2)编辑配置文件

feign:
  httpclient:
    # 让feign使用apache httpclient做请求,而不是默认的urlconnection
    enabled: true
    # feign的最大连接数
    max-connections: 200
    # feign单个路径最大连接数
    max-connections-per-route: 50

四、和RestTemplate对比

在这里插入图片描述

五、OpenFeign和Ribbon的超时重试

这个重试是指客户端发现远程服务不可达后的重试机制,而不是说远程服务异常去重试。

OpenFeign底层依赖Ribbon,但是OpenFeign和Ribbon都提供了相互独立的重试机制,也就是其实可以有两套重试规则。

默认的,OpenFeign自己的重试机制默认是Retryer.NERVER_RETRY,也就是不重试。最多只启用Ribbon的重试机制,否则,两个重试机制可能会有冲突

如果要启用Ribbon的重试机制,需要单独引入包

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>${spring.retry.version}</version>
</dependency>

Ribbon的重试机制:

1.如果OkToRetryOnAllOperations属性设置为true,那么只要发现服务不可达,就会重试。

2.如果OkToRetryOnAllOperations属性设置为fasle,假如是非GET请求,只有在出现连接错误(connectErrors)的时候才会进行重试;假如是GET请求,只要发现服务不可达,就会重试。

所以,使用Ribbon一定要严格遵循Restful接口的幂等性规则,因为不管你是否启用OkToRetryOnAllOperations都可能进行Ribbon重试。同时,为了减少错误发生的可能性,强烈建议设置ribbon.OkToRetryOnAllOperations=false

两套重试机制OpenFeign和Ribbon都有自己的超时时间,在OpenFeign中使用Ribbon的重试机制只需要设置OpenFeign的重试时间就能让Ribbon的重试机制使用该配置生效。

因此,在使用OpenFeign时,参考以下配置:

# Ribbon重试机制相关配置
ribbon:
  # 任意连接不可达的情况是否重试
  OkToRetryOnAllOperations: false
  # 同一台实例最大重试次数,首次调用不算重试,默认是0次
  MaxAutoRetries: 0
  # 其他实例最大重试实例数,默认是1次
  MaxAutoRetriesNextServer: 1
# Feign重试机制相关配置
feign:
  client:
    config:
    # default为全局配置,如果需要单独为某个服务配置,则将default改为服务名称
    default:
      # 连接超时时长,默认10s
      connectTimeout: 10000
      # 读取数据超时时长,默认60s
      readTimeout: 60000

所以最大重试次数是1+MaxAutoRetries+MaxAutoRetriesNextServer+MaxAutoRetries*MaxAutoRetriesNextServer

如果使用了熔断器,熔断器的超时时间应该要大于(Ribbon的ConnectTimeount时间+ReadTimeout时间)*N,N是Ribbon调用次数,以保证在Ribbon请求结束之前不会因为超时触发熔断器熔断,否则Ribbon还没请求结束就发生了超时熔断,Ribbon的重试机制就无效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值