一:前言
之前微服务之间调用使用的RestTemplate,调用比较复杂,URL需要拼接,使用不太方便Feign是SpringCloud提供的声明式的HTTP客户端,只用编写接口,就能够通过http请求实现服务的调用OpenFeign是Feign的扩展,能够支持SpringMVC的注解OpenFeign = RestTemplate + Ribbon + Hystrix
二:OpenFeign是什么
Feign是一个声明式的Web服务客户端(Web服务客户端就是Http客户端),让编写Web服务客户端变得非常容易,只需创建一个接口并在接口上添加注解即可。
cloud官网介绍Feign:Spring Cloud OpenFeign
三:OpenFeign能干什么
Java当中常见的Http客户端有很多,除了Feign,类似的还有Apache 的 HttpClient
以及OKHttp3
,还有SpringBoot自带的RestTemplate
这些都是Java当中常用的HTTP 请求工具。
什么是Http客户端?
当我们自己的后端项目中 需要 调用别的项目的接口的时候,就需要通过Http客户端来调用。在实际开发当中经常会遇到这种场景,比如微服务之间调用,除了微服务之外,可能有时候会涉及到对接一些第三方接口也需要使用到 Http客户端 来调用 第三方接口。
所有的客户端相比较,Feign更加简单一点,在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定。
四: OpenFeign的特点和优势
- 声明式的调用:使用OpenFeign,开发人员只需要定义接口并添加注解,就可以轻松地调用HTTP API,而无需手动编写HTTP请求和处理响应的代码。
- 自动序列化和反序列化:OpenFeign可以自动处理请求和响应的序列化和反序列化,无需手动转换JSON数据。
- 请求和响应拦截器:OpenFeign提供了拦截器的支持,开发人员可以在请求和响应的过程中添加自定义的逻辑。
- 整合Netflix生态系统:OpenFeign可以与Netflix的其他库(如Hystrix和Ribbon)无缝集成,提供容错和负载均衡的功能。
五:Feign和OpenFeign的区别
Feign:
Feign是SpringCloud组件中一个轻量级RESTful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
OpenFeign
OpenFeign 是SpringCloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等。OpenFeign 的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
六:OpenFeign的使用
① openFeign的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
② 编写Feign客户端接口
/**
* 调用商品服务的Feign客户端
* @FeignClient需要设置调用的服务名
*/
@FeignClient("product-service")
public interface ProductServiceFeignClient{
/**
* 调用商品id查询
* @param id
* @return
*/
@GetMapping("/product/{id}")
ResponseEntity<Product> getProductById(@PathVariable Long id);
}
③ 启动类加注解扫描feign接口@EnableFeignClients(basePackages = "com.blb.orderservice.feign")
④ 调用服务时
@Autowired
private ProductServiceFeignClient productServiceFeignClient;
//使用feign客户端调用服务
ResponseEntity<Product> entity = productServiceFeignClient.getProductById(order.getProductId());
七:Feign简介
Feign是一个声明式的Web服务客户端,它可以轻松地调用其他微服务的API。它基于注解和反射机制,可以自动生成HTTP请求和响应的代码,从而减少了手动编写HTTP客户端的工作量。
八:Feign的特点和优势
- 声明式的调用:使用Feign,开发人员只需要定义接口并添加注解,就可以轻松地调用其他微服务的API,而无需手动编写HTTP请求和处理响应的代码。
- 自动负载均衡:Feign集成了Ribbon负载均衡器,可以自动分发请求到多个实例上,提高了系统的可用性和性能。
- 整合Netflix生态系统:Feign可以与Netflix的其他库(如Hystrix和Eureka)无缝集成,提供容错和服务发现的功能。
- 支持多种协议:除了HTTP,Feign还支持使用其他协议(如HTTP2和WebSocket)进行通信。
九:Feign整合Ribbon
Feign默认整合了Ribbon实现负载均衡
-
全局配置
ribbon.属性 = 值
-
指定服务配置
服务名称.ribbon.属性 = 值
Ribbon常用配置:
-
ConnectionTimeout 连接超时
-
ReadTimeout 读取超时
-
OkToRetryOnAllOperations 对所有操作启动重试机制 true/false
-
MaxAutoRetries 最大重试次数
-
MaxAutoRetriesNextServer 最大重试下个服务器次数
① 引入相关依赖
<!-- Feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
② 在启动类上添加@EnableFeignClients
注解,启用Feign客户端功能
@SpringBootApplication
@EnableFeignClients
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
③ 在Feign客户端接口的@FeignClient
注解中使用configuration
属性指定Ribbon的配置类。
@FeignClient(name = "user-service", configuration = RibbonConfig.class)
public interface UserServiceClient {
// 定义远程服务的接口方法...
}
④ 创建Ribbon的配置类RibbonConfig
,并使用@Configuration
注解进行标记。在配置类中可以定制Ribbon的负载均衡策略等相关配置。
java
@Configuration
public class RibbonConfig {
@Bean
public IRule ribbonRule() {
return new RandomRule(); // 使用随机负载均衡策略
}
// 其他配置...
}
⑤ 最后,在需要使用Feign的地方注入Feign客户端接口,并直接调用方法即可。
@RestController
public class UserController {
@Autowired
private UserServiceClient userServiceClient;
@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
return userServiceClient.getUserById(id);
}
// 其他业务代码...
}
通过以上步骤,就可以在Feign中成功整合Ribbon来实现服务调用的负载均衡功能了。
十: Feign整合Hystrix
Feign默认整合了Hystrix的熔断机制
Feign可以单独定义类,编写降级方法
实现:
1)定义降级处理类,实现对应的FeignClient接口
2)实现接口中的方法,所有方法均为降级方法
/**
* 降级处理类
*/
@Component
public class ProductServiceFallback implements ProductServiceFeignClient {
/**
* 降级方法返回兜底数据
*/
@Override
public ResponseEntity<Product> getProductById(Long id) {
Product product = new Product(id,"降级数据", BigDecimal.valueOf(0),"测试");
return ResponseEntity.ok(product);
}
}
3)在FeignClient注解中配置降级方法处理类
@FeignClient(value = "product-service",fallback = ProductServiceFallback.class)
4)启动Feign的Hystrix特性
feign.hystrix.enabled=true
PS: 如果feign接口和降级类和服务提供者项目不是同一个项目,需要加包的扫描
@SpringBootApplication(scanBasePackages = {"com.blb.orderservice","com.blb.common"})
十一: Feign的优化配置
1. 优化连接池
Feign是基于HTTP协议,HTTP协议基于TCP协议,TCP具有三次握手四次挥手机制,频繁的创建连接比较消耗系统的资源和时间,降低系统的吞吐量。
使用连接池可以减少网络连接的创建,提高连接的使用效率,提高系统吞吐量。
Feign默认使用JDK自带的HttpURLConnection,没有连接池。可以使用HttpClient或OkHttp
使用步骤:
1)导入feign-httpclient依赖
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
2)feign.httpclient.enable=true
2. 请求压缩优化
Feign可以对网络数据进行GZIP压缩,减少网络流量,提高速度
GZIP是什么
gzip是一种数据格式,采用deflate算法为进行数据压缩;gzip是一种非常流行的文件压缩算法,在Linux平台再是平常不过了
GZIP有什么用
当gzip压缩一个纯文本文件时,大约可以减少7成以上的文件大小;从这你就可以看出压缩能力多强悍,这样一来加快了网页加载的速度,提高了用户体验。
启动压缩:
#启动请求压缩
feign.compression.request.enabled=true
#启动响应压缩
feign.compression.response.enabled=true
#设置请求压缩的多媒体类型
feign.compression.request.mime-types=text/html,application/xml,application/json
#设置请求压缩的下限 (默认2048)
feign.compression.request.min-request-size=1024
3.使用日志对连接过程进行监控
1)开启debug日志
logging.level.包名.FeignClient接口名=DEBUG
2)定义配置类,配置日志
/** Feign日志配置 */
@Configuration
public class FeignLoggerConfig {
/** 返回日志类型,NONE没有日志,BASIC基本信息(请求方法,URL,响应代码等),HEADERS(头部信息),FULL(基本+头部)*/
@Bean
public Logger.Level level(){
return Logger.Level.BASIC;
}
}
4. 超时优化
Ribbon是具有重试机制的,就是连接失败后进行重连,问题是:Hystrix的超时时间默认是小于Ribbon的超时,Hystrix会提前熔断,Ribbon无法进行重试
Feign底层设置的超时时间为一秒,时间太短了如果超时就会异常,可以添加一个线程睡眠测试一下,线程睡眠1.5秒
@Override
public User getUserById(Integer id) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new User(id, "小明1", 22);
}
浏览器报错页面
后端抛出异常
把超时时间延长配置上后重新测试,并且这次睡眠时间设置为4秒
server:
port: 9006
compression:
enabled: true #开启浏览器<----->consumer的gzip压缩
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.65.132:8848 #注册中心的地址
application:
name: feign-consumer #注册的名字
feign:
compression:
request:
enabled: true #开启feign<---->provider的gzip压缩
response:
enabled: true
client:
config:
feign-provider:
ConnectionTimeout: 5000 #请求连接的超时时间
ReadTimeout: 5000 #请求处理的超时时间
Hystrix的超时要大于Ribbon的超时
# hystrix的超时
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
# ribbon的超时
ribbon.ConnectionTimeout=1000
ribbon.ReadTimeout=3000
十二:Feign工作原理
为什么Feign只需要编写接口就能完成远程服务的调用
关键技术:
IOC
动态代理
HTTP网络连接
实现步骤:
1) 添加@EnableFeignClients后,对Feign接口进行扫描,加载FeignClient接口信息到IOC容器中
2) 使用JDK动态代理创建FeignClient接口的实现类
3) 在JDK动态代理的InvocationHandler中的invoke方法实现方法的调用,创建RequestTemplate对象
4) 将RequestTemplate对象交给负载均衡器处理,对请求进行编码,发送HTTP请求
5) 获得响应,对响应进行解码,返回数据
十三:总结
OpenFeign是一个强大而简单的工具,可以极大地简化HTTP API调用的过程。它的声明式调用方式、自动序列化和反序列化功能以及与Netflix生态系统的整合,使开发人员能够更专注于业务逻辑的实现,而无需过多关注底层的HTTP请求和响应处理。
Feign是一个强大而简单的工具,可以极大地简化微服务间的通信。它的声明式调用方式、自动负载均衡功能以及与Netflix生态系统的整合,使开发人员能够更专注于业务逻辑的实现,而无需过多关注底层的HTTP请求和响应处理。