• SpringCloud之OpenFeign简单使用


    SpringCloud之OpenFeign简单使用

    OpenFeign是springcloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡调用其他服务。

    一、远程调用功能

    1. 创建提供服务的模块remote-feign-provider
    • 引入依赖
    <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
    
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-bootstrapartifactId>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    版本信息如下

    <properties>
            <maven.compiler.source>8maven.compiler.source>
            <maven.compiler.target>8maven.compiler.target>
            <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
            <spring-boot.version>2.4.2spring-boot.version>
            <spring-cloud-alibaba.version>2021.1spring-cloud-alibaba.version>
            <nacos.version>2021.1nacos.version>
            <spring-cloud.version>2020.0.1spring-cloud.version>
            <spring-cloud-bootstrap.version>3.0.3spring-cloud-bootstrap.version>
            <spring-cloud-loadbalancer.version>3.0.1spring-cloud-loadbalancer.version>
            <spring-cloud-openfeign.version>3.0.1spring-cloud-openfeign.version>
    properties>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 创建主类
    @EnableDiscoveryClient
    @SpringBootApplication
    public class RemoteFeignProviderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(RemoteFeignProviderApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 创建bootstrap.yml
    spring:
      application:
        name: remote-feign-provider
      cloud:
        nacos:
          discovery:
            group: remote-group
            namespace: remoteinvoke
            server-addr: 192.168.56.102:8848
            weight: 5
    
    server:
      port: 8082
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意nacos面板中需要新建相应的命名空间

    • 创建TestController,提供相应的调用服务
    @RestController
    public class TestController {
    
        @Value("${server.port}")
        private int port;
    
        @GetMapping("/service")
        public String test(){
            return "provicer servvice: [from port]:" + port;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    开启8081,8082两个端口的remote-feign-provider服务集群

    1. 下面开始创建调用模块,consumer模块
    • 创建remote-feign-service模块
    • 引入依赖
    <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-openfeignartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
    
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-bootstrapartifactId>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 主类
    @SpringBootApplication
    @EnableFeignClients(basePackages = "cn.axj.remote.feign.feign")
    @EnableDiscoveryClient
    public class FeignServiceApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(FeignServiceApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    @EnableDiscoveryClient默认要注册到注册中心,这个注解可加可不加。

    @EnableFeignClients : basePackages 用于OpenFeign扫描定义的FeignClient包路径

    • bootstrap.yml
    spring:
      application:
        name: remote-feign-service
      cloud:
        nacos:
          discovery:
            group: remote-group
            namespace: remoteinvoke
            server-addr: 192.168.56.102:8848
            weight: 5
    
    server:
      port: 8080
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    使用url形式的方式
    • 创建LoadBalanceProviderOriginalFeignClient的接口,并利用SpringMvc的特性,将provider提供的服务/service声明成springmvc形式
    @FeignClient(url = "http://localhost:8082",name = "remoteFeignSerivce")
    public interface LoadBalanceProviderOriginalFeignClient {
    
        @GetMapping("/service")
        String service();
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    定义一个url为http://localhost:8082的服务ip/端口的服务,指定该类访问的基础ip地址和端口固定

    关于@FeignClient注解,参数释义如下

    参数名称释义示例
    name/value指定远程服务的名称,用于服务发现和调用。@FeignClient(name = "user-service")
    url直接指定远程服务的 URL 地址。当提供了 url 时,name 将被忽略。@FeignClient(url = "http://localhost:8080")
    configuration用于自定义 Feign 客户端的配置,可以包含自定义的 Encoder、Decoder、LoggerLevel 等。@FeignClient(name = "user-service", configuration = MyFeignConfiguration.class)
    fallback用于指定熔断降级类,当远程服务调用失败时,会调用这个降级类中的方法。@FeignClient(name = "user-service", fallback = UserServiceClientFallback.class)
    fallbackFactory用于创建熔断降级类的工厂,允许在创建降级类时注入其他依赖。@FeignClient(name = "user-service", fallbackFactory = UserServiceClientFallbackFactory.class)
    path定义所有请求的基础路径,会添加到每个请求的前面。@FeignClient(name = "user-service", path = "/api/v1")
    decode404当服务器返回 404 时,是否应该解码响应体。默认为 false@FeignClient(name = "user-service", decode404 = true)
    loggerLevel设置 Feign 客户端的日志级别,可选值包括 NONE, BASIC, HEADERS, FULL@FeignClient(name = "user-service", loggerLevel = Logger.Level.FULL)
    primary当在 Spring 上下文中存在多个同名的 Feign 客户端时,标记哪个作为主要的 bean。@FeignClient(name = "user-service", primary = true)
    qualifier当需要区分多个同类型的 Feign 客户端时,用于指定一个唯一的名称,以便在注入时区分。@FeignClient(name = "user-service", qualifier = "myFeignClient")
    • 创建入口类Controller
    @RestController
    public class TestController {
    
        @Resource
        private LoadBalanceProviderOriginalFeignClient loadBalanceProviderOriginalFeignClient;
    
        @GetMapping("/test")
        public String test(){
            return loadBalanceProviderOriginalFeignClient.service();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    将FeignClient用组件的形式注入到Spring中,类似于Mybatis的Mapper类,OpenFeign会生产代理对象注入到Spring容器中

    测试

    启动remote-feign-service模块,访问localhost:8080/test,返回

    provicer servvice: [from port]:8082
    
    • 1

    反复刷新,观察返回情况,可以看到返回信息一直是8082服务器返回的。

    二、负载功能

    OpenFeign默认开启负载,使用注册到注册中心的服务名称定义FeignClient。

    • 在remote-feign-service模块中增加loadBalancer依赖
    <dependency>
         <groupId>org.springframework.cloudgroupId>
         <artifactId>spring-cloud-starter-loadbalancerartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 创建负载类的LoadBalanceProviderFeignClient接口
    @FeignClient(name = "remote-feign-provider") 
    public interface LoadBalanceProviderFeignClient {
    
        @GetMapping("/service")
        String service();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    name: 在注册中心中注册的调用服务名称

    • 在TestController中注入该FeignClient
    @RestController
    public class TestController {
    
        @Resource
        private LoadBalanceProviderOriginalFeignClient loadBalanceProviderOriginalFeignClient;
    
        @Resource
        private LoadBalanceProviderFeignClient loadBalanceProviderFeignClient;
    
        @GetMapping("/test")
        public String test(){
            return loadBalanceProviderOriginalFeignClient.service();
        }
    
        @GetMapping("/test2")
        public String test2(){
            return loadBalanceProviderFeignClient.service();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    测试

    重启remote-feign-service模块,访问localhost:8080/test2,观察返回

    provicer servvice: [from port]:8082
    provicer servvice: [from port]:8081
    provicer servvice: [from port]:8082
    provicer servvice: [from port]:8081
    provicer servvice: [from port]:8082
    ....
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    此时已默认加入负载功能

    三、熔断降级

    当远程服务调用失败时,会采用熔断降级策略,调用熔断降级的方法返回。

    熔断降级需要搭配熔断降级组件使用,这里使用hystrix进行熔断

    由于springcloud高版本openFeign已经默认移除了hystrix组件,这里需要手动加上hystrix依赖

    		<dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
                <version>2.2.5.RELEASEversion>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • bootstrap.yml中增加配置
    feign:
      circuitbreaker:
        enabled: true
    
    • 1
    • 2
    • 3
    • 新建LoadBalanceProviderFeignClientFallback熔断类
    @Component
    public class LoadBalanceProviderFeignClientFallback implements LoadBalanceProviderFeignClient{
        
        @Override
        public String service() {
            return "error fall back";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    tips: 必须将熔断类放入Spring容器中

    • 配置FeignClient的熔断类,配置FeignClient fallback属性
    @FeignClient(name = "remote-feign-provider",fallback = LoadBalanceProviderFeignClientFallback.class)
    public interface LoadBalanceProviderFeignClient {
    
        @GetMapping("/service")
        String service();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    重启remote-feign-service模块,并将remote-feign-provider服务全部关掉。模拟熔断现象产生,访问localhost:8080/test2,观察返回

    error fall back
    
    • 1

    返回结果是有熔断类逻辑返回

  • 相关阅读:
    2-1.spring源码--Container
    Flume从入门到精通一站式学习笔记
    linux的SSH(远程登录)服务
    C++实现单例模式
    投影矩阵、NDC 空间与 Reversed-Z
    HK32F030MF4P6 3路ADC采集
    分布式与微服务的区别
    随机森林实战(分类任务+特征重要性+回归任务)(含Python代码详解)
    生态短讯 | Tapdata 与 TDengine 完成产品兼容性互认证,打造物联网实时数据生态
    CentOS7 自带防火墙+Nginx封堵高频访问的恶意IP
  • 原文地址:https://blog.csdn.net/aoxiaojun/article/details/137914116