OpenFeign、Ribbon

警告
本文最后更新于 2024-01-08,文中内容可能已过时。

微服务同步调用核心链路。Ribbon负责客户端负载均衡,OpenFeign负责声明式远程调用。

一、微服务调用基础概念

1、调用层级关系(链路)

服务消费者 → LoadBalancer(SpringCloud内置) / Ribbon → OpenFeign → HTTP请求 → 服务提供者

2、核心区别 🟠

  • Ribbon:客户端负载均衡组件,负责挑选服务实例。

  • OpenFeign:声明式HTTP调用框架,封装请求、简化编码。

一句话总结:Feign负责发请求,Ribbon负责选机器。

二、Ribbon 负载均衡

1、负载均衡分类

(1)服务端负载均衡(Nginx)

请求统一发给中间件,由Nginx转发;集中式负载,有单点瓶颈。

(2)客户端负载均衡(Ribbon)

消费者本地维护服务列表,本地直接算法挑选实例,无中间转发、性能更高。

2、Ribbon 七大内置负载均衡策略

策略类名 策略名称 底层原理 生产使用
RoundRobinRule 轮询(默认) 按顺序依次分发请求 通用、最常用
RandomRule 随机 随机挑选实例 极少用
WeightedResponseTimeRule 响应时间权重 响应越快权重越高,分配更多流量 生产推荐
BestAvailableRule 最小并发 挑选当前请求最少、压力最小节点 高并发服务
AvailabilityFilteringRule 可用性过滤 剔除熔断、故障节点,再轮询 容错项目
ZoneAvoidanceRule 区域规避 优先同机房、过滤故障区域 集群多机房
RetryRule 重试策略 失败后重试其他节点 弱网不稳定环境

3、Ribbon 淘汰说明 🔴

  • SpringCloud 2020 之后 剔除 Ribbon

  • 官方替换为 Spring Cloud LoadBalancer

  • 但是 OpenFeign 默认依然兼容 Ribbon,企业老项目大量存在

新版本用LoadBalancer,旧版本默认Ribbon,算法逻辑基本一致。

4、Ribbon 核心执行流程

  1. 从注册中心拉取服务实例列表,本地缓存

  2. 负载均衡器筛选可用实例(剔除不健康节点)

  3. 根据负载均衡算法选出目标实例

  4. 将IP+端口交给Feign发起HTTP调用

三、OpenFeign 核心原理 🔴

1、Feign 是什么?

OpenFeign 是 声明式、模板化 HTTP 远程调用框架,基于接口注解,无需手动拼接URL、无需RestTemplate。

2、Feign 核心优势

  • 接口式编程、代码极简、可读性极强

  • 内置Ribbon负载均衡(老版本)

  • 内置重试、超时、拦截器

  • 适配SpringMVC注解,学习成本极低

3、动态代理原理 🔴

(1)核心流程

  1. @EnableFeignClients 开启扫描

  2. 扫描所有 @FeignClient 标记接口

  3. Feign 内置 JDK动态代理 生成接口代理对象

  4. 代理对象拦截接口方法,解析注解、URL、请求头、参数

  5. 封装HTTP请求,通过底层Client发送请求

(2)总结

OpenFeign 基于 JDK 动态代理,在启动时为Feign接口生成代理类,拦截方法调用,解析注解封装HTTP请求,底层借助Ribbon挑选实例,完成远程调用。

4、Feign 底层通信客户端 🔴

  • 默认:JDK原生URLConnection(无连接池、性能差)

  • 生产优化:替换Apache HttpClient / OKHttp,开启连接池、复用连接


四、Feign 生产必备配置(超时、重试、请求透传)

1、超时时间配置(大坑) 🟠

(1)双层超时机制

  • Ribbon超时:连接超时、读取超时(外层)

  • Feign超时:内层请求超时

优先级:Feign超时 < Ribbon超时,必须Ribbon设置更大,否则不生效。

2、请求头Header透传(生产刚需)

(1)业务场景

微服务登录认证、Token、用户上下文、链路追踪ID需要向下游传递。

(2)实现方式

自定义Feign拦截器,拦截请求,从ThreadLocal获取上下文,把Header全部放入下游请求。

(3)注意坑点

Feign内部请求会清空原有Header,不手动拦截透传,下游拿不到Token

3、编码、日志、压缩配置

  • 日志级别:生产仅保留Basic,避免日志爆炸

  • 请求响应压缩:减少带宽、提升传输速度

  • 编码格式统一UTF-8,防止乱码


五、Feign 完整调用流程 🔴

  1. 消费者调用Feign接口方法;

  2. JDK动态代理拦截方法,解析接口上的请求注解、请求参数、请求头;

  3. 将Java方法封装为标准HTTP请求报文;

  4. 将请求交给Ribbon负载均衡组件;

  5. Ribbon从本地服务列表筛选健康实例,按照算法选出目标服务;

  6. 底层HTTP客户端(OKHttp/URLConnection)发起TCP请求;

  7. 服务提供者接收请求,执行接口逻辑;

  8. 响应结果原路返回,Feign自动反序列化为Java对象;

  9. 结束远程调用。

六、高频易错坑点(高级开发必避坑)

1、超时坑

Feign超时时间必须 小于 Ribbon超时,否则Feign配置失效。

2、请求头丢失坑

Feign默认清空Header,必须手动写拦截器透传Token。

3、GET传POJO坑

Feign GET请求不能直接传实体类,需要拆分参数或自定义解码器。

4、熔断降级坑

新版本Feign默认关闭熔断,需要手动开启Sentinel熔断。

5、连接池坑

默认URLConnection无连接池,高并发必须替换OKHttp。


七、总结 🔴

  1. Ribbon是客户端负载均衡,本地缓存服务列表、算法挑选实例,性能优于Nginx;

  2. OpenFeign基于JDK动态代理,简化远程调用、屏蔽HTTP底层;

  3. 生产环境必须优化:连接池、超时配置、请求透传、日志级别;

  4. 新版本SpringCloud放弃Ribbon,改用LoadBalancer,原理一致。

Feign代理发请求,Ribbon挑选机器;

拦截器传Token,双层超时要注意;

默认无池性能低,生产必须换HttpClient。