微服务学习-服务调用组件 OpenFeign 实战

1. OpenFeign 接口方法编写规范

1.1. 在编写 OpenFeign 接口方法时,需要遵循以下规范

1.1.1.1. 接口中的方法必须使用 @RequestMapping、@GetMapping、@PostMapping 等注解声明 HTTP 请求的类型。
1.1.1.2. 方法的参数可以使用 @RequestParam、@RequestHeader、@PathVariable 等注解来制定如何传递 HTTP 请求的参数。
1.1.1.3. 可以使用 @RequestBody 来指定如何传递请求体中的参数。
1.1.1.4. 可以使用 @HearderMap 来传递头部信息。

1.2. 案例演示

1.2.1.1. Get 请求

get 请求,参数全放 URL 中,不建议放 Body,部分浏览器可能会限制不能读取 body 中的数据;

get 请求参数过长的话,也会有问题,适用于参数不长的场景。

目标接口方法:

@GetMapping("/getOrderByUserId")
public Result<List<OrderResponse>> getOrderByUserId(@RequestParam("userId") Long userId)

OpenFeign 接口方法

@GetMapping("/getOrderByUserId")
Result<List<OrderResponse>> getOrderByUserId(@RequestParam("userId") Long userId);
1.2.1.2. post 请求
1.2.1.2.1. @RequestBody

目标接口方法:

@RequestMapping(value = "/post1")
public Result<OrderResponse> post1(@RequestBody OrderRequest orderRequest)

OpenFeign 接口方法

@PostMapping("/post1")
Result<OrderResponse> post1(@RequestBody OrderRequest orderRequest);
1.2.1.2.2. URL 后面追加参数

除了放在 body 中的参数,还能直接 url 后面追加参数,@RequestParam 注解

例如:增加参数 token http:/XXXXXXXX?token=xxxxxx

目标接口方法:

@RequestMapping(value = "/post2")
public Result<OrderResponse> post2(@RequestBody OrderRequest orderRequest, @RequestParam("token") String token)

OpenFeign 接口方法:

@PostMapping("/post2")
Result<OrderResponse> post2(@RequestBody OrderRequest orderRequest, @RequestParam("token") String token);
1.2.1.2.3. url 中加参数

url 中追加参数,参数用 @PathVariable 注解

目标接口方法:

@RequestMapping(value = "/post3/{userId}")
public Result<OrderResponse> post3(@RequestBody OrderRequest orderRequest, @PathVariable("userId") Long userId)

OpenFeign 接口方法:

@PostMapping("/post3/{userId}")
Result<OrderResponse> post3(@RequestBody OrderRequest orderRequest, @PathVariable("userId") Long userId);

2. OpenFeign 的调用流程

3. OpenFeign 常用扩展点配置

openFeign 提供了很多的扩展机制,让用户可以更加灵活的使用。

3.1. 测试环境

速通版:git checkout v2.0.0 版本:

icoolkj-microservices-code 标签 - Gitee.com

会员服务调用订单服务。

3.2. 日志配置

配置 Feign 的日志,让 Feign 把请求信息输出,方便查找问题等。

日志级别有4 种:

  • NONE【性能最佳,默认值】:不记录任何日志。
  • BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。
  • HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
  • FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据。
3.2.1.1. 配置方式
3.2.1.1.1. Java Bean 方式

全局生效:利用 @Configuration 实现全局生效,对所有的微服务调用者都生效。

    1. 定义一个配置类,指定日志级别
// 注意: 此处配置@Configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置@Configuration
@Configuration
public class FeignConfig {

    /**
     * 日志级别
     * @return
     */
    @Bean
    public Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }

}
    1. 在 application.yml 中配置 Client 的日志级别才能正常输出日志

格式:logging.level.feign 接口包路径=debug

logging:
  level:
    com.icoolkj.mall.user.openfeign.demo.feign: debug
    1. 重启测试

分别选择日志级别进行测试,查看控制台输出结果信息。

局部生效:让指定的微服务生效,在 @FeignClient 注解中指定 configuration

