CodeAshen's blog CodeAshen's blog
首页
  • Spring Framework

    • 《剖析Spring5核心原理》
    • 《Spring源码轻松学》
  • Spring Boot

    • Spring Boot 2.0深度实践
  • Spring Cloud

    • Spring Cloud
    • Spring Cloud Alibaba
  • RabbitMQ
  • RocketMQ
  • Kafka
  • MySQL8.0详解
  • Redis从入门到高可用
  • Elastic Stack
  • 操作系统
  • 计算机网络
  • 数据结构与算法
  • 云原生
  • Devops
  • 前端
  • 实用工具
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • Reference
GitHub (opens new window)

CodeAshen

后端界的小学生
首页
  • Spring Framework

    • 《剖析Spring5核心原理》
    • 《Spring源码轻松学》
  • Spring Boot

    • Spring Boot 2.0深度实践
  • Spring Cloud

    • Spring Cloud
    • Spring Cloud Alibaba
  • RabbitMQ
  • RocketMQ
  • Kafka
  • MySQL8.0详解
  • Redis从入门到高可用
  • Elastic Stack
  • 操作系统
  • 计算机网络
  • 数据结构与算法
  • 云原生
  • Devops
  • 前端
  • 实用工具
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • Reference
GitHub (opens new window)
  • 剖析Spring5核心原理

  • Spring源码轻松学

  • Spring Boot 2.0深度实践

  • Spring-Cloud

  • Spring-Cloud-Alibaba

    • 第01章-简介
    • 第02章-Nacos服务发现
    • 第03章-Ribbon负载均衡
    • 第04章-Feign声明式HTTP客户端
      • 4.1 Feign基本使用
        • 4.1.1 Feign整合
        • 4.1.2 Feign基本使用
      • 4.2 Feign组成
      • 4.3 Feign配置
        • 4.3.1 自定义Feign日志级别
        • 针对指定服务配置
        • 全局配置
        • 4.3.2 Feign支持的配置项
        • 4.3.3 Feign配置最佳实践
      • 4.4 Feign继承
      • 4.5 Feign脱离Ribbon使用
      • 4.6 Feign和RestTemplate对比
      • 4.7 Feign性能优化
      • 4.8 Feign更多参考
    • 第05章-Sentinel集群容错
    • 第06章-RocketMQ消息队列
    • 第07章-Spring Cloud Gateway网关
    • 第08章-认证授权
    • 第09章-Nacos配置管理
    • 第10章-Sletuh调用链
  • Spring
  • Spring-Cloud-Alibaba
CodeAshen
2023-02-10
目录

第04章-Feign声明式HTTP客户端

# 4.1 Feign基本使用

# 4.1.1 Feign整合

Feign是Netflix开源的声明式HTTP客户端

整合三板斧:

  1. 加依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    1
    2
    3
    4
  2. 加注解

    @SpringBootApplication
    @EnableFeignClients
    public class ContentCenterApplication {}
    
    1
    2
    3
  3. 写配置(暂时没有)

# 4.1.2 Feign基本使用

编写FeignClient接口

@FeignClient("user-center")  // 对应远程服务名称
public interface UserCenterFeignClient {
    
    @GetMapping("/users/{id}")  // 对应远程接口endpoint
    UserDTO findById(@PathVariable Integer id);
}
1
2
3
4
5
6

使用自动生成的实现类调用远程服务

@Service
public class ShareService {
    // 注入FeignClient
    @Autowired
    private UserCenterFeignClient userCenterFeignClient;
    
