• Nacos整合OpenFegin实现RPC调用


    往期回顾

    Nacos的安装与配置

    Spring Cloud集成Nacos作为注册中心

    LoadBalacer集成Nacos实现负载均衡

    常见的负载均衡策略分析

    Spring Cloud集成Dubbo实现RPC调用

    SpringCloud集成Nacos作为配置中心

    前面我们已经介绍了Nacos 的安装与配置,Spring Cloud 集成Nacos 作为服务的注册中心和配置中心,集成Nacos 实现服务的负载均衡和一些常见的负载均衡策略以及使用Dubbo进行RPC调用

    接下来,将介绍如何使用OpenFeign 进行RPC调用

    关于RPC的一些相关概念前面的文章已经介绍过,这里不再赘述。如果还有疑问的同学可以参见

    Spring Cloud集成Dubbo实现RPC调用

    OpenFeign介绍

    Spring Cloud OpenFeign 是声明式的服务调用工具,它整合了RibbonHystrix ,拥有负载均衡和服务容错功能

    Feign 是声明式的服务调用工具,我们只需创建一个接口并用注解的方式来配置它,就可以实现对某个服务接口的调用,简化了直接使用RestTemplate 来调用服务接口的开发量。Feign 具备可插拔的注解支持,同时支持Feign 注解、JAX-RS注解及SpringMvc注解。当使用Feign时,Spring Cloud集成了RibbonEureka 以提供负载均衡的服务调用及基于Hystrix 的服务容错保护功能。

    大家经常听到有人说OpenFeign,有人说Feign,给人一种好像是两个东西的错觉。其实是因为Feign本身也是Netflix的开源项目,后面独立出来单独做了开源项目,改名为OpenFeign。这种情况其实很常见,比如鸿蒙-HarmonyOS就有Open HarmonyOS。

    快速开始

    引入依赖

    我们先在原有的项目工程上创建一个新的消费者模块

    引入对应依赖

            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
                <exclusions>
                    
                    <exclusion>
                        <groupId>org.springframework.cloudgroupId>
                        <artifactId>spring-cloud-starter-netflix-ribbonartifactId>
                    exclusion>
                exclusions>
            dependency>  
    		        
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-loadbalancerartifactId>
            dependency>
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-bootstrapartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-openfeignartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    添加相关配置

    Nacos配置

    详见SpringCloud集成Nacos作为配置中心

    新建bootstrap.yml

    spring:
      application:
        name: user-openfeign-consumer
      cloud:
        nacos:
          discovery:
            server-addr: 192.168.199.128:8848 #Nacos地址
          config:
            server-addr: 192.168.199.128:8848 #Nacos地址
            file-extension: yaml #这里我们获取的yaml格式的配置
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    添加application.yml

    server:
      port: 7002
    spring:
      profiles:
        active: dev
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置OpenFeign 日志级别

    日志的级别分为四种:

    • NONE :不记录任何日志信息,这是默认值。
    • BASIC :仅记录请求的方法,URL以及响应状态码和执行时间
    • HEADERS :在BASIC的基础上,额外记录了请求和响应的头信息
    • FULL :记录所有请求和响应的明细,包括头信息、请求体、元数据

    日志的级别如果没有特殊要求,一般使用 NONE、BASIC 两个就好了,默认是NONE

    注意:因为feign调试日志是debug级别输出,springboot默认的日志级别是info,所以feign的debug日志级别就不会输出,所以需要对Feign接口单独配置日志输出级别

    # 因为feign调试日志是debug级别输出,springboot默认的日志级别是info,所以feign的debug日志级别就不会输出
    # logging.level=debug这样配置是对所有的日志级别进行配置
    # 该场景只需要对feign接口进行debug配置,所以是这样配置logging.level.com.example.order.feign=debug
    logging:
      level:
        cuit.epoch.pymjl.service.UserFeignClient: debug
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. Java代码的方式

    可以基于Java代码来修改日志级别,先声明一个类,然后声明一个Logger.Level 的对象

    先创建一个配置类

    package cuit.epoch.pymjl.config;
    
    import feign.Logger;
    import org.springframework.context.annotation.Bean;
    
    
    /**
     * 在启动类的注解@EnableFeignClients上指定
     * 局部生效就在@FeignClient中指定,不能加@Configuration注解
     *
     * @author Pymjl
     * @version 1.0
     * @date 2022/9/1 13:17
     **/
    public class OpenFeignConfig {
        @Bean
        public Logger.Level feignLogLevel() {
            // 日志级别为BASIC
            return Logger.Level.FULL;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    如果要全局生效,将其放到 启动类的@EnableFeignClients 这个注解中

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

    如果是局部生效,则把它放到对应的@FeignClient 这个注解中

    @FeignClient(value = "user-service",configuration = OpenFeignConfig.class)
    
    • 1
    1. 配置文件的方式
    # 针对某个微服务的配置  userservice:微服务名称  FULL:日志级别
    feign.client.config.userservice.logger-level=FULL
    # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
    #feign.client.config.default.logger-level=FULL
    
    • 1
    • 2
    • 3
    • 4

    配置LoadBalancer

    详见LoadBalacer集成Nacos实现负载均衡

    1. 配置负载均衡策略
    /**
     * 注意不要加@Configuration
     *
     * @author Pymjl
     * @version 1.0
     * @date 2022/8/26 13:05
     **/
    public class MyLoadBalancerConfig {
        @Resource
        NacosDiscoveryProperties nacosDiscoveryProperties;
    
        @Bean
        ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                                LoadBalancerClientFactory loadBalancerClientFactory) {
            String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
            // Nacos权重轮询
            return new NacosLoadBalancer(loadBalancerClientFactory
                    .getLazyProvider(name, ServiceInstanceListSupplier.class), name, nacosDiscoveryProperties);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    1. 配置RestTemplate
    /**
     * 在这里配置我们自定义的LoadBalancer策略 如果想自己扩展算法 需要实现ReactorServiceInstanceLoadBalancer接口
     * @LoadBalancerClients(defaultConfiguration = {name = "CLOUD-PAYMENT-SERVICE", configuration = MyLoadBalancerConfig.class})
     * 注意这里的name属性 需要和Nacos页面中的服务提供者名字一致
     *
     * @author Pymjl
     * @version 1.0
     * @date 2022/8/26 12:20
     **/
    @Configuration
    @LoadBalancerClient(name = "user-service", configuration = MyLoadBalancerConfig.class)
    public class RestTemplateConfig {
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    超时配置

    我们在通过 Feign 去调用接口,难免会遇到超时的问题,我们可以在 yml 文件设置超时属性,防止系统抛出超时异常

    feign:
        client:
            config:
    		   # 全局配置(default 默认就是适用于全部微服务)
                default:
                    connectTimeout: 100000
                    readTimeout: 100000
                # 单独配置
                user-service:
                    connectTimeout: 300000
                    readTimeout: 300000
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    OpenFeign的其他配置

    类型作用说明
    feign.Logger.Level修改日志级别包含四种不同的级别:NONE、BASIC、HEADERS、FULL
    feign.codec.Decoder响应结果的解析器http远程调用的结果做解析,例如解析json字符串为java对象
    feign.codec.Encoder请求参数编码将请求参数编码,便于通过http请求发送
    feign. Contract支持的注解格式默认是SpringMVC的注解
    feign. Retryer失败重试机制请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

    一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可

    常用的配置如下:

    feign:
      hystrix:
        enabled: true #在Feign中开启Hystrix
      compression:
        request:
          enabled: false #是否对请求进行GZIP压缩
          mime-types: text/xml,application/xml,application/json #指定压缩的请求数据类型
          min-request-size: 2048 #超过该大小的请求会被压缩
        response:
          enabled: false #是否对响应进行GZIP压缩
    logging:
      level: #修改日志级别
        com.macro.cloud.service.UserService: debug
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    OpenFeign的优化

    默认情况下,Feign 使用的是 UrlConnetcion 去请求,这种原生的请求方式一旦遇到高并发的情况下,响应会变得很慢,所以我们可以考虑加入连接池技术来优化性能, 比如常用的Ok HttpApache Http Client

    在HTTP 通信的过程中,建立连接是一个很复杂的过程,涉及到多个数据包的交换,很耗时间,而且HTTP连接需要3次握手和4次挥手开销都很大。

    这时可以采用HTTP连接池,节约大量的3次握手4次挥手时间,提升吞吐量。

    默认的HttpURLConnection是JDK自带的,并不支持连接池,如果要实现连接池的机制,还需要自己来管理连接对象。

    HttpClient 相比传统JDK自带的HttpURLConnection,它封装了访问HTTP的请求头,参数,内容体,响应等等。它不仅使客户端发送HTTP请求变得容易,而且也方便了开发人员测试接口(基于HTTP协议的),既提高了开发的效率,又提高了代码的健壮性。另外高并发大量的请求网络的时候,也是用"连接池"提升吞吐量。

    OkHttp作为后期之秀,功能和性能上,可能稍优于HttpClient ,但是几乎没多大区别,实际使用时,都是可以的,不过HttpClient集成起来更方便

    下面介绍下如何集成 Apache 下的 HttpClient 的连接池

    1. 先引入依赖
    >
        >io.github.openfeign>
        >feign-httpclient>
    >
    
    • 1
    • 2
    • 3
    • 4
    1. 编写对应的yml文件
    feign:
      httpclient:
        enabled: true
        max-connections: 200
        max-connections-per-route: 50
    
    • 1
    • 2
    • 3
    • 4
    • 5

    编写对应的接口

    1. 先在服务提供者正常的编写service 代码,然后将service 注入进controller 完成controller 的编写
    /**
     * @author Pymjl
     * @version 1.0
     * @date 2022/8/25 12:48
     **/
    @RestController
    @RequestMapping("/user")
    public class UserController {
        @Resource
        UserService userService;
    
        @GetMapping("/register")
        public CommonResult<String> register() {
            userService.register();
            return ResultUtils.success();
        }
    
        @GetMapping("/get/{id}")
        public CommonResult<User> get(@PathVariable("id") Long id) {
            return ResultUtils.success(userService.get(id));
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. 在消费者端编写对应的FeignClient ,和我们平常的service接口没太大的区别,只是在上面加上对应的SpringMVC注解
    /**
     * @author Pymjl
     * @version 1.0
     * @date 2022/9/1 0:03
     **/
    @FeignClient(value = "user-service")
    public interface UserFeignClient {
        /**
         * 注册
         *
         * @return {@code CommonResult}
         */
        @GetMapping("/user/register")
        CommonResult<String> register();
    
        /**
         * 得到
         *
         * @param id id
         * @return {@code CommonResult}
         */
        @GetMapping("/user/get/{id}")
        CommonResult<User> get(@PathVariable("id") Long id);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    注意value 的值要和nacos 中的服务提供者的名字相同

    然后编写对应的消费者controller

    /**
     * @author Pymjl
     * @version 1.0
     * @date 2022/9/1 0:09
     **/
    @RestController
    @RequestMapping("/consumer")
    public class TestController {
        @Resource
        UserFeignClient userFeignClient;
    
        @GetMapping("/register")
        public CommonResult<String> register() {
            return userFeignClient.register();
        }
    
        @GetMapping("/get/{id}")
        public CommonResult<User> get(@PathVariable Long id) {
            return userFeignClient.get(id);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    测试

    1. 先启动服务提供者user-service,再启动消费者

    image-20220901140039863

    1. 访问对应接口

    image-20220901140307734

    1. 查看消费者后台日志输出

    image-20220901140333458

    从上面可以看见,因为我们对OpenFegin 配置了日志的输出级别,控制台在访问对应的请求时打印了对应的HTTP接口的详情

    1. 查看提供者的日志输出

    image-20220901140446778

    至此,整合NacosOpenFegin 就完成了,至于OpenFegin 整合Hystrix 进行服务的降级与熔断这里不做赘述,后面考虑整合Sentinel

    Spring Cloud 之前使用的断路器是 Netfilx 开源的 Hystrix 。被很多开发人员作为默认的断路器来使用。2018 年 11 月,当 Netflix 宣布将这个项目置于维护模式时(不再开发新特性,只进行例行维护),Spring Cloud 官方也不得不跟进了 Netfix ,在 SpringOne 2019中,Spring 宣布将从 Spring Cloud 3.1 版本中删除 Hystrix 仪表板。要不了多长时间 Spring Cloud Netfix 将结束生命周期。

    应的请求时打印了对应的HTTP接口的详情

    1. 查看提供者的日志输出

    [外链图片转存中…(img-J4Qu3Fig-1662298670269)]

    至此,整合NacosOpenFegin 就完成了,至于OpenFegin 整合Hystrix 进行服务的降级与熔断这里不做赘述,后面考虑整合Sentinel

    Spring Cloud 之前使用的断路器是 Netfilx 开源的 Hystrix 。被很多开发人员作为默认的断路器来使用。2018 年 11 月,当 Netflix 宣布将这个项目置于维护模式时(不再开发新特性,只进行例行维护),Spring Cloud 官方也不得不跟进了 Netfix ,在 SpringOne 2019中,Spring 宣布将从 Spring Cloud 3.1 版本中删除 Hystrix 仪表板。要不了多长时间 Spring Cloud Netfix 将结束生命周期。

    项目源码:gitee github

  • 相关阅读:
    Git---idea中git的基本操作
    带您识别RJ45网口连接器/网口插座口的LED灯的平脚/斜脚,带弹/不带弹细节区分
    Vuex中多个参数显示undefined的解决方案
    【MATLAB 入门手册】基本操作与矩阵输入
    记nrm管理仓库以及发布npm包
    抽象的代理模式1.0版本
    前端监控系列2 |聊聊 JS 错误监控那些事儿
    【数据结构】手撕双向链表
    使用虚拟机安装ikuai软路由系统,搭建pppoe拨号服务器
    stack使用+模拟实现
  • 原文地址:https://blog.csdn.net/apple_52109766/article/details/126695067