服务调用OpenFeign
1、介绍
①什么是OpenFeign
OpenFeign是在Feign的基础上进行了加强
使用在Client-Consuemr(消费者客户端)
Fiegn是一个声明式的Web服务客户端,让编写Web服务客户端非常容易,只需要创建一个接口并且在接口上添加注解即可
OpenFeign底层使用的是Ribbon做负载均衡的
②为什么需要OpenFeign
原因:
我们之前写restTemplate很麻烦,每个Controller都需要注入RestTemplate,需要手写Provider的Url,在多次复用的时候也需要反复编写,或者需要封装
在前面我们使用Ribbon+RestTemplate时,使用RestTemplate对Http请求进行封装。形成一套模板化的调用方法。但是在实际的开发中,由于对服务依赖的调用可能不止一处。一个接口会被多次调用,所以通常对每个微服务自行封装一些客户端来包装这些依赖服务的调用。
Feign在这个基础上做了进一步的封装,通过Feign我们能够定义和实现依赖服务接口的定义。
在Feign的实现下,我们只需要创建一个接口并使用注释的方式来配置他(以前是Dao接口标注Mapper,现在是一个微服务接口上标注一个Feign注解就行了)
这样就完成了对Provider提供的接口的绑定,简化我们使用RestTemplate手写url等的麻烦。
③Feign和OpenFeign
2、搭建
1.新建子模块cloud-consumer-feign-order80
2.pom.xml:
<dependencies> <!-- openfeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- eureka-client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- 引用自己定义的api通用包,可以使用Payment支付Entity --> <dependency> <groupId>cn.zko0.cloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <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> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
3.yml:
注意这里,rigister-with-eureka为false,不将自己注册进eureka,但是它是可以发现到eureka上的provider服务的
server: port: 80 eureka: client: register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
4.启动类:
@EnableFeignClients //激活feign @SpringBootApplication public class OrderFeignMain80 { public static void main(String[] args) { SpringApplication.run(OrderFeignMain80.class, args); } }
5.新建Provider提供相关服务的接口
新建service包(可以体现,使用OpenFeign就像使用本地的Service一样,能够结合SpringMVC)
可以看到,在PaymentController中存在一个接口为getPaymentById。我们使用Feign来让Service调用provider的这个接口,作为service提供给该项目的controller
@Component //Feign去 @FeignClient(value = "CLOUD-PAYMENT-SERVICE") public interface PaymentFeignService { @GetMapping("/payment/get/{id}") public CommonResult getPaymentById(@PathVariable("id") Long id); }
6.在controller中注入这个feign的service,远程调用provider的接口
@Slf4j @RestController public class OrderFeignController { @Resource private PaymentFeignService paymentFeignService; @GetMapping("/consumer/payment/get/{id}") public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){ return paymentFeignService.getPaymentById(id); } }
7.调用测试:成功!
3、超时控制
①超时错误现象
设置provider休眠3s:
@GetMapping("/payment/feign/timeout") public String paymentFeignTimeOut(){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } return port; }
在Order消费者出定义该接口:
在消费者中,openfrign-ribbon,客户端一般默认是等待1s
@Component //Feign去 @FeignClient(value = "CLOUD-PAYMENT-SERVICE") public interface PaymentFeignService { @GetMapping("/payment/get/{id}") public CommonResult getPaymentById(@PathVariable("id") Long id); //在消费者中,openfrign-ribbon,客户端一般默认是等待1s @GetMapping("/payment/feign/timeout") public String paymentFeignTimeOut(); }
在消费者Controller中,使用service这个该方法:
@GetMapping("/consumer/payment/feign/timeout") public String paymetFeignTimeout(){ //openfeign-ribbon,客户端一般默认等待1s return paymentFeignService.paymentFeignTimeOut(); }
启动测试:
feign超过1s报错
②修改等待时间
openFeign最底层使用ribbon实现负载均衡
修改consumer的yml:
#没提示不管它,可以设置 ribbon: #指的是建立连接后从服务器读取到可用资源所用的时间 ReadTimeout: 5000 #指的是建立连接使用的时间,适用于网络状况正常的情况下,两端连接所用的时间 ConnectTimeout: 5000
测试:
超过3s依然能够调用:
4、日志打印功能
Feign提供日志打印功能,可以通过配置调整日志级别,从而了解Feign中Http请求的细节。
即对Feign接口的调用情况进行监控和输出
①日志级别
- NONE :默认,不显示日志
- BASIC :仅记录请求的方法,URL,响应状态码还有执行时间
- HEADER :除了BASIC中定义的信息外,还有请求和响应的头信息
- FULL :除了HEADER中定义的信息外,还有请求和响应的正文以及元数据
②日志配置
1.配置日志Bean
在springclou包下新建FeignLoggerConfig配置类
@Configuration public class FeignLoggerConfig { @Bean Logger.Level feignLoggerLevel(){ //打印最详细的日志 return Logger.Level.FULL; } }
2.添加yml:
#开启日志的feign客户端 logging: level: #feign日志以什么级别监控哪个接口 cn.zko0.springcloud.service.PaymentFeignService: debug
3.测试
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!