文章目录
- 什么是 OpenFegin
- 0penFeign 与 Ribbon.
- 对 consumer 的改造
- 超时配置
- 请求响应的压缩设置
- 选择远程调用的底层实现技术
- OpenFegin 整合 LoadBalancer 负载均衡
- 负载均衡策略的更换
- 小结
前面消费者对于微服务的消费是通过 RestTemplate 完成的,这种方式的弊端是很明显的:消费者对提供者的调用无法与业务接口完全吻合。
例如,原本Service 接口中的方法是有返回值的,但经过 RestTemplate 相关API调用后没有了其返回值,最终执行是否成功用户并不清楚。
再例如 RestTemplate 的对数据的删除与修改操作方法都没有返回值。
代码编写不方便,不直观。提供者原本是按照业务接口提供服务的,而经过 RestTemplate一转手,变为了 URL,使得程序员在编写消费者对提供者的调用代码时,变得不直接、不明了。没有直接通过业务接口调用方便、清晰。
什么是 OpenFegin
- 声明式 REST 客户端:Feign 通过使用 JAX-RS(JavaApieXtensionsofRESTful webServivces)或 SpringMVc 注解的修饰方式,生成接口的动态实现。”
- Feign,假装、伪装。openFeign 可以将提供者提供的 Restful服务伪装为接口进行消费,消费者只需使用“feign 接口 + 注解”的方式即可直接调用提供者提供的 Restful 服务而无需再使用 RestTemplate。
- 对于 openFeign,可简单总结为以下几点:OpenFeign 只涉及 Consumer,与Provider 无关。因为其是用于 Consumer 调用 Provider的
- OpenFeign 仅仅就是一个伪客户端,其不会对请求做任务的处理。
- OpenFeign 是通过注解的方式实现 RESTful 请求的。
0penFeign 与 Ribbon.
OpenFeign 具有负载均衡功能,其可以对指定的微服务采用负载均衡方式进行消费、访问。之前老版本 Springcloud 所集成的 OpenFeign 默认采用了 Ribbon 负载均衡器。但由于Netflix 已不再维护 Ribbon,所以从 Springcloud2021.x开始集成的 OpenFeign 中已彻底丢弃Ribbon,而是采用 SpringCloud 自行研发的 SpringCloud Loadbalancer 作为负载均衡器
对 consumer 的改造
- SpringCloud 2021.x 版本不在使用 Ribbon,需要额外引入 SpringCloud-Loadbalancer 依赖
<!--openfegin依赖-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 新增 service 接口
/*** ProjectName: springcloudalibaba* ClassName: DepartService* Package: com.cheese.service* Description: openFegin 伪客户端接口* Datetime: 2024-07-23 1:12* Author: LJZ*/
@FeignClient(value = "depart-provider", path = "/provider/depart") //微服务名称,uri
public interface DepartService {/*** 接口名,注解路径,所有方法名与provider-server 中的接口一致* @param depart* @return*///新增@PostMapping("/save")Boolean addDepart(@RequestBody DepartEntity depart);//修改@PutMapping("/update")Boolean updateDepart(@RequestBody DepartEntity depart);//删除@DeleteMapping("/del/{id}")Boolean deleteDepartById(@PathVariable Integer id);//查询@GetMapping("/get/{id}")DepartEntity getDepartById(@PathVariable Integer id);//列表@GetMapping("/list")List<DepartEntity> getAllDepart();
}
//SpringCloud2021.x前后版本的openfegin使用差异
//旧版本
@FeignClient(value = "depart-provider", path = "/provider/depart") //微服务名称,uri
或是
@FeignClient(value = "depart-provider") //微服务名称,uri
@RequestMapping("/provider/depart")
//两种方式均可
//-----------------------------------------
//新版本只能使用第一种方式进行注解配置
- DepartController 中调用的 service 与接口方法命保持一致
@Resourceprivate DepartService departService;//新增@PostMapping("/")public Boolean addDepart(@RequestBody DepartEntity depart) {return departService.addDepart(depart);}//修改@PutMapping("/")public Boolean modifyDepart(@RequestBody DepartEntity depart) {return departService.updateDepart(depart);}//删除@DeleteMapping("/{id}")public Boolean deleteDepart(@PathVariable Integer id) {return departService.deleteDepartById(id);}//查询@GetMapping("/{id}")public DepartEntity getDepart(@PathVariable Integer id) {return departService.getDepartById(id);}//列表@GetMapping("/list")public List<DepartEntity> getDepartList() {return departService.getAllDepart();}
- 启动类上新增注解
@EnableFeignClients //开启OpenFeginClient
- 启动 nacos, 启动 consumer 启动 provider,使用 consumer,openfegin 调用 provider
超时配置
- 在 consumer 的 yaml 配置文件中做如下配置
spring:cloud:# OpenFegin 超时配置openfeign:client:config:default: #全局设置#consumer与provider建立连接的超时时间<==取决于网络因素connect-timeout: 1#建立连接后的读取时间,consumer发出请求到provider的响应这段时间的阈值<==取决于provider的业务逻辑read-timeout: 1depart-provider: #指定微服务设置,优先于全局设置,feginName即,@FeginClient注解value的值connect-timeout: 1read-timeout: 2
- 使用全局设置时(将下方的 depart-provider 进行注释),重启 consumer,预期结果超时时间 1ms 出现 timeout 现象较多
- 指定 feginName 方式(将注解放开),重启 consumer
- 有时能够访问到,由于 read-timeout 比原先的的 default 设置的比较大,符合预期
请求响应的压缩设置
spring:cloud:#对请求响应的压缩设置compression:request:#开启压缩配置enabled: true#指定类型mime-types: ["text/xml", "application/xml", "application/json","video/mp4"]#最小请求大小,默认值2048min-request-size: 1024response:enabled: true
选择远程调用的底层实现技术
- feign 的远程调用底层实现技术默认采用的是 JDK的 URLConnection,同时还支持HttpClient 与OkHttp。.
- 由于 JDK 的 URLConnection 不支持连接池,通信效率很低,所以生产中是不会使用该默认实现的。所以在 Spring cloud OpenFeign 中直接将默认实现变为了 Htpclient,同时也支持OkHttp。
- 用户可根据业务需求选择要使用的远程调用底层实现技术。”
OpenFegin 整合 LoadBalancer 负载均衡
- 紧接上文,现在已经有了一个 provider8081,如何使用 springcloud 负载均衡呢?查阅官网
- 简而言之,想要使用 OpenFegin 客户端负载均衡,必须引入
spring-cloud-starter-loadbalancer
依赖,如果不引入依赖也能够使用默认的 feginclient,但是就不会有负载均衡的功能 - 引入依赖
<!--nacos2.2.0.1往后版本的客户端负载均衡依赖-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
- 使用 idea 动态参数构建 provider8082,provider8083
- 可以看到 consumer 已经具备负载均衡功能了,默认负载均衡策略为轮询方式
负载均衡策略的更换
- 新增一个配置类
DepartConfig.java
,用于配置负载均衡策略
/*** ProjectName: springcloudalibaba* ClassName: DepartConfig* Package: com.cheese.config* Description: 用于修改负载均衡策略* Datetime: 2024-07-30 1:21* Author: LJZ*/
public class DepartConfig {@Beanpublic ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory factory) {//获取负载均衡客户端名称,即提供者服务名称String serverName = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);//获取提供者微服务名称可用的实例列表ObjectProvider<ServiceInstanceListSupplier> lazyProvider = factory.getLazyProvider(serverName, ServiceInstanceListSupplier.class);//从集合lazyProvider中获取指定serverName的实例,随机做负载均衡return new RandomLoadBalancer(lazyProvider, serverName);}
}
- 在 DepartConfig 类中未见
@Configuration
注解,在启动类中需添加@LoadBalancerClients(defaultConfiguration = DepartConfig.class)
- 重启 consumer8080
小结
spring-cloud-loadbalancer 存在以下弊端
- 负载均衡策略较少
- 仅支持轮询和随机策略,默认是轮询策略
- 更换负载均衡策略方式较为麻烦
- 生产环境下使用的负载均衡器,通常是 dubbo
- dubbo 作为通讯客户端,负载均衡策略可供选择更加多样
- 无论是 openfegin 还是 resttemplate 建立通讯方式均是基于 http 协议进行
- http 协议效率较低,生产环境下使用远程过程调用协议 RPC 效率会更高
- 基于 RPC 通讯协议的框架恰好就有
dubbo
,此外还有gRPC
等