Feign 中的继承、日志与数据压缩

2023-11-17

上篇文章和大家分享了声明式微服务调用组件 Feign 的基本用法,相信大家已经了解到使用 Feign 的好处了,使用 Feign 有效地解决了使用 RestTemplate 时的代码模板化的问题,使服务之间的调用更加简单方便,同时也不易出错。不过,细心的读者可能也发现,上篇文章中我们学的 Feign 还是有一些明显的缺陷,例如,当我们在 provider 中定义接口时,可能是下面这样:

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(String name) {
        return "hello " + name + " !";
    }
}

然后在 feign-consumer 中定义接口的调用,又是下面这样:

@FeignClient("provider")
public interface HelloService {
    @GetMapping("/hello")
    String hello(@RequestParam("name") String name);
}

这两段代码其实也有部分重复了,例如接口的定义、请求参数绑定、方法返回值等,都是一样的,只是一个有接口的具体实现,一个没有具体实现而已。这些相同的代码如果写错了,还有可能导致调用失败,例如 provider 中写了 @GetMapping("/hello") ,而 feign-consumer 中写了 @GetMapping("/hello2") ,此时就会调用失败,那么如何避免这些问题呢?这就要使用到我们本文介绍到的 Feign 的继承特性。另外,Feign 中的操作日志可以帮助我们快速定位问题,数据压缩特性又能够提高数据传输效率,这些知识点,我将在本文和大家分享。

准备工作

和前面的文章一样,我们需要先做一些准备工作。首先创建一个名为 FeignAdvanced 的父工程,然后在父工程中创建一个子模块 eureka 服务注册中心并启动,具体的操作步骤我这里就不再赘述,大家要是忘记了,可以参考上一章的第一小节。

然后再在 FeignAdvanced 工程中创建一个子模块 commons。注意,这个子模块是一个 Maven 工程,而不是 Spring Boot 工程,因为这个模块我只是用它来提供公共接口。

commons 模块创建成功后,因为要在 commons 模块中使用 SpringMVC 的一整套东西,方便起见,在 commons 模块的 pom.xml 文件中添加如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

添加成功后,再在 commons 中添加一个 HelloService 接口:

public interface HelloService {
    @GetMapping("/hello")
    String hello(@RequestParam("name") String name);
}

在这个 HelloService 接口中,我们会将前面提到的 provider 和 feign-consumer 中公共的部分抽取出来定义在这里,然后在 provider 中调用这个接口,在 feign-consumer 中实现这个接口。

好了, HelloService 接口定义完成后,我们的准备工作就算是OK啦,接下来我们就来看看具体的继承特性要如何去实现。

继承特性

Feign 中继承,我们整体可以分两步来实现:

  1. 在 provider 中实现公共接口;
  2. 在 feign-consumer 中去调用接口。

我们分别来看。

在 provider 中实现接口

首先创建一个 provider 微服务项目,创建成功后,将刚刚创建的 commons 项目的依赖添加进来,完整的 pom.xml 文件如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>com.justdojava</groupId>
    <artifactId>commons</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

然后修改 provider 的配置文件,将 provider 微服务注册到 eureka 服务注册中心上,这一步也比较简单,不赘述。

接下来,我们在 provider 中定义一个 HelloController 来实现 commons 模块中的 HelloService 接口,如下:

@RestController
public class HelloController implements HelloService {
    @Override
    public String hello(String name) {
        return "hello " + name + " !";
    }
}
预览

做完这一切之后,就可以启动 provider 啦! provider 启动成功后,我们来继续开发 feign-consumer 。

在 feign-consumer 中调用接口

接下来我们在 FeignAdvanced 工程中再创建一个子模块 feign-consumer ,注意创建时候除了选择 Eureka Discovering 依赖之外,还需要选择 Feign 的依赖,具体步骤和上文一致,如下图:

项目创建成功后,也将 commons 模块加入到 pom.xml 文件中,如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>com.justdojava</groupId>
    <artifactId>commons</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

然后修改 feign-consumer 的配置文件 application.properties ,将 feign-consumer 注册到 eureka 服务注册中心上,这一步就比较简单,我这里就不再赘述。

接下来,和前面的步骤一样,在项目的启动类上添加 @EnableFeignClients 注解,开启 Feign 的使用:

@SpringBootApplication
@EnableFeignClients
public class FeignConsumerApplication {
public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApplication.class, args);
    }
}

