Feign
Feign的设计图
Feign支持同步和异步模型
Feign调用流程
- 发起请求
- target动态代理对象(根据接口生成代理对象)
HardCodedTarget 默认Target,不做任何处理。LoadBalancingTarget 使用Ribbon进行客户端路由
- 契约选择:选择使用哪个类型的注解(SpringMVC的还是Feign的) MethodHander就是反射的调用
有一个接口是
Target
,他有一个实现是HardCodedTarget
Contract的作用是解析接口方法,生成Rest定义。feign默认使用自己的定义的注解,还提供了JAXRSContract javax.ws.rs注解接口实现SpringContract是spring cloud提供SpringMVC注解实现方式
- encoder:将实体对象转换成HTTP请求的消息正文,并写到Request中。decode:从Response中提取HTTP消息正文,通过接口类声明的返回类型,消息自动装配。Feign自动处理请求和响应的序列化与反序列化。默认情况下,Feign使用了Spring MVC的
HttpMessageConverters
来序列化请求体和反序列化响应体。如果需要,可以自定义这些转换器来处理特定的数据格式。
Encoder:默认编码器,只能处理String和byte[];json编码器GsonEncoder、JacksonEncoder;XML编码器JAXBEncoder
Decoder:json解码器 GsonDecoder、JacksonDecoder;XML解码器 JAXBDecoder;Stream流解码器 StreamDecoder
- 拦截器,拦截和修改HTTP请求和响应,也可以压缩请求的组件。(拦截请求和响应,并对其进一步处理)。
例如添加通用的请求头(认证令牌)、日志记录、请求参数修改和错误处理等。 如:RequestInterceptor.调用客户端发请求前,修改RequestTemplate,比如为所有请求添加Header就可以用拦截器实现
- 日志记录 在发送和接受请求的时候,Feign定义了统一的日志记录。
级别 | 说明 |
---|---|
NONE | 不做任何记录 |
BASIC | 只记录输出Http 方法名称、请求URL、返回状态码和执行时间 |
HEADERS | 记录输出Http 方法名称、请求URL、返回状态码和执行时间 和 Header 信息 |
FULL | 记录Request 和Response的Header,Body和一些请求元数据 |
- Client 发送请求和重试
CLient:Client.Default 使用java api的HttpClientConnection发送http请求; ApacheHttpClient 使用apache的Http客户端发送请求; OkHttpClient 使用OKHttp客户端发送请求;RibbonClient 使用Ribbon进行客户端路由.
Retryer:默认的策略是Retryer.Default,包含3个参数:间隔、最大间隔和重试次数,第一次失败重试前会sleep输入的间隔时间的,后面每次重试sleep时间是前一次的1.5倍,超过最大时间或者最大重试次数就失败
三种HTTP连接客户端的对比
-
Java 原生的 HttpURLConnection
优点
- 无额外依赖:使用 JDK 自带的 HTTP 客户端,无需添加额外的库和依赖。
- 简单直接:适合简单的 HTTP 请求场景。
缺点
- 不存在连接池:每次发送请求的时候都会创建新的HttpURLConnection连接,性能相对较差.
-
Apache HttpClient
优点
- 丰富的功能:Apache HttpClient 提供了丰富的 HTTP 功能,如连接池管理、超时设置、代理支持、重定向处理和身份验证等。
- 高度可配置:允许详细配置 HTTP 请求和连接管理。
缺点
-
依赖较多:相比其他客户端,Apache HttpClient 需要更多的依赖库。
-
性能一般:虽然功能强大,但在某些场景下性能可能不如 OkHttp
-
OkHttp
优点
-
高性能:OkHttp 以高性能著称,特别是在处理大并发请求时表现优秀。
-
轻量级:相比 Apache HttpClient,OkHttp 更加轻量级,依赖较少。
-
现代特性:支持 HTTP/2、WebSocket 等现代协议和特性。
-
易用性强:API 设计简洁易用。
缺点
- 功能相对较少:虽然功能足够应对大多数场景,但某些高级特性不如 Apache HttpClient 丰富。
-
Feign在SpringCloud中工作流程
在配置了服务发现的情况下,Feign会与Ribbon结合,使用Ribbon的负载均衡功能来选择一个可用的服务实例进行调用.
Ribbon组件实现负载均衡原理 原理:根据调用服务id去服务注册中心获取对应服务id的服务列表,并将服务列表拉取本地进行缓存,然后在本地通过默认的轮询负载均衡策略在现有列表中选择一个可用节点提供服务
Ribbon 是一个客户端负载均衡器,它与 Feign 集成使用时,可以在微服务之间实现透明的负载均衡。在 Feign 中,Ribbon 负责从多个服务实例中选择一个适合的实例进行调用。Ribbon 提供了多种负载均衡策略.
Ribbon 提供了几种常见的负载均衡策略:
- Round Robin:轮询策略,按顺序循环选择每一个服务实例。
- Random:随机策略,随机选择一个服务实例。
- Availability Filtering:可用性过滤策略,过滤掉故障实例和并发连接数超过阈值的实例,然后对剩余实例进行轮询。
- Weighted Response Time:加权响应时间策略,根据每个实例的平均响应时间分配权重,响应时间越短的实例权重越高,被选择的概率越大。
- Zone Avoidance:区域避免策略,综合考虑实例所在区域的可用性和性能。
Ribbon发现服务实例
Feign 客户端在调用接口方法时,会通过 Ribbon 查找对应的服务实例。Ribbon 使用 Eureka 或者配置文件中的服务列表来发现可用的服务实例。
流程说明
(1)服务提供者注册服务到Eureka服务端;
(2)服务消费者的Eureka客户端定时从Eureka服务端获取实例列表;
(3)Ribbon定时从Eureka客户端获取对应服务的实例列表;
(4)Ribbon根据负载均衡规则获取到一个实例,然后调用这个实例的接口。
Ribbon从服务名映射到具体的服务提供者实例
- 获取到被调用服务的服务名。🌰 http://product-service/product?productId=1
- 根据从注册中心拉取过来的服务列表对应的节点信息.🌰product-service对应[192.168.10.180:8081、192.168.10.180:8083]
- 根据负载均衡策略去选择一个信息节点,将服务名称替换成对应的ip和端口。🌰http://192.168.10.180:8081/product?productId=1