    public ShareDTO findById(Integer id) {
        // ...
        // 使用FeignClient直接调用
        UserDTO userDTO = userCenterFeignClient.findById(userId);
        // ....
        return shareDTO;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 4.2 Feign组成

接口 作用 默认值
Feign.Builder Feign的入口 Feign.Builder
Client Feign底层用什么去请求 和Ribbon配合时:LoadBalancerFeignClient
不和Ribbon配合时:feign.Client.Default
Contract 契约,注解支持 SpringMvcContract
Encoder 编码器,用于将对象转换成HTTP请求消息体 SpringEncoder
Decoder 解码器,将响应消息体转换成对象 ResponseEntityDecoder
Logger 日志管理器 SIf4jLogger
Requestinterceptor 用于为每个请求添加通用逻辑 无

# 4.3 Feign配置

# 4.3.1 自定义Feign日志级别

级别 打印内容
NONE(默认值 不记录任何日志
BASIC 仅记录请求方法、URL、响应状态代码以及执行时间
HEADERS 记录BASIC级别的基础上,记录请求和响应的header
FULL 记录请求和响应的header、body和元数据

# 针对指定服务配置

方式一、Java代码配置方式

编写配置类

/**
 * Feign的配置类
 * 这个类别加@Configuration注解,否则必须挪到@ComponentScan包扫描以外,
 * 不然会有父子上下文问题,变成全局配置
 */
public class UserCenterFeignConfig {
    
    @Bean
    public Logger.Level level() {
        // 让Feign打印所有日志细节
        return Logger.Level.FULL;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

FeignClient引入配置类

@FeignClient(name = "user-center", configuration = UserCenterFeignConfig.class)  // 对应远程服务名称
public interface UserCenterFeignClient {}
1
2

配置文件添加日志级别,这个是必须的,无论Java代码方式还是注解方式

logging:
  level:
    com.lucifer.contentcenter.feignclient.UserCenterFeignClient: debug
1
2
3

方式二、配置文件方式

# 配置日志级别
logging:
  level:
    com.lucifer.contentcenter.feignclient.UserCenterFeignClient: debug

# feign配置
feign:
  client:
    config: 
      # 想要调用的微服务名称
      user-center:
        loggerLevel: full
1
2
3
4
5
6
7
8
9
10
11
12

# 全局配置

方式一、Java代码配置方式

代码方式又分为以下两种:

  • 让父子上下文CemponentScan重叠(强烈不建议使用)

  • 启动类上的注解配置属性:@EnableFeignClients(defaultConfiguration=xxx.class)

    // 启动类
    @SpringBootApplication
    @EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)
    public class ContentCenterApplication {}
    
    // 配置类
    public class DefaultFeignConfig {
        @Bean
        public Logger.Level level() {
            return Logger.Level.FULL;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

方式二、配置文件方式

# 配置日志级别
logging:
  level:
    com.lucifer.contentcenter.feignclient.UserCenterFeignClient: debug

# feign配置
feign:
  client:
    config: 
      default:
        loggerLevel: full
1
2
3
4
5
6
7
8
9
10
11

# 4.3.2 Feign支持的配置项

代码方式支持的配置:

配置项 作用
Logger.Level 指定日志级别
Retryer 指定重试策略
ErrorDecoder 指定错误解码器
Request.Options 超时时间
Collection 拦截器
SetterFactory 用于设置Hystrix的配置属性,Feign整合Hystrix才会用

属性方式支持的配置:

feign.client.config:
  <feignName>:
    connectTimeout: 5000   #连接超时时间 
    readTimeout: 5000      #读取超时时间 
    1oggerLeve1: ful1      #日志级别 
    errorDecoder: com.examp1e.SimpleErrorDecoder #错误解码器 
    retryer: com.example.simpleRetryer           #重试策略 
    requestInterceptors:
      -com.example.FooRequestInterceptor         #拦截器   
    #是否对404错误码解码 
    #处理逻辑详见feign.SynchronousMethodHandler#executeAndDecode 
    decode404: false 
    encoder: com.example.SimpleEncoder    #编码器 
    decoder: com.example.SimpleDecoder    #解码器 
    contract: com.example.SimpleContract  #契约
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 4.3.3 Feign配置最佳实践

Ribbon和Feign配置对比:

image-20210220170423735

Feign代码和属性配置方式对比:

配置方式 优点 缺点
代码配置 基于代码,更加灵活 如果Feign的配置类加了Configuration注解,需注意父子上下文
线上修改得重新打包、发布
属性配置 易上手
配置更加直观
线上修改无需重新打包、发布
优先级更高
极端场景下没有代码配置方式灵活

最佳实践:

  • 尽量使用属性配置,属性方式实现不了的情况下再考虑用代码配置
  • 在同一个微服务内尽量保持单一性,比如统一使用属性配置,不要两种方式混用,增加定位代码的复杂性

# 4.4 Feign继承

FeignClient注解所在的接口和远程服务的Controller极度相似,可以抽象出一个接口,放在一个独立maven模板,服务提供者和消费者都引入该模块。服务提供者Controller实现该接口,服务消费者的FeignClient接口继承该接口。这样就可以实现代码重用,且修改后不用多处修改。

虽然Feign有该特性,但是Spring官方不推荐这样使用,因为官方认为微服务之间应该相互独立,不应该这样耦合。

但是该方式在业界很流行,使用时权衡利弊即可。

# 4.5 Feign脱离Ribbon使用

模拟使用FeignClient访问百度

@FeignClient(name = "baidu", url = "http://www.baidu.com")
public interface BaiduFeignClient {
    @GetMapping("")
    String index();
}
1
2
3
4
5

# 4.6 Feign和RestTemplate对比

角度 RestTemplate Feign
可读性、可维护性 一般 极佳
开发体验 欠佳 极佳
性能 很好 中等(RestTemplate的50%左右)
灵活性 极佳 中等(内置功能可满足绝大多数需求)

# 4.7 Feign性能优化

Feign默认使用URLConnection发起请求,不支持连接池,可以配置让Feign底层使用OKHttp或Apache HttpClient,它们是支持连接池的。

以Apache HttpClient为例,配置如下:

  1. 加依赖

    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-httpclient</artifactId>
    </dependency>
    
    1
    2
    3
    4
  2. 写配置

    feign:
      httpclient:
        # 让feign底层使用apache httpclient,而不是默认的URLConnection
        enabled: true
        # feign最大连接数
        max-connections: 200
        # feign单个路径最大连接数
        max-connections-per-route: 50
    
    1
    2
    3
    4
    5
    6
    7
    8

还可以通过为Feign配置合适的日志级别优化性能,默认的NONE肯定是最好的。

# 4.8 Feign更多参考

参考:Feign常见问题总结 (opens new window)

包括:

  • 如何使用Feign构造多参数的请求 (opens new window)

  • 使用Spring Cloud Feign上传文件 (opens new window)

  • [使用Feign实现Form表单提交](

编辑 (opens new window)
上次更新: 2023/06/04, 12:34:19
第03章-Ribbon负载均衡
第05章-Sentinel集群容错

← 第03章-Ribbon负载均衡 第05章-Sentinel集群容错→

最近更新
01
第01章-RabbitMQ导学
02-10
02
第02章-入门RabbitMQ核心概念
02-10
03
第03章-RabbitMQ高级特性
02-10
更多文章>
Theme by Vdoing | Copyright © 2020-2023 CodeAshen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式