再接下来创建的 FeignHelloService 接口继承自 HelloSerivce 接口,如下:

@FeignClient("PROVIDER")
public interface FeignHelloService extends HelloService {
}

注意,不同于上篇文章中的 HelloService 接口,这里的 FeignHelloService 接口直接继承自 HelloSerivce ,继承之后, FeignHelloService 自动具备了 HelloService 中的接口,因此可以在使用 @FeignClient(“PROVIDER”) 注解绑定服务之后就可以直接使用了。

最后,我们来创建一个 UseHelloController,在 UseHelloController 中来使用 FeignHelloService,如下:

@RestController
public class UseHelloController {
    @Autowired
    FeignHelloService feignHelloService;
    @GetMapping("/hello")
    public String hello(String name) {
        return feignHelloService.hello(name);
    }
}

配置完成后,启动 feign-consumer ,在浏览器中就可以访问 feign-consumer 了,通过 feign-consumer 就能调用 provider 的服务了。
图片描述

优缺点分析

通过上面案例的搭建,相信大家对 Feign 的继承特性已经有了一个大致的了解,那么这种写法和上篇文章我们的写法各自有什么优缺点呢?我们来分析下:

  1. 使用继承特性,代码简洁明了,不易出错,不必担心接口返回值是否写对,接口地址是否写对。如果接口地址有变化,也不用 provider 和 feign-consumer 大动干戈,只需要修改 commons 模块即可,provider 和 feign-consumer 就自然变了;
  2. 前面提到的在 feign-consumer 中绑定接口时,如果是 key/value 形式的参数或者放在 header 中的参数,就必须要使用 @RequestParam 注解或者 @RequestHeader 注解,这个规则在这里一样适用。即在 commons 中定义接口时,如果涉及到相关参数,该加的@RequestParam 注解或者 @RequestHeader 注解一个都不能少;
  3. 当然,使用了继承特性也不是没有缺点。继承的方式将 provider 和 feign-consumer 绑定在一起,代码耦合度变高,一变俱变,此时就需要严格的设计规范,否则会牵一发而动全身,增加项目维护的难度。

好了,通过上面这样一个简单的案例,相信大家对 Feign 的继承特性已经有所了解。

日志配置

使用了 Feign 之后,如果希望能够查看微服务之间调用的日志,则可以通过开启 Feign 的日志功能实现, Feign 中的日志级别一共分为四种:

  1. NONE ,不开启日志记录,默认即此;
  2. BASIC ,记录请求方法和请求 URL ,以及响应的状态码以及执行时间;
  3. HEADERS ,在第2条的基础上,再增加请求头和响应头;
  4. FULL ,在第3条的基础上再增加 body 以及元数据。

那么具体的配置是怎样的呢?很简单,首先在配置类中配置一个日志级别的 Bean ,我这里直接放在系统启动类中,如下:

@SpringBootApplication
@EnableFeignClients
public class FeignConsumerApplication {
public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApplication.class, args);
    }
  @Bean
    Logger.Level loggerLevel() {
        return Logger.Level.FULL;
    }
}

然后在 application.properties 中开启日志级别。注意, Feign 中的日志只对 DEBUG 级别的日志输出进行响应:

logging.level.com.justdojava.feignconsumer.FeignHelloService=debug

这里 logging.level 是指日志级别的前缀,com.justdojava.feignconsumer.FeignHelloService 表示该 class 以 debug 级别输出日志。当然,类路径也可以是一个 package ,这样就表示该 package 下的所有 class 以 debug 级别输出日志。配置完成后,重启 feign-consumer 项目,访问其中任意一个接口,就可以看到请求日志,如下:

数据压缩

使用 Feign 执行请求时,也可以对请求数据执行 GZIP 压缩,提高数据传输效率。具体配置如下:

feign.compression.request.enabled=true
feign.compression.response.enabled=true
feign.compression.request.mime-types=text/html,application/json
feign.compression.request.min-request-size=2048

前两行表示开启请求和响应压缩,第三行表示压缩的数据类型,默认是 text/html,application/json,application/xml ,第四行表示压缩数据的下限,即当要传输的数据大于2048时才需要对请求进行压缩。

请求重试

Feign 中默认也自带请求重试功能,即这里不需要添加 spring-retry 依赖,直接配置即可使用:

# 最大的重试次数,不包括第一次请求
ribbon.MaxAutoRetries=3
# 最大重试server的个数,不包括第一个 server
ribbon.MaxAutoRetriesNextServer=1
# 是否开启任何异常都重试
ribbon.OkToRetryOnAllOperations=false
预览