@FeignClient(name = "icoolkj-mall-order01", path = "/api/order", configuration = OpenFeignConfig.class)
public interface OrderFeignService {
  
  

注意:此时配置类不能添加 @Configuration 注解 。

3.2.1.1.2. yum 配置文件方式

全局生效:配置{服务名} 为 default,对应的微服务调用者都生效。

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            loggerLevel: FULL

局部生效:配置{服务名}为具体的服务名(icoolkj-mall-order01),对调用的微服务提供者生效。

spring:
  cloud:
    openfeign:
      client:
        config:
          icoolkj-mall-order01:
            loggerLevel: FULL
3.2.1.1.3. 配置方式选择

建议使用 yml 配置,可以利用配置中心对配置进行统一管理。

3.3. 超时时间配置

3.3.1.1. OpenFeign 使用两个超时参数

connectionTimeout 可以防止由于较长的服务器处理时间而阻塞调用者。

readTimeout 从连接建立时开始应用,当返回响应花费太长时间时触发。

注意:OpenFeign 底层使用 LoadBalancer,但是超时以 OpenFeign 配置为准。

3.3.1.2. 配置方式
3.3.1.2.1. Java bean 方式

通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接的超时时间(ms);第二个是请求处理的超时时间(ms)。

@Bean
public Request.Options options() {
    return new Request.Options(3000, 5000);
}
3.3.1.2.2. yml 配置文件方式
spring:
  cloud:
    openfeign:
      client:
        config:
          icoolkj-mall-order01:
            loggerLevel: FULL
            # 连接超时时间
            connectTimeout: 3000
            # 请求处理超时时间
            readTimeout: 5000
3.3.1.2.3. 测试配置是否生效

利用 Thread.sleep 来修改订单接口调用时间,验证是否超时。

3.4. 契约配置

Spring Cloud 在 Feign 的基础上做了扩展,可以让 Feign 支持 Spring MVC 的注解来调用。原生的 Feign 是不支持 Spring MVC 注解的,如果你想在 Spring Cloud 中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud 中默认的是 SpringMvcContract。

3.4.1.1. 配置方式
3.4.1.1.1. Java Bean 方式
@Bean
public Contract feignContract(){
    return new Contract.Default();
}
3.4.1.1.2. yml 配置文件方式
spring:
  cloud:
    openfeign:
      client:
        config:
          icoolkj-mall-order01:
            loggerLevel: FULL
            # 连接超时时间
            connectTimeout: 3000
            # 请求处理超时时间
            readTimeout: 5000
            # 指定
            contract: feign.Contract.Default

注意:修改契约配置后,OrderFeignService 不在支持 SpringMvc 的注解,需要使用 Feign 原生的注解。

Class OrderFeignService has annotations [FeignClient] that are not used by contract Default

@FeignClient(name = "icoolkj-mall-order01", path = "/api/order")
public interface OrderFeignService {
    // 使用 Feign 原生注解调用
    @RequestLine("GET /getOrderByUserId?userId={userId}")
    Result<List<OrderResponse>> getOrderByUserId(@Param("userId") Long userId);
}

3.5. 客户端组件配置

Feign 中默认使用 JDK 原生的 URLConnection 发送 HTTP 请求,没有连接池,我们可以集成别的组件来替换掉 URLConnection,比如 Apache HttpClient5,OKHttp。

Feign 发起调用真正执行逻辑:feign.Client#execute(扩展点)

3.5.1.1. 配置 Apache HttpClient5(推荐)
3.5.1.1.1. 引入依赖
<!-- Apache HttpClient5 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-hc5</artifactId>
</dependency>
3.5.1.1.2. 修改 yml 配置,启用 Apache HttpClient5,引入依赖后默认启用的,可以忽略
spring:
  cloud:
    openfeign:
      httpclient:
        hc5:
          enabled: true

关于配置可参考:org.springframework.cloud.openfeign.FeignAutoConfiguration

3.5.1.1.3. 重启测试

调用会进入 feign.hc5.ApacheHttp5Client#execute

3.5.1.2. 配置 OkHttp
3.5.1.2.1. 引入依赖
<!-- okhttp -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>
3.5.1.2.2. 修改 yml 配置,将 Feign 的 HttpClient 禁用,启用 OkHttp。
spring:
  cloud:
    openfeign:
      httpclient:
        hc5:
          enabled: false
      okhttp:
        enabled: true

关于配置可参考:org.springframework.cloud.openfeign.FeignAutoConfiguration

3.5.1.2.3. 重启测试

调用会进入 feign.okhttp.OkHttpClient#execute

3.6. GZIP 压缩配置

开启压缩可以有效节约网络资源,提升接口性能,我们可以配置 GZIP 来压缩数据

spring:
    openfeign:
      compression: # 配置 GZIP 来压缩数据
        request:
          enabled: true
          mime-types: text/xml,application/xml,application/json
          min-request-size: 1024 # 最小请求压缩阈值
        response:
          enabled: true

关于配置可参考:

org.springframework.cloud.openfeign.encoding.FeignAcceptGzipEncodingAutoConfiguration

3.7. 编码器解码器配置

Feign 中提供了自定义的编码器解码器设置,同时也提供了多种编码器的实现,比如 Gson、Jaxb、Jackson。我们可以用不同的编码器解码器来处理数据的传输。如果你想传输 XML 格式的数据,可以自定义 XML 编码器解码器来实现,或者使用官方提供的 Jaxb。

扩展点:feign.codec.Encoder & feign.codec.Decoder

public interface Encoder {
  void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException;
}

public interface Decoder {
    Object decode(Response var1, Type var2) throws IOException, DecodeException, FeignException;
}

3.8. 配置方式

3.8.1.1.1. 引入依赖
<!-- jackson -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-jackson</artifactId>
</dependency>
3.8.1.1.2. Java Bean 方式
@Bean
public Encoder encoder(){
    return new JacksonEncoder();
}

@Bean
public Decoder decoder(){
    return new JacksonDecoder();
}
3.8.1.1.3. yml 配置文件方式
spring:
  cloud:
    openfeign:
      client:
        config:
          icoolkj-mall-order01:
            # 配置编码器解码器
            encoder: feign.jackson.JacksonEncoder
            decoder: feign.jackson.JacksonDecoder

3.9. 拦截器配置

通过拦截器实现参数传递。

常用场景:统一添加 header 信息,比如向服务提供者传递全局事务 XID,会员 ID,认证 token 令牌,链路追踪的 traceID 等等。

扩展点:feign.RequestInterceptor

public interface RequestInterceptor {
    void apply(RequestTemplate var1);
}

每次 feign 发起 http 调用之前,会去执行拦截器中的逻辑。

3.9.1. 自定义拦截器实现认证逻辑

需求场景,微服务调用链路需要传递请求头的 token 信息

如果不做任何配置,直接使用 openFeign 在服务间进行调用就会丢失请求头。

解决方案:

3.9.1.1. 方案1:增加接口参数
@RequestMapping(value = "/api/product/getPriceProduct", method = RequestMethod.GET)  
String getPriceProduct(@RequestParam(value = "productId") Long productId, @RequestHeader(value = "token") String token);

该方案不好,代码有侵入性,需要开发人员每次手动获取和添加接口参数。

3.9.1.2. 方案2:添加拦截器

OpenFeign 在远程调用之前会遍历容器中的 RequestInterceptor,调用 RequestInterceptor 的 apply 方法,创建一个新的 Request 进行远程服务调用。因此可以通过实现 RequestInterceptor 给容器中添加自定义的 RequestInterceptor 实现类,这个类里面设置需要发送请求的参数,比如请求头信息,链路追踪信息等。

3.9.1.2.1. 代码实现拦截器:
@Slf4j
public class FeignAuthRequestInterceptor implements RequestInterceptor{

