OpenFeign、Ribbon
微服务同步调用核心链路。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 核心执行流程
-
从注册中心拉取服务实例列表,本地缓存
-
负载均衡器筛选可用实例(剔除不健康节点)
-
根据负载均衡算法选出目标实例
-
将IP+端口交给Feign发起HTTP调用
三、OpenFeign 核心原理 🔴
1、Feign 是什么?
OpenFeign 是 声明式、模板化 HTTP 远程调用框架,基于接口注解,无需手动拼接URL、无需RestTemplate。
2、Feign 核心优势
-
接口式编程、代码极简、可读性极强
-
内置Ribbon负载均衡(老版本)
-
内置重试、超时、拦截器
-
适配SpringMVC注解,学习成本极低
3、动态代理原理 🔴
(1)核心流程
-
@EnableFeignClients 开启扫描
-
扫描所有 @FeignClient 标记接口
-
Feign 内置 JDK动态代理 生成接口代理对象
-
代理对象拦截接口方法,解析注解、URL、请求头、参数
-
封装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 完整调用流程 🔴
-
消费者调用Feign接口方法;
-
JDK动态代理拦截方法,解析接口上的请求注解、请求参数、请求头;
-
将Java方法封装为标准HTTP请求报文;
-
将请求交给Ribbon负载均衡组件;
-
Ribbon从本地服务列表筛选健康实例,按照算法选出目标服务;
-
底层HTTP客户端(OKHttp/URLConnection)发起TCP请求;
-
服务提供者接收请求,执行接口逻辑;
-
响应结果原路返回,Feign自动反序列化为Java对象;
-
结束远程调用。
六、高频易错坑点(高级开发必避坑)
1、超时坑
Feign超时时间必须 小于 Ribbon超时,否则Feign配置失效。
2、请求头丢失坑
Feign默认清空Header,必须手动写拦截器透传Token。
3、GET传POJO坑
Feign GET请求不能直接传实体类,需要拆分参数或自定义解码器。
4、熔断降级坑
新版本Feign默认关闭熔断,需要手动开启Sentinel熔断。
5、连接池坑
默认URLConnection无连接池,高并发必须替换OKHttp。
七、总结 🔴
-
Ribbon是客户端负载均衡,本地缓存服务列表、算法挑选实例,性能优于Nginx;
-
OpenFeign基于JDK动态代理,简化远程调用、屏蔽HTTP底层;
-
生产环境必须优化:连接池、超时配置、请求透传、日志级别;
-
新版本SpringCloud放弃Ribbon,改用LoadBalancer,原理一致。
Feign代理发请求,Ribbon挑选机器;
拦截器传Token,双层超时要注意;
默认无池性能低,生产必须换HttpClient。