文章目录
通过百度网盘分享的文件:springcloud
链接:https://pan.baidu.com/s/1_hU27PMZb5UM8E3ZbkfRUg
提取码:msr3
官网翻译:https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/#spring-cloud-feign
github:https://github.com/spring-cloud/spring-cloud-openfeign
1 简介
- 可插拔的注解支持,包括Feign注解和JAX-RS注解
- 支持可插拔的HTTP编码器和解码器
- 支持Sentinel和它的Fallback
- 支持SpringCloudLoadBalancer的负载均衡
- 支持HTTP请求和响应的压缩
2 OpenFeign 通用步骤
服务消费者80 → 调用含有@FeignClient注解的Api服务接口 → 服务提供者(8001/8002)
2.1 建module
创建模块:cloud-consumer-feign-order80
feign在消费端使用
2.2 改POM
<dependencies>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- httpclient5-->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3</version>
</dependency>
<!-- feign-hc5-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-hc5</artifactId>
<version>13.1</version>
</dependency>
<!--SpringCloud consul discovery-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- 引入自己定义的api通用包 -->
<dependency>
<groupId>com.msr.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--web + actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--hutool-all-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!--fastjson2-->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
<!-- swagger3 调用方式 http://你的主机IP地址:5555/swagger-ui/index.html -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.3 写YML
**server:
port: 80
spring:
application:
name: cloud-consumer-openfeign-order
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}**
2.3 主启动类
修改为:MainOpenFeign80
主启动类上面配置@EnableFeignClients表示开启OpenFeign功能并激活
@SpringBootApplication
@EnableDiscoveryClient//该注解用于向使用consul为注册中心时注册服务
@EnableFeignClients//启用feign客户端,定义服务+绑定接口,以生命式的方法优雅而简单的实现服务调用
public class MainOpenFeign80 {
public static void main(String[] args) {
SpringApplication.run(MainOpenFeign80.class,args);
}
}
2.4 cloud-api-commons模块修改
2.4.1 按照架构说明进行编码准备
订单模块要去调用支付模块,订单和支付两个微服务,需要通过Api接口解耦,一般不要在订单模块写非订单相关的业务,
自己的业务自己做+其它模块走FeignApi接口调用
2.4.2 引入openfeign依赖
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.4.3 新建服务接口PayFeignApi
类添加注解:@FeignClient(value = “cloud-payment-service”)//value填写对应的服务名
并参考8001的controller层,添加方法
@FeignClient(value = "cloud-payment-service")
public interface PayFeignApi {
@PostMapping("/pay/add")
public ResultData addPay(PayDTO payDTO);
@GetMapping("/pay/get/{id}")
public ResultData getPayInfo(@PathVariable("id") Integer id);
@GetMapping("/pay/get/info")
public String mylb();
}
2.5 编写controller
cloud-consumer-feign-order80模块controller编写
创建OrderController类
@RestController
public class OrderController {
@Resource
private PayFeignApi payFeignApi;
@PostMapping(value = "/feign/pay/add")
public ResultData addOrder(@RequestBody PayDTO payDTO){
ResultData resultData = payFeignApi.addPay(payDTO);
return resultData;
}
@GetMapping(value = "feign/pay/get/{id}")
public ResultData getPayInfo(@PathVariable("id") Integer id){
System.out.println("-------支付微服务远程调用,按照id查询订单支付流水信息");
ResultData resultData = null;
try
{
System.out.println("调用开始-----: "+ DateUtil.now());
resultData = payFeignApi.getPayInfo(id);
}catch (Exception e){
e.printStackTrace();
System.out.println("调用结束-----: "+ DateUtil.now());
ResultData.fail(ReturnCodeEnum.RC500.getCode(),e.getMessage());
}
return resultData;
}
@GetMapping(value = "feign/pay/mylb")
public String mylb(){
return payFeignApi.mylb();
}
}
2.6 测试
测试是否连通
- 先启动consul服务器
- 启动服务8001
- 启动cloud-consumer-feign-order80
- 测试:http://localhost/feign/pay/get/1
测试OpenFegin默认集成了LoadBalancer
- 启动服务8002
- 测试:http://localhost/feign/pay/mylb
2.7 总结
3 OpenFeign高级特性
3.1 注意
OpenFeign版本要注意,最新版和网络上你看到的配置不一样
3.2 OpenFeign超时控制
在Spring Cloud微服务架构中,大部分公司都是利用OpenFeign进行服务间的调用,而比较简单的业务使用默认配置是不会有多大问题的,但是如果是业务比较复杂,服务要进行比较繁杂的业务计算,那后台很有可能会出现Read Timeout这个异常,因此定制化配置超时时间就有必要了
3.2.1 超时设置,故意设置超时演示出错情况,自己使坏写bug
3.2.2 服务提供方cloud-provider-payment8001故意写暂停62秒钟程序
3.2.3 服务调用方cloud-consumer-feign-order80写好捕捉超时异常
3.2.4 测试
http://localhost/feign/pay/get/1
3.2.5 结论
OpenFeign默认等待60秒钟,超过后报错
3.2.6 官网解释+配置处理
默认OpenFeign客户端等待60秒钟,但是服务端处理超过规定时间会导致Feign客户端返回报错。
为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制,默认60秒太长或者业务时间太短都不好
yml文件中开启配置:
connectTimeout 连接超时时间
readTimeout 请求处理超时时间
3.2.7 修改cloud-consumer-feign-order80的YML文件
server:
port: 80
spring:
application:
name: cloud-consumer-openfeign-order
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
default:
#连接超时时间
connectTimeout: 3000
#读取超时时间
readTimeout: 3000
3.2.8 三秒测试
3.3 OpenFeign重试机制
3.3.1 默认重试是关闭的,给了默认值
3.3.2 默认关闭重试机制,测试看看
http://localhost/feign/pay/get/1
结果,只会调用一次后就结束
3.3.3 开启Retryer功能
feign80服务新增配置类FeignConfig并修改Retryer配置
@Configuration
public class FeignConfig
{
@Bean
public Retryer myRetryer()
{
//return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的
//最大请求次数为3(1+2),初始间隔时间为100ms,重试间最大间隔时间为1s
return new Retryer.Default(100,1,3);
}
}
3.3.4 测试
测试完成耗时12秒
只有时间没有看到三次调用的过程,看后续打开日志
3.3.5 打开OpenFeign日志
1.在FeignConfig配置类里添加OpenFeign的log
日志级别:
NONE:默认的,不显示任何日志;
BASIC:仅记录请求方法、URL、响应状态码及执行时间;
HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;
FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。
@Configuration
public class FeignConfig {
@Bean
public Retryer myRetryer()
{
// return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的
//最大请求次数为3(1+2),初始间隔时间为100ms,重试间最大间隔时间为1s
return new Retryer.Default(100,1,3);
}
/**
* log日志
* @return
*/
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
2.修改yml
logging.level.com.msr.cloud.apis.PayFeignApi:debug
# feign日志以什么级别监控哪个接口
logging:
level:
com:
msr:
cloud:
apis:
PayFeignApi: debug
3.3.6 测试
再次测试就会看到三次调用
3.4 OpenFeign默认HttpClient修改
3.4.1 是什么
OpenFeign中http client
如果不做特殊配置,OpenFeign默认使用JDK自带的HttpURLConnection发送HTTP请求,
由于默认HttpURLConnection没有连接池、性能和效率比较低,如果采用默认,性能上不是最牛B的,所以加到最大。
3.4.2 如何查看
替换之前,还是按照超时报错的案例
3.4.3 替换
3.4.3.1 FeignConfig类里面将Retryer属性修改为默认
Configuration
public class FeignConfig
{
@Bean
public Retryer myRetryer()
{
return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的
}
}
3.4.3.2 POM修改
<!-- httpclient5-->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3</version>
</dependency>
<!-- feign-hc5-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-hc5</artifactId>
<version>13.1</version>
</dependency>
3.4.3.3 Apache HttpClient5 配置开启说明
# Apache HttpClient5 配置开启
spring:
cloud:
openfeign:
httpclient:
hc5:
enabled: true
3.4.3.4 YML修改
server:
port: 80
spring:
application:
name: cloud-consumer-openfeign-order
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
default:
connectTimeout: 4000 #连接超时时间
readTimeout: 4000 #读取超时时间
httpclient:
hc5:
enabled: true
#cloud-payment-service:
#connectTimeout: 4000 #连接超时时间
#readTimeout: 4000 #读取超时时间
3.4.4测试
3.5 OpenFeign请求/响应压缩
3.5.1是什么
对请求和响应进行GZIP压缩
Spring Cloud OpenFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
通过下面的两个参数设置,就能开启请求与相应的压缩功能:
spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.response.enabled=true
细粒度化设置
对请求压缩做一些更细致的设置,比如下面的配置内容指定压缩的请求数据类型并设置了请求压缩的大小下限,
只有超过这个大小的请求才会进行压缩:
spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.request.mime-types=text/xml,application/xml,application/json #触发压缩数据类型
spring.cloud.openfeign.compression.request.min-request-size=2048 #最小触发压缩的大小
3.5.2 改YML
server:
port: 80
spring:
application:
name: cloud-consumer-openfeign-order
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
prefer-ip-address: true #优先使用服务ip进行注册
service-name: ${spring.application.name}
openfeign:
client:
config:
default:
#cloud-payment-service:
#连接超时时间
connectTimeout: 4000
#读取超时时间
readTimeout: 4000
httpclient:
hc5:
enabled: true
compression:
request:
enabled: true
min-request-size: 2048 #最小触发压缩的大小
mime-types: text/xml,application/xml,application/json #触发压缩数据类型
response:
enabled: true
测试,后台日志查看
带着压缩调用
去掉压缩调用