这样的配置,请求失败重试适用于所有的请求,也可以配置专门针对某一个微服务的请求失败重试,例如专门配置针对 provider 微服务的请求失败重试,如下:

#最大的重试次数
provider.ribbon.MaxAutoRetries=3
#最大重试server的个数
provider.ribbon.MaxAutoRetriesNextServer=1
#是否开启任何异常都重试
provider.ribbon.OkToRetryOnAllOperations=false
预览

这样,就可以针对不同的微服务配置不同的请求失败重试策略。

也可以不配置 application.properties ,而是通过提供如下一个 Bean 来实现请求重试:

@Bean
public Retryer feignRetryer() {
    Retryer.Default retryer = new Retryer.Default();
    return retryer;
}
预览
小结

本文主要向大家介绍了声明式微服务调用工具 Feign 的一些高级特性,例如继承机制、日志配置、请求压缩、请求重试等,并对继承特性的优缺点进行了分析。在实际开发中,灵活地使用这些属性,可以使我们的微服务以一个更高的效率运行。通过对这些特性的学习,相信大家对 Feign 将会有一个更深刻的认识。

本文作者:纯洁的微笑、江南一点雨

注:本博客是学习慕课网上江南一点雨老师博文的学习笔记,大家可以购买他的课程进行学习,如有侵权请联系我删除。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Feign 中的继承、日志与数据压缩 的相关文章

  • app离线消息推送服务器,在线消息推送和离线消息推送(3)

    首先介绍一下具体的功能设计 整个系统由服务端 客户端组成 客户端包含前端 浏览器端 pyqt桌面端 和后台 用于添加要推送的消息 因为浏览器端不容易注意到实时提醒 所以我将实时提醒功能放到pyqt桌面端中实现 如托盘区闪烁等醒目的方式 浏览
  • Unity 数据保存失败

    问题 游戏数据突然保存不了了 没有任何报错 切后台保存也出问题 编辑器上和PC端没问题 移动端上保存不了 原因 我使用的存储方式是 Newtonsoft Json 将对象转换成加密字符串并保存到本地 而不巧的是 我使用了 HashSet 这
  • BOOST升压电路原理详解

    原文来自公众号 工程师看海 BOOST升压电源是利用开关管开通和关断的时间比率 维持稳定输出的一种开关电源 它以小型 轻量和高效率的特点被广泛应用在各行业电子设备找那个 是不可缺少的一种电源架构 公众号后台回复 boost仿真文件 Boos
  • Linux 添加开机启动方法

    添加开启启动的方式一般有如下几种 第一种 把开机命令 写入到os的启动文件之中 伴随着启动文件的读取 顺便帮你把要启动的任务 一起启动了 第二种 把启动任务 放到os的启动目录下 os启动过程之中 会执行所有放在此目录下的任务 第三种 os
  • KaTeX数学公式输入

    序号 运算符 输入 举例 举例代码 1 x y
  • 【Java 学习】方法 和 一些编程案例

    文章目录 一 概述 二 案例 1 计算1 n的和返回 2 判断整数是奇数还是偶数 3 数组求最值改方法实现 三 方法的内存原理 四 方法参数传递机制 基本类型 引用类型 五 参数传递的案例 1 打印整型数组内容 2 从数组中查询指定元素的索
  • 【机器学习】SMO算法

    1 SMO基础概念 将原始最优化问题转化成了其对偶问题 因为对偶问题是一个凸二次规划问题 这样的凸二次规划问题具有全局最优解 其中 xi yi xi yi 表示训练样本数据 xixi为样本特征 yi 1 1 yi 1 1 为样本标签 C为惩
  • 中国货币超发严重 去年新增货币占全球近一半

    提要 2009年以来 中国已成为目前全球最大的 印钞机 2012年 全球新增货币供应量中国占近一半 21世纪网评估发现 均衡人均收入差异后 中国的经济货币化程度高居全球前列 截至2012年末 中国M2余额达到人民币97 42万亿元 居世界第
  • JS考点

    JavaScript 1 原始值和引用值类型及区别 原始值即存在栈中的数据 包含symbol number string null undefined boolean类型 引用值即存在堆中的对象 对象地址 指针 存在栈中 指向堆中存储的数据
  • 2021-07-25

    神经网络 M P神经元 感知机 感知机 神经网络 M P神经元 1 M P神经元 模拟生物行为的数学模型 接手n个输入 来自其他的神经元 并给各个输入赋予权重计算加权和 再跟自己特有的阀值 比较 通常用减法 最后经过激活函数 模拟 抑制 和
  • Stable Diffusion Base Model from safetensors transfer to diffusers

    Steps File Setup Clone the ControlNet model repo from HF into a folder like hf controlnet model git clone https huggingf
  • Qt 中父子关系使用总结

    背景 Qt 中到父子关系和类的继承无关 仅表示对象间到从属关系 继承自 QObject 的对象在构造时需要指定父对象指针 include
  • 计算机基础知识+Java语言基础 +JAVA学习笔记-DAY01

    计算机基础知识 01 01 计算机概述 了解 A 什么是计算机 计算机在生活中的应用举例 计算机 Computer 全称 电子计算机 俗称电脑 是一种能够按照程序运行 自动 高速处理海量数据的现代化智能电子设备 由硬件和软件所组成 没有安装
  • Cent OS6.5 安装nodeJS(分分钟搞定)

    第一步 下载 cd opt wget https nodejs org dist v7 5 0 node v7 5 0 linux x64 tar xz 第二步 解压缩文件包 xz d node v7 5 0 linux x64 tar x
  • hive原理与源码分析-hive源码架构与理论(一)

    什么是Hive 数据仓库 存储 查询 分析大规模数据 SQL语言 简单易用的类SQL查询语言 编程模型 允许开发者自定义UDF Transform Mapper Reducer 来更简单地完成复杂MapReduce无法完成的工作 数据格式
  • 运放增加输出电流

    功率输出模块 采用三极管9012 9013来进行双向扩流以提高其带载能力 可以完全满足发挥部分所要求的稳幅输出能力 当负载变化时 其输出电压幅度变化小于3 如图所示 集成运放的扩流和扩压 一 集成运放的扩流 在集成运放的输出端再加一级互补对
  • k8s-client(java)从6.0.1升级到11.0.0出现patch问题may not be specified for non-apply patch/cannot unmarshal...

    背景 kubernetes client java升级 复杂的patch出现各种问题 并且没有找到解决方案 经过研究 测试 找到了解决方案 希望能帮助到使用kubernetes client java客户端的同学 patch方法调用出现异常
  • IEEE 1471(ISO/IEC/IEEE 42010)架构描述方法

    ISO IEC IEEE 42010 架构描述方法 关于 背景 架构描述 利益相关者和关注点 架构视图和架构观点 架构模型 架构关系 架构原理 关于 本文对软件体系架构的描述方法的研究基于 ISO IEC IEEE 42010 ISO IE
  • unity ethan_响应式网页设计的挑战,Ethan Marcotte

    unity ethan In this episode of the Versioning Show David and Tim are joined by Ethan Marcotte a well known designer who