    @Override
    public void apply(RequestTemplate template) {
        // 业务逻辑,模拟认证逻辑
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        if(null != requestAttributes){
            HttpServletRequest request = requestAttributes.getRequest();
            String access_token = request.getHeader("Authorization");
            log.info("从 Request 中解析请求头:{}", access_token);
            // 设置 token
            template.header("Authorization", access_token);
        }
    }
}
3.9.1.2.2. 配置拦截器生效

方式1,Java Bean

@Bean
public FeignAuthRequestInterceptor feignAuthRequestInterceptor(){
    return new FeignAuthRequestInterceptor();
}

方式2,yml 配置文件

spring:
  cloud:
    openfeign:
      client:
        config:
          icoolkj-mall-order01:  #对应微服务
            request-interceptors:   # 配置拦截器
              - com.icoolkj.mall.user.openfeign.demo.interceptor.FeignAuthRequestInterceptor
            
3.9.1.2.3. 重启测试

postman 中增加请求头参数 Authorization,查看会员服务 openFeign 日志是否有 Authorization 信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/960283.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开源项目Umami网站统计MySQL8.0版本Docker+Linux安装部署教程

Umami是什么&#xff1f; Umami是一个开源项目&#xff0c;简单、快速、专注用户隐私的网站统计项目。 下面来介绍如何本地安装部署Umami项目&#xff0c;进行你的网站统计接入。特别对于首次使用docker的萌新有非常好的指导、参考和帮助作用。 Umami的github和docker镜像地…

研究 Day.js 及其在 Vue3 和 Vue 框架中的应用详解

前言 在前端开发中&#xff0c;日期和时间处理是一个常见需求。随着技术的发展&#xff0c;我们有了更多高效、灵活的日期库可供选择。Day.js 就是一个轻量级、易于使用的 JavaScript 日期库&#xff0c;其灵感来源于 Moment.js&#xff0c;但体积更小&#xff0c;速度更快。本…

python基础语法(3) -------- 学习笔记分享

目录: 1. 函数 1.1 语法格式 1.2 函数参数 1.3 函数返回值 1.4 变量的作用域 1.5 函数的执行过程 1.6 函数的链式调用 1.7 函数的嵌套调用 1.8 函数递归 1.9 参数默认值 1.10 函数的关键字传参 2. 列表和元组 2.1 列表和元组是啥 2.2 创建列表 2.3 访问下标 2.…

ceph新增节点,OSD设备,标签管理(二)

一、访问客户端集群方式 方式一: 使用cephadm shell交互式配置 [rootceph141 ~]# cephadm shell # 注意&#xff0c;此命令会启动一个新的容器&#xff0c;运行玩后会退出&#xff01; Inferring fsid c153209c-d8a0-11ef-a0ed-bdb84668ed01 Inferring config /var/lib/ce…

解决查看服务器ESN(许可证管理)

服务器的ESN&#xff08;许可证管理&#xff09;和SN码是两个东西。 查看步骤如下&#xff1a; 进入服务器的iBMC管理系统&#xff08;一般为机房运维人员可以查看&#xff09; 选择“许可证管理” 红框中即可看到信息。

《深入解析:DOS检测的技术原理与方法》

DDOS入侵检测与防御 一、实现Linux下DDOS的入侵检测与防御 利用Python编程实现对wrk的泛洪攻击检测&#xff0c;并让程序触发调用Linux命令实现防御: 1、泛洪攻击的检测&#xff0c;可以考虑使用的命令&#xff0c;这些命令可以通过Python进行调用和分析 (1) netstat -ant …

论文笔记(六十三)Understanding Diffusion Models: A Unified Perspective(四)

Understanding Diffusion Models: A Unified Perspective&#xff08;四&#xff09; 文章概括学习扩散噪声参数&#xff08;Learning Diffusion Noise Parameters&#xff09;三种等效的解释&#xff08;Three Equivalent Interpretations&#xff09; 文章概括 引用&#xf…

1.23 补题 寒假训练营

E 一起走很长的路&#xff01; 输入描述 第一行输入两个整数 n,q&#xff08;1≤n,q≤210^5&#xff09;&#xff0c;代表多米诺骨牌的个数和询问次数。 第二行输入 n 个整数 a1,a2,…,an​&#xff08;1≤ai≤10^9&#xff09;&#xff0c;表示多米诺骨牌的重量。 此后输入…

dmfldr实战

dmfldr实战 本文使用达梦的快速装载工具&#xff0c;对测试表进行数据导入导出。 新建测试表 create table “BENCHMARK”.“TEST_FLDR” ( “uid” INTEGER identity(1, 1) not null , “name” VARCHAR(24), “begin_date” TIMESTAMP(0), “amount” DECIMAL(6, 2), prim…

在深度Linux (Deepin) 20中安装Nvidia驱动

文章创作不易&#xff0c;麻烦大家点赞关注收藏一键三连。 在Deepin上面跑Tensorflow, pytorch等人工智能框架不是一件容易的事情。特别是如果你要使用GPU&#xff0c;就得有nvidia的驱动。默认情况下Deepin系统自带的是nouveau开源驱动。这是没办法用tensorflow的。下面内容是…

【Linux】IPC:匿名管道、命名管道、共享内存

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;Linux 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 1、管道2、进程池3、命名管道4、共享内存 1、管道 我们知道进程具有独立性&#xff0c;但是在一些场景中进程间也需要通信&#…

Pyside6(PyQT5)中的QTableView与QSqlQueryModel、QSqlTableModel的联合使用

QTableView 是QT的一个强大的表视图部件&#xff0c;可以与模型结合使用以显示和编辑数据。QSqlQueryModel、QSqlTableModel 都是用于与 SQL 数据库交互的模型,将二者与QTableView结合使用可以轻松地展示和编辑数据库的数据。 QSqlQueryModel的简单应用 import sys from PySid…

DeepSeek学术题目选择效果怎么样?

论文选题 一篇出色的论文背后&#xff0c;必定有一个“智慧的选题”在撑腰。选题足够好文章就能顺利登上高水平期刊&#xff1b;选题不行再精彩的写作也只能“当花瓶”。然而许多宝子们常常忽视这个环节&#xff0c;把大量时间花在写作上&#xff0c;选题时却像抓阄一样随便挑一…

Linux的权限和一些shell原理

目录 shell的原理 Linux权限 sudo命令提权 权限 文件的属性 ⽂件类型&#xff1a; 基本权限&#xff1a; chmod改权限 umask chown 该拥有者 chgrp 改所属组 最后&#xff1a; 目录权限 粘滞位 shell的原理 我们广义上的Linux系统 Linux内核Linux外壳 Linux严格…

【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(一)

目录 1 -> 概述 1.1 -> 整体架构 2 -> 文件组织 2.1 -> 目录结构 2.2 -> 文件访问规则 2.3 -> 媒体文件格式 3 -> js标签配置 3.1 -> pages 3.2 -> window 3.3 -> 示例 4 -> app.js 4.1 -> 应用生命周期 4.2 -> 应用对象6…

计算机的错误计算(二百二十二)

摘要 利用大模型化简计算 实验表明&#xff0c;虽然结果正确&#xff0c;但是&#xff0c;大模型既绕了弯路&#xff0c;又有数值计算错误。 与前面相同&#xff0c;再利用同一个算式看看另外一个大模型的化简与计算能力。 例1. 化简计算摘要中算式。 下面是与一个大模型的…

Ubuntu介绍、与centos的区别、基于VMware安装Ubuntu Server 22.04、配置远程连接、安装jdk+Tomcat

目录 ?编辑 一、Ubuntu22.04介绍 二、Ubuntu与Centos的区别 三、基于VMware安装Ubuntu Server 22.04 下载 VMware安装 1.创建新的虚拟机 2.选择类型配置 3.虚拟机硬件兼容性 4.安装客户机操作系统 5.选择客户机操作系统 6.命名虚拟机 7.处理器配置 8.虚拟机内存…

基于单片机的智能小区门禁系统设计(论文+源码)

1总体架构 智能小区门禁系统以STM32单片机和WiFi技术为核心&#xff0c;STM32单片机作为主控单元&#xff0c;通过WiFi模块实现与手机APP的连接&#xff0c;构建整个门禁系统。系统硬件包括RFID模块、指纹识别模块、显示屏、按键以及继电器。通过RFID绑定IC卡、APP面部识别、指…

03_使用同一个函数创建不同的任务

一、声明 这个程序执行的任务就是在一个函数里面可以执行几个不同的任务&#xff08;好吧&#xff0c;我到现在也没学会怎么添加自己的视频&#xff09; 我们这个程序使用到的外设只有OLED屏幕 二、CubeMx的配置 注意要选一下TIM4 挂一个I2C&#xff0c;用来放OLED的屏幕 再开…

高频 SQL 50 题(基础版)_620. 有趣的电影

高频 SQL 50 题&#xff08;基础版&#xff09;_620. 有趣的电影 一级目录 表&#xff1a;cinema id 是该表的主键(具有唯一值的列)。 每行包含有关电影名称、类型和评级的信息。 评级为 [0,10] 范围内的小数点后 2 位浮点数。 编写解决方案&#xff0c;找出所有影片描述为 …