• Spring Cloud OpenFeign


    目录

    一、OpenFeign

    1、OpenFeign能干什么

    2、OpenFeign具体使用

    3、OpenFeign超时时间控制

    3.1、超时案例演示

    3.2、设置超时控制案例演示

    4、OpenFeign日志打印

    5、Sentinel整合OpenFegin


    一、OpenFeign

            OpenFeign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求,用法其实就是编写一个接口,在接口上添加注解即可。
            可以简单理解它是借鉴Ribbon的基础之上,封装的一套服务接口+注解的方式的远程调用器。

    1、OpenFeign能干什么

            它的宗旨是在编写Java Http客户端接口的时候变得更加容易,其底层整合了Ribbon,所以也支持负载均衡
            之前我们使用Ribbon的时候,利用RestTemplate对Http请求进行封装处理,但是在实际开发中,由于对服务依赖的调用不可能就一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以OpenFeign在此基础之上做了进一步的封装,由它来帮助我们定义和实现依赖服务接口的定义,我们只需创建一个接口并使用注解的方式来配置它,即可完成对微服务提供方的接口绑定,简化Ribbon的操作。

    OpenFeign官网解释

    OpenFeign源码地址

    2、OpenFeign具体使用

            首先我们要明确使用OpenFeign是使用在消费者端去远程调用,就必须要是用FeignClient注解,来标注要调用的服务提供者名称,然后在通过一个接口来定义要调用的方法,所以我们首先新建一个Model:cloudalibaba-openfeign-consumer-8888

    需要在父级项目引入对应依赖

    1. <dependency>
    2. <groupId>org.springframework.cloudgroupId>
    3. <artifactId>spring-cloud-starter-openfeignartifactId>
    4. <version>${openfeign-version}version>
    5. dependency>

    pom

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <parent>
    5. <artifactId>cloud2021artifactId>
    6. <groupId>com.lwz.springcloudgroupId>
    7. <version>1.0-SNAPSHOTversion>
    8. parent>
    9. <modelVersion>4.0.0modelVersion>
    10. <artifactId>cloudalibaba-openfeign-consumer-8888artifactId>
    11. <dependencies>
    12. <dependency>
    13. <groupId>org.springframework.bootgroupId>
    14. <artifactId>spring-boot-starter-webartifactId>
    15. dependency>
    16. <dependency>
    17. <groupId>org.springframework.bootgroupId>
    18. <artifactId>spring-boot-starter-actuatorartifactId>
    19. dependency>
    20. <dependency>
    21. <groupId>org.springframework.bootgroupId>
    22. <artifactId>spring-boot-devtoolsartifactId>
    23. <scope>runtimescope>
    24. <optional>trueoptional>
    25. dependency>
    26. <dependency>
    27. <groupId>org.projectlombokgroupId>
    28. <artifactId>lombokartifactId>
    29. <optional>trueoptional>
    30. dependency>
    31. <dependency>
    32. <groupId>org.springframework.bootgroupId>
    33. <artifactId>spring-boot-starter-testartifactId>
    34. <scope>testscope>
    35. dependency>
    36. <dependency>
    37. <groupId>com.alibaba.cloudgroupId>
    38. <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    39. dependency>
    40. <dependency>
    41. <groupId>com.lwz.springcloudgroupId>
    42. <artifactId>cloud-api-commonsartifactId>
    43. <version>${project.version}version>
    44. dependency>
    45. <dependency>
    46. <groupId>org.springframework.cloudgroupId>
    47. <artifactId>spring-cloud-starter-openfeignartifactId>
    48. dependency>
    49. <dependency>
    50. <groupId>org.springframework.bootgroupId>
    51. <artifactId>spring-bootartifactId>
    52. dependency>
    53. dependencies>
    54. <build>
    55. <plugins>
    56. <plugin>
    57. <groupId>org.springframework.bootgroupId>
    58. <artifactId>spring-boot-maven-pluginartifactId>
    59. plugin>
    60. plugins>
    61. build>
    62. project>

    yml

    1. server:
    2. port: 8888
    3. spring:
    4. application:
    5. name: nacos-consumer-openFeign
    6. cloud:
    7. nacos:
    8. discovery:
    9. server-addr: localhost:8848

    主启动

    1. @SpringBootApplication
    2. @EnableDiscoveryClient
    3. @EnableFeignClients//添加此注解
    4. public class OpenfeignConsumer8888Application {
    5. public static void main(String[] args) {
    6. SpringApplication.run(OpenfeignConsumer8888Application.class, args);
    7. }
    8. }

    调用服务提供者对外提供接口

    这里要调用的是服务提供者9003/9004

    1. package com.lwz.cloud.service;
    2. import com.lwz.springcloud.entities.JsonResult;
    3. import org.springframework.cloud.openfeign.FeignClient;
    4. import org.springframework.stereotype.Service;
    5. import org.springframework.web.bind.annotation.GetMapping;
    6. import org.springframework.web.bind.annotation.PathVariable;
    7. /**
    8. * 此接口就是配合使用OpenFeign的接口,
    9. * 在此接口中添加@FeignClient接口同时标注
    10. * 要调用的服务端名称,同时使用与服务提供者
    11. * 方法签名一致的抽象方法来表示远程调用的
    12. * 具体内容
    13. */
    14. @Service
    15. //表示远程调用服务名称
    16. @FeignClient("nacos-provider")
    17. public interface OpenFeignService {
    18. /**
    19. * 此方法表示远程调用info/{id}接口
    20. */
    21. @GetMapping("info/{id}")
    22. public JsonResult getSql(@PathVariable("id") Long id);
    23. }

    控制器

    1. package com.lwz.cloud.controller;
    2. import com.lwz.cloud.service.OpenFeignService;
    3. import com.lwz.springcloud.entities.JsonResult;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.web.bind.annotation.GetMapping;
    6. import org.springframework.web.bind.annotation.PathVariable;
    7. import org.springframework.web.bind.annotation.RestController;
    8. @RestController
    9. public class OpenFeignController {
    10. @Autowired
    11. private OpenFeignService openFeignService;
    12. @GetMapping("getInfo/{id}")
    13. public JsonResult getInfo(@PathVariable("id") Long id){
    14. return openFeignService.getSql(id);
    15. }
    16. }

    测试

    启动9003/9004/8888,能够远程调用的同时还有负载均衡效果

    http://localhost:8888/getInfo/2

    3、OpenFeign超时时间控制

     OpenFeign 客户端默认等待1秒钟,但是如果服务端业务超过1秒,则会报错。为了避免这样的情况,我们需要设置feign客户端的超时控制。

    解决办法

    由于OpenFeign 底层是ribbon 。所以超时控制由ribbon来控制。在yml文件中配置

    3.1、超时案例演示

    首先演示超时效果,我们现在9003/9004上设置一个延迟3秒执行的方法,来模仿长业务线调用。

    1. @GetMapping("/timeOut")
    2. public String timeOut() {
    3. try {
    4. System.out.println("延迟响应");
    5. TimeUnit.SECONDS.sleep(3);
    6. } catch (InterruptedException e) {
    7. e.printStackTrace();
    8. }
    9. return serverPort;
    10. }

    客户端8888通过OpenFeign来进行调用

    1. //OpenFeginController
    2. @GetMapping("/testTimeout")
    3. public String TestTimeout(){
    4. return openFeignService.timeOut();
    5. }
    6. //OpenFeignService
    7. @GetMapping("/timeOut")
    8. public String timeOut();

    测试

    http://localhost:8888/testTimeout

    1. 2023-06-09 22:58:31.625 INFO 8000 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty : Flipping property: nacos-provider.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
    2. 2023-06-09 22:58:32.903 ERROR 8000 --- [nio-8888-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.RetryableException: Read timed out executing GET http://nacos-provider/timeOut] with root cause
    3. java.net.SocketTimeoutException: Read timed out
    4. at java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.8.0_202]

    3.2、设置超时控制案例演示

    首先我们需要在8888消费者端的yml文件中配置超时时间,因为OpenFeign本身整合了Ribbon所以,这里其实我们用的是Ribbon来配置

    1. server:
    2. port: 8888
    3. spring:
    4. application:
    5. name: nacos-consumer-openfegin
    6. cloud:
    7. nacos:
    8. discovery:
    9. server-addr: localhost:8848
    10. #设置feign客户端超时时间(OpenFeign默认支持ribbon)
    11. ribbon:
    12. #指的是建立连接后从服务器读取到可用资源所用的时间
    13. ReadTimeout: 5000
    14. #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
    15. ConnectTimeout: 5000

    测试

    重启8888,起不来的话,把注释或空行部分删除

    4、OpenFeign日志打印

            Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节。

    简单理解,就是对Feign接口的调用情况进行监控和输出

    日志级别:

    • NONE:默认的,不显示任何日志;
    • BASIC:仅记录请求方法、URL、响应状态码及执行时间;
    • HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;
    • FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。

    具体使用

    1、需要在启动类中通过@Bean注解注入OpenFeign的日志功能

    1. @SpringBootApplication
    2. @EnableFeignClients
    3. public class OpenFeginConsumer8888Application {
    4. public static void main(String[] args) {
    5. SpringApplication.run(OpenFeginConsumer8888Application.class, args);
    6. }
    7. @Bean
    8. Logger.Level feignLoggerLevel(){
    9. //开启详细日志
    10. return Logger.Level.FULL;
    11. }
    12. }

    2、在yml中配置中配置

    1. server:
    2. port: 8888
    3. spring:
    4. application:
    5. name: nacos-consumer-openfegin
    6. cloud:
    7. nacos:
    8. discovery:
    9. server-addr: localhost:8848
    10. #设置feign客户端超时时间(OpenFeign默认支持ribbon)
    11. ribbon:
    12. #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
    13. ReadTimeout: 5000
    14. #指的是建立连接后从服务器读取到可用资源所用的时间
    15. ConnectTimeout: 5000
    16. logging:
    17. level:
    18. # Openfeign日志以什么级别监控哪个接口
    19. com.lwz.cloud.service.OpenFeignService: debug

    测试

    重启8888,启动成功把控制台日志清空,访问 http://localhost:8888/testTimeout

    1. 2023-06-09 23:17:21.193 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] ---> GET http://nacos-provider/timeOut HTTP/1.1
    2. 2023-06-09 23:17:21.193 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] ---> END HTTP (0-byte body)
    3. 2023-06-09 23:17:24.200 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] <--- HTTP/1.1 200 (3006ms)
    4. 2023-06-09 23:17:24.200 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] connection: keep-alive
    5. 2023-06-09 23:17:24.201 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] content-length: 4
    6. 2023-06-09 23:17:24.201 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] content-type: text/plain;charset=UTF-8
    7. 2023-06-09 23:17:24.201 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] date: Fri, 09 Jun 2023 15:17:24 GMT
    8. 2023-06-09 23:17:24.201 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] keep-alive: timeout=60
    9. 2023-06-09 23:17:24.202 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut]
    10. 2023-06-09 23:17:24.202 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] 9003
    11. 2023-06-09 23:17:24.202 DEBUG 8152 --- [nio-8888-exec-2] com.lwz.cloud.service.OpenFeignService : [OpenFeignService#timeOut] <--- END HTTP (4-byte body)

    5、Sentinel整合OpenFegin

    引入OpenFegin

    在之前的8084项目中引入对应的依赖

    1. <dependency>
    2. <groupId>org.springframework.cloudgroupId>
    3. <artifactId>spring-cloud-starter-openfeignartifactId>
    4. dependency>

    激活Sentinel对OpenFeign的支持,所以配置yml

    1. # 激活Sentinel对OpenFeign的支持
    2. feign:
    3. sentinel:
    4. enabled: true

    主启动类要添加@EnableFeignClients注解

    OpenFegin接口编写

    1. //当没有成功调用/info/{id}接口时会走fallback属性标注的类型的处理方法
    2. @Service
    3. @FeignClient(value = "nacos-provider",fallback = FeignServiceImpl.class)
    4. public interface FeignService {
    5. /**
    6. * 远程调用对应方法
    7. */
    8. @GetMapping("info/{id}")
    9. public JsonResult getSql(@PathVariable("id") Long id);
    10. }

    实现类必须添加@Component注解,否则无法注入到容器中

    1. @Component
    2. public class FeignServiceImpl implements FeignService {
    3. @Override
    4. public JsonResult getSql(Long id) {
    5. return new JsonResult<>(444,"服务降级返回!");
    6. }
    7. }

    控制器

    1. //DemoController
    2. @Autowired
    3. private FeignService feignService;
    4. @GetMapping("getInfo/{id}")
    5. public JsonResult getInfo(@PathVariable("id") Long id){
    6. if(id > 3){
    7. throw new RuntimeException("没有该id");
    8. }
    9. return feignService.getSql(id);
    10. }

    测试

    此时如果我们访问http://localhost:8084/getInfo/2的地址,是没有问题的,但是如果此时我们人为结束9003/9004服务,这个时候就会触发fallback属性对应的处理类型,完成服务降级。

    http://localhost:8084/getInfo/2

     

    断开9003&9004服务以后

    Spring Cloud Alibaba - Sentinel(一)

    Spring Cloud Alibaba - Sentinel(二)

    Spring Cloud Alibaba - Sentinel源码分析(一)​​​​​​​

    懂与不懂都是收获!

  • 相关阅读:
    BUUCTF reverse wp 91 - 95
    无代码平台会导致程序员失业,是真的吗?
    swagger 文档自动生成接口代码+ts类型
    使用Qt Creator 创建 一个 QML 工程(一)
    从JS角度直观理解递归的本质
    Hadoop分布式文件系统-HDFS
    暑假加餐|有钱人和你想的不一样+风电随机性动态经济调度模型(Python&Matlab代码)
    SDL3 入门(2):第一个窗口
    【强化学习】09——价值和策略近似逼近方法
    现代图片性能优化及体验优化指南 - 懒加载及异步图像解码方案
  • 原文地址:https://blog.csdn.net/weixin_42472027/article/details/131098165