• 微服务组件之Feign


    Feign

    Feign是一种声明式服务调用组件,它在RestTemplate的基础上做了进一步的封装。通过Feign,我们只需声明一个接口,并通过注解进行简单的配置,即可实现对HTTP接口的绑定。

    Feign Ribbon进行了集成,通过 Ribbon 实现了客户端的负载均衡调用。

    OpenFeign

    OpenFeignSpring Cloud Feign 的二次封装,它具有 Feign 的所有功能,并在Feign的基础上增加了对 Spring MVC 注解的支持。

    核心注解

    @FeignClient 该注解用于通知 OpenFeign 组件对 @RequestMapping 注解下的接口进行解析,并通过动态代理的方式产生实现类,实现负载均衡和服务调用。

    @EnableFeignClients该注解用于开启 OpenFeign 功能,当 Spring Cloud 应用启动时,OpenFeign 会扫描标有 @FeignClient 注解的接口,生成代理并注册到 Spring 容器中。

    OpenFeign远程服务调用示例

    搭建producer服务(被调用方)

    1.创建一个springboot应用

    (1)pom文件添加相关依赖

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        <version>${spring.cloud.netflix.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-ribbonartifactId>
        <version>${spring.cloud.netflix.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-openfeignartifactId>
        <version>${spring.cloud.netflix.version}version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    (2)配置

    server.port=8091
    spring.application.name=producer-service
    
    #可以注册到eureka服务注册中心
    eureka.client.enabled=true
    eureka.client.service-url.defaultZone=http://admin:123456@127.0.0.1:10001/eureka
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (3)启动类

    @EnableEurekaClient
    @SpringBootApplication
    public class ProducerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ProducerApplication.class, args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    (4)接口

    @Controller
    @RequestMapping("/orderService/service")
    public class UserController {
    
        @ResponseBody
        @RequestMapping("/get")
        public String get(){
            return "producer info";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    搭建consumer服务(调用方)

    1.创建一个springboot应用

    (1)pom文件添加依赖

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        <version>${spring.cloud.netflix.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-ribbonartifactId>
        <version>${spring.cloud.netflix.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-openfeignartifactId>
        <version>${spring.cloud.netflix.version}version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    (2)配置

    server.port=8092
    spring.application.name=consumer-service
    #可以注册到eureka服务注册中心
    eureka.client.enabled=true
    
    spring.security.user.name=admin
    spring.security.user.password=123456
    eureka.client.service-url.defaultZone=http://admin:123456@127.0.0.1:10001/eureka
    
    #服务消费者客户端需要去检索服务
    eureka.client.fetch-registry=true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (3)启动类

    启动类上添加@EnableFeignClients注解开启 OpenFeign 功能

    @EnableFeignClients
    @SpringBootApplication
    public class ConsumerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class, args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    (4)创建一个接口,使用注解@FeignClient,实现对服务接口的绑定,value属性值即为服务提供者的实例名称

    @Component
    @FeignClient(value = "producer-service")
    public interface FeignService {
    
        //value值即为producer服务的接口地址
        @RequestMapping(value = "orderService/service/get", method = RequestMethod.GET)
        String get();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (5)controller入口

    @Controller
    @RequestMapping("/orderService/service")
    public class UserController {
    
        @Autowired
        FeignService feignService;
    
        @ResponseBody
        @RequestMapping("/get")
        public String get(){
            return feignService.get();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    服务启动

    依次启动eureka serverproducer服务consumer服务

    接口调用测试

    浏览器访问http://localhost:8092/orderService/service/get请求接口,返回结果如下:

    在这里插入图片描述

    OpenFeign超时控制

    1.producer提供一个超时接口

    @ResponseBody
    @RequestMapping("/getTimeOut")
    public String getTimeOut(){
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        return "producer info";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.consumer接口调用producer的超时接口

    @ResponseBody
    @RequestMapping("/getTimeOut")
    public String getTimeOut(){
        return feignService.getTimeOut();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    尝试请求http://localhost:8092/orderService/service/getTimeOut接口,结果:

    在这里插入图片描述

    OpenFeign客户端默认等待一秒钟,超时就会报错。

    3.修改consumer的配置

    feign.client.config.producer-service.connect-timeout=6000
    feign.client.config.producer-service.read-timeout=6000
    
    • 1
    • 2

    4.重启consumer

    尝试请求http://localhost:8092/orderService/service/getTimeOut接口,返回结果如下:

    在这里插入图片描述

    OpenFeign日志增强

    1.开启日志相关配置

    Feign 为每一个 FeignClient 都提供了一个 feign.Logger 实例,通过它可以对 OpenFeign 服务绑定接口的调用情况进行监控。

    # com.example.consumer.service.FeignService 即为开启@FeignClient 注解的接口的全类名
    # debug:表示监听该接口的日志级别
    logging.level.com.example.consumer.service.FeignService=debug
    
    • 1
    • 2
    • 3

    2.创建一个配置类

    @Configuration
    public class ConfigOpenFeignLog {
        /**
         * OpenFeign 日志增强
         * 配置 OpenFeign 记录哪些内容
         */
        @Bean
        Logger.Level feginLoggerLevel() {
            //Logger.Level.FULL: 记录所有请求与响应的明细,包括头信息、请求体、元数据等等
            return Logger.Level.FULL;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    访问接口http://localhost:8092/orderService/service/get,查看控制台打印日志

    2022-11-01 14:31:53.134 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] ---> GET http://producer-service/orderService/service/get HTTP/1.1
    2022-11-01 14:31:53.135 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] ---> END HTTP (0-byte body)
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] <--- HTTP/1.1 200 (2ms)
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] cache-control: no-cache, no-store, max-age=0, must-revalidate
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] content-length: 13
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] content-type: text/plain;charset=UTF-8
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] date: Tue, 01 Nov 2022 06:31:53 GMT
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] expires: 0
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] pragma: no-cache
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] x-content-type-options: nosniff
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] x-frame-options: DENY
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] x-xss-protection: 1; mode=block
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] 
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] producer info
    2022-11-01 14:31:53.138 DEBUG 62672 --- [nio-8092-exec-1] c.example.consumer.service.FeignService  : [FeignService#get] <--- END HTTP (13-byte body)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    控制台打印了该接口请求与响应的所有明细

    总结

    本节内容主要记录了声明式的服务调用组件,OpenFeign如何进行远程服务调用,以及对调用服务接口的超时控制相关的配置,还有接口调用过程的日志增强…

  • 相关阅读:
    MySQL,刷题之对多表查询,题+代码!!
    虚假新闻检测——Exploring the Role of Large Language Models in Fake News Detection
    Linux服务器下搭建SFTP服务
    kobs-ng 编译使用
    Android基础第七天 | 字节跳动第四届青训营笔记
    Python中的yield关键字
    LLM:huggingface-datasets库
    Java基础数组-选择排序算法
    GitHub霸榜月余的24万字Java面试手册,竟是如此牛逼
    求后缀表达式的值
  • 原文地址:https://blog.csdn.net/Wang_Dong_Liang/article/details/127633506