随机推荐

  • c语言设计(TVI)地铁自动售票机---@颜麓

    设计TVI 地铁自动售票机 机软件 输入站数 计算费用 计费规则 6站2元 7 10站3元 11站以上为4元 输入钱数 计算找零 找零时优先找回面额大的钞票 找零方式为各种面额张数 可识别面额 100 50 20 10 5 1 includ
  • Sentinel整合Ribbon/OpenFeign,Sentinel自定义限流熔断

    Sentinel服务熔断环境搭建 服务熔断 应对微服务雪崩效应的一种链路保护机制 类似保险丝 需要完成Sentinel整合Ribbon openFeign 所以我们先要搭建环境 那么先从整合Ribbon开始 环境搭建 为了演示操作 所以在这
  • DBeaver改成英语

    DBeaver改成英语 安装目录中有个dbeaver ini文件 追加 Duser language en可以改回英文 有些数据库术语翻译后反而不太容易理解
  • java获取唯一时间戳Id.多线程保证唯一性

    工程里有获取唯一时间戳作为id的需求 想了想用乐观锁cas实现 自旋 cas原子性操作获得了绝对唯一的时间戳 系统时间 纳秒版本 单机有效 不能分布式调用 public class AtomicTimeStamp private Atomi
  • Anaconda的安装与环境配置

    这里简单的记录一下Anaconda的安装过程 没有干货 只是记录 但也看了就会 下载安装包 这里有两个下载地址 分别是官网和清华镜像源 推荐清华镜像 下的快 官网下半天还可能失败 无论是哪个下载地址 找到对应你系统的安装程序下载即可 官网
  • Ubuntu下安装JDK图文教程详解

    操作系统 Ubuntu 11 10 我们选择的是jdk1 6 0 30版本 安装文件名为jdk 6u30 linux i586 bin 1 复制jdk到安装目录 1 假设jdk安装文件在桌面 我们指定的安装目录是 usr local jav
  • 可以编辑的table antd

    版本一 效果图 有保存按钮 antd3 代码 import React Component from react import Form Input Button Table Divider Popconfirm Tooltip from
  • 19_复制目录下所有文件夹和目录CopyFile()

    复制目录下所有文件夹和目录CopyFile 想一下 若要复制文件夹 可以在目录位置新建一个文件夹 然后将源文件夹中里面的文件进行遍历 一个一个的复制到目标文件夹中即可 void EnumCopyFile 输入参数 TCHAR szSrcRo
  • STL——vector以及emplace_back分析

    1 这里需要注意凡是连续空间的容器都提供operator 是为了数组操作 2 back 应该是 end 1 3 vector的大小为12 vector的迭代器为指针 1 emplace back 1 相比push back 如果传入临时对象
  • matlab中的锐度测量,锐度(解析度)MTF定义及测试

    Image sharpness 图像锐度 解析度 锐度无疑是最重要的摄影图像质量的评价因素 它是关系到图片中有多少细节可以被辨认的最密切因素 但它不是唯一的重要因素 其他重要因素包括色差 与锐度密切相关 噪音 动态范围 与噪声密切相关 和色
  • mysql常用命令

    mysql命令 查询 限制返回个数及偏移量 m 偏移量 n 个数 只限制个数可省略m 如limit 2 select from
  • IntelliJ IDEA破解

    今天写个IDEA破解 废话不多说 直接给网址 官网 https www jetbrains com idea 破解注册码 http idea lanyus com 里面有永久破解 还有注册码 可你根据你的喜爱 来选择 今天写一下它的破解补丁
  • HashMap之扩容原理

    一 什么是HashMap HashMap 数据结构为 数组 链表 JDk1 7 JDK1 8中增加了红黑树 其中 链表的节点存储的是一个 Entry 对象 每个Entry 对象存储四个属性 hash key value next 二 为什么
  • explicit关键字解析

    C 提供了关键字explicit 可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生 声明为explicit的构造函数不能在隐式转换中使用 C 中 一个参数的构造函数 或者除了第一个参数外其余参数都有默认值的多参构造函数 承担了两个角
  • Vue3.0-计算属性computed

    Vue3 0中的computed的功能与2 0中的计算函数功能一样 引入方法 import computed from vue 使用 在引入之后 设计箭头函数 var name computed gt 函数体 retrun 返回值 也就是计
  • Make和Makefile快速入门

    文章目录 目的 基础入门 Makefile语法 基础杂项 变量 条件选择 函数 文件引用 嵌套执行 make使用 使用进阶 总结 目的 我们可以在终端中通过命令来使用GCC编译代码生成可执行文件 对于实际的项目因为涉及的文件通常会比较多一些
  • 搭建OpenGL开发环境

    资料 安装教程 软件下载 Visual Studio 2019 CMake GLFW GLAD glfw 3 3 8 下载glfw的目的 获取压缩包里的include 生成glfw3 lib 获取include 解压找到Include in
  • shader学习笔记一:shader运行原理及uniform关键字

    shader运行原理 首先 opengl api函数输入一些数据 包括顶点数据 纹理数据 矩阵变换数据 这些顶点数据到 顶点处理阶段 顶点处理阶段 图形流水线会调用 vertex shader 顶点shader 对顶点进行处理 有多少个顶点
  • QT 5.12.9 +VS 2019配置并实现与三菱Q系列PLC通讯(2)实现通讯

    QT 5 12 9 VS 2019配置并实现与三菱Q系列PLC通讯功能 1 软件的安装 之前已经完成了软件的安装 接下来要通过MX Component去实现PLC的直连功能 首先 打开VS2019 新建项目 搜索qt 在出来的内容中选择QT
  • Feign 中的继承、日志与数据压缩

    上篇文章和大家分享了声明式微服务调用组件 Feign 的基本用法 相信大家已经了解到使用 Feign 的好处了 使用 Feign 有效地解决了使用 RestTemplate 时的代码模板化的问题 使服务之间的调用更加简单方便 同时也不易出错