【微服务】Feign远程调用

news2024/11/17 22:39:51

本系列介绍的是Spring Cloud中涉及的知识点,如有错误欢迎指出~

一.引子

  • 我们以前基于RestTemplate发起的http请求远程调用服务:

在这里插入图片描述

  • 存在下面的问题:

    • 代码可读性差,编程体验不统一

    • 参数复杂URL难以维护,字符串拼接硬编码

  • Feign是一个声明式的http客户端,官方地址:https://github.com/OpenFeign/feign

    • 作用:帮助我们实现http请求的发送替代RestTemplate,解决上面提到的问题。

在这里插入图片描述

二.使用Feign

Fegin的使用步骤如下,以order-service为例:

(1) 引入依赖

我们在order-service服务的pom文件中引入feign的依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

(2) 添加注解

在order-service的启动类添加注解开启Feign的功能:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lj4Mxx4F-1674225596437)(C:\Users\15802\Pictures\微服务\Feign远程调用\3.png)]

(3) 编写Feign的客户端

在order-service中新建一个接口,内容如下:

package cn.itcast.order.client;

import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("userservice")
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}
  • 这个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:

    • 服务名称:userservice

    • 请求方式:GET

    • 请求路径:/user/{id}

    • 请求参数:Long id

    • 返回值类型:User

这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。
在这里插入图片描述

(4) 测试

修改order-service中的OrderService类中的queryOrderById方法,使用Feign客户端代替RestTemplate:

在这里插入图片描述

使用起来简洁和看起来舒服。

(5) 总结

  • 使用Feign的步骤:

    • ① 引入依赖
    • ② 添加@EnableFeignClients注解
    • ③ 编写FeignClient接口
    • ④ 使用FeignClient中定义的方法代替RestTemplate
  • Feign内部集成了ribbon自动实现了负载均衡
    在这里插入图片描述

三.自定义配置

(1) 介绍

Feign可以支持很多的自定义配置,例如如下几个示例:

类型作用说明
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即可。

(2) 示例

下面以修改日志级别为例来演示如何自定义配置。

(2.1) 配置文件方式

可以基于配置文件(例如yml)修改feign的日志级别

  1. 局部生效:可以针对单个服务
feign:  
  client:
    config: 
      userservice: # 写具体服务名称,针对某个微服务的配置
        loggerLevel: FULL #  日志级别 
  1. 全局生效:也可以针对所有服务
feign:  
  client:
    config: 
      default: # 使用default为全局配置
        loggerLevel: FULL #  日志级别 

而日志的级别分为四种:

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

(2.2) Java代码方式

也可以基于Java代码来修改日志级别

  1. 先声明一个类,然后声明一个Logger.Level的对象:
public class DefaultFeignConfiguration  {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}
  1. 选择生效范围
  • 如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中:
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class) 
  • 如果是局部生效,则把它放到对应Client的@FeignClient注解中:
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class) 

四.使用优化

  • Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:

    • URLConnection:默认实现,不支持连接池
    • Apache HttpClient :支持连接池
    • OKHttp:支持连接池
  • 因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。

  • 这里我们用Apache的HttpClient来演示。

(1) 引入依赖

在order-service的pom文件中引入Apache的HttpClient依赖:

<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

(2) 配置连接池

在order-service的application.yml中添加配置,连接数需要自己测试最佳数量:

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

(3) 测试

接下来,在FeignClientFactoryBean中的loadBalance方法中打断点:
在这里插入图片描述

Debug方式启动order-service服务,可以看到这里的client,底层就是Apache HttpClient:
在这里插入图片描述

(4) 总结

  • Feign性能优化主要手段:

    • 日志级别尽量用basic或none

    • 使用HttpClient或OKHttp代替URLConnection

      • 引入feign-httpClient依赖

      • 配置文件开启httpClient功能,设置连接池参数

五.最佳实践

(1) 引子

所谓最佳实践,就是使用过程中总结的经验,认为最好的一种使用方式。

通过观察可以发现,Feign的客户端与服务提供者的controller代码非常相似:

feign客户端:
在这里插入图片描述

UserController:
在这里插入图片描述

有没有一种办法简化这种重复的代码编写呢?

(2) 继承方式

一样的代码可以通过继承来共享:

1)定义一统一的父接口作为标准,定义方法,并基于SpringMVC注解做声明。

2)Feign客户端和Controller都集成该接口

在这里插入图片描述

  • 优点:

    • 简单

    • 实现了代码共享

  • 缺点:

    • 官方不太推荐使用

    • 服务提供方、服务消费方紧耦合

    • 参数列表中的注解映射并不会继承,因此Controller中必须再次声明方法、参数列表、注解

(3) 抽取方式

将Feign的Client抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用。

例如,将UserClient、User、Feign的默认配置都抽取到一个feign-api包中,所有微服务引用该依赖包,即可直接使用。

在这里插入图片描述

(4) 实现基于抽取的最佳实践

(4.1) 抽取

首先创建一个module,命名为feign-api:

在这里插入图片描述

项目结构:

在这里插入图片描述

在feign-api中然后引入feign的starter依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

然后,order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中

在这里插入图片描述

(4.2) 在order-service中使用feign-api

首先,删除order-service中的UserClient、User、DefaultFeignConfiguration等类或接口。

在order-service的pom文件中中引入feign-api的依赖:

<dependency>
    <groupId>cn.itcast.demo</groupId>
    <artifactId>feign-api</artifactId>
    <version>1.0</version>
</dependency>

修改order-service中的所有与上述三个组件有关的导包部分,改成导入feign-api中的包

(4.3) 重启测试

重启后,发现服务报错了:

在这里插入图片描述

这是因为UserClient现在在cn.itcast.feign.clients包下,

而order-service的@EnableFeignClients注解是在cn.itcast.order包下,不在同一个包,无法扫描到UserClient。

(4.4) 解决扫描包问题

  • 方式一:

在启动类中指定Feign应该扫描的包:

@EnableFeignClients(basePackages = "cn.itcast.feign.clients")
  • 方式二(推荐):

在启动类中指定需要加载的Client接口字节码:

@EnableFeignClients(clients = {UserClient.class})

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

逆卷积(ConvTranspose2d)是什么?

上图是一个卷积操作&#xff08;蓝色为输入&#xff0c;绿色为输出&#xff09;。 输入的特征图为x&#xff1a;( 4&#xff0c;4 &#xff0c;channels_in&#xff09;其中channels_in表示通道数。 卷积核设置&#xff1a;无padding&#xff0c; kernel size为3*3&#xff0c…

<关键字(1)>——《C语言深度剖析》

目录 关键字 - 第一讲 1.关键字分类 2.定义与声明 2.1 什么是变量(是什么) 2.2如何定义变量(怎么用) 2.3为什么要定义变量(为什么) 2.4 变量定义的本质 2.5 变量声明的本质 3. 最宽宏大量的关键字 - auto 3.1 变量的分类 3.2 变量的作用域 3.3 变量的生命周期 …

汇编语言(第四版)第八章 实验7 习题解答

Power idea 公司从1975年成立一直到1995年的基本情况如下&#xff1a; 下面的程序中&#xff0c;已经定义好了这些数据&#xff1a; assume cs:codesg,ds:datasgdatasg segmentdb 1975,1976,1977,1978,1979,1980,1981,1982,1983db 1984,1985,1986,1987,1988,1989,1990,1991,19…

【12】C语言_几个循环的经典练习

目录 1. 打印n的阶乘; 2、计算 1!2!3!......10! 3、用二分查找在一个有序数组中查找一个数 4、打印如下 5、输入三次密码 6、写一个猜数字游戏 7、如题 8、打印1到100之间 3的倍数 9、给两个数&#xff0c;求出最大公约数 10、找出从1000到2000之间的闰年 11、找出10…

Java是编译性语言还是解释型语言 ?

首先我们应该了解这两种语言的概念 . 高级语言在计算机上执行 , 有两种方式 , 分为编译型语言和解释型语言 . 编译型语言 : 编写源代码–>编译–>链接. 典型的编译型语言 : C/C . 特点 : 源代码中一处有错 , 就不允许编译 ; 编译过程中出现一处错误 , 就停止编译 . 优…

论文投稿指南——中文核心期刊推荐(武器工业)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

4个免费数据恢复软件:免费恢复您的数据

意外的文件删除或文件损坏可能会令人头疼&#xff0c;尤其是在您不使用云存储的情况下。两者通常都支持已删除的文件恢复和版本控制&#xff0c;以帮助您摆脱此类困境。如果您不使用云&#xff0c;通常唯一的机会就是使用数据恢复软件来找回丢失或损坏的数据。 这种方法有两个…

使用 Burpsuite 测试的常用操作(二)

大家好啊&#xff0c;我是大田。接上篇文章「 使用 Burpsuite 测试的常用操作&#xff08;一&#xff09;」&#xff0c;今天继续分享一下 Burpsuite 在工作中常用操作三、本文中 2 个常用操作1、Burpsuite_proxy 篡改请求通过代理模式可以拦截、查看、修改所有客户端和服务器端…

(二)Linux嵌入式开发——软件安装(Ubuntu)

文章目录&#xff08;二)Linux嵌入式开发——软件安装&#xff08;Ubuntu&#xff09;APP StoreAPT工具问题解决办法1解决办法2deb软件包程序源码问题1解决办法问题2解决办法总结&#xff08;二)Linux嵌入式开发——软件安装&#xff08;Ubuntu&#xff09; 接下来&#xff0c;…

【GD32F427开发板试用】FOC矢量算法研究系列之一:PWM实现呼吸灯

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;Q_dGHvwj 前言 有幸被选为此次开发板测评活动的参与者&#xff0c;万分感谢。收到板子后迫不及待的拆来查看&#xff0c;画风整齐美观&#x…

SpringCloudAlibabaNacosConfig学习笔记

目录 1. Nacos配置中心使用 2 搭建nacos-config服务 3 Config相关配置 4 .配置的优先级 5. RefreshScope 1. Nacos配置中心使用 官方文档&#xff1a; https://github.com/alibaba/springcloudalibaba/wiki/Nacosconfig Nacos 提供用于存储配置和其他元数据的key/value 存…

23种设计模式(十三)——代理模式【接口隔离】

文章目录 意图什么时候使用代理真实世界类比代理模式的实现代理模式的优缺点亦称:Proxy 意图 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。 什么时候使用代理 1、…

论文投稿指南——中文核心期刊推荐(环境科学)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

操作系统-操作系统引论(1)

操作系统的基本概念一、操作系统的定义二、操作系统的产生与发展三、操作系统的特征四、操作系统的功能五、操作系统的运行机制六、操作系统的体系结构一、操作系统的定义 资源管理的观点&#xff1a;操作系统是控制和管理计算机的软、硬件资源&#xff0c;并且合理的组织计算…

通过C++对【图】进行抽丝剥茧(包括广度、深度优先遍历,求最小生成树,求最短路径)

目录 一.图的基本概念 二.图的存储结构 1.邻接矩阵 &#xff08;1&#xff09;无向图、有向图矩阵存储 &#xff08;2&#xff09;实现&#xff1a; 2.邻接表 &#xff08;1&#xff09;无向图邻接表存储 &#xff08;2&#xff09;有向图邻接表存储 &#xff08;3&a…

windows下运行ROSEFusion

其实LZ已经不再是两年前的Linux小白了&#xff0c;至于为什么要在windows下配置环境&#xff0c;是因为LZ在Linux下已经成功编译成功了ROSEFusion&#xff0c;但运行时一直报错Frame could not be processed&#xff0c;在github下的issue里面查询得知可能是CUDA版本问题。另外…

VM16 Pro+ubuntu20.04.5+GAMIT10.71安装(20230118更新包)

VMware Workstation 16 Proubuntu20.04GAMIT10.71安装测绘老中医&#xff08;qq8212714&#xff09;&#xff08;2023-01-20&#xff09;NOTE:安装环境&#xff1a;Windows 10 专业版&#xff0c;64 位操作系统, 基于 x64 的处理器1、首先在计算机中安装VMware Workstation 16 …

交叉编译(全志)

文章目录一、交叉编译概念二 、香橙派交叉编译3.带WiringPi库的交叉编译一、交叉编译概念 交叉编译&#xff0c;就是&#xff1a;在一种平台上编译&#xff0c;编译出来的程序&#xff0c;是放到别的平台上运行即编译的环境&#xff0c;和运行的环境不一样&#xff0c;属于交叉…

【基础】高低位和大小端

大小端模式出现是为了兼容不同CPU采用的不同的指令集 PowerPC架构和x86架构采用的是不同的CPU指令集。PowerPC采用精简指令集&#xff08;RISC&#xff0c;reduced instruction set computer&#xff09;&#xff0c;x86指的是特定微处理器执行的一些计算机语言指令集。 Powe…

Obsidian 插件(一):DataView 的使用

文章目录DataView 的使用一、 环境配置二、 入门介绍1、 快速开始2、 页面和字段3、 创建查询4、 系统字段三、 接口讲解1、 表达式1.1 概述1.2 表达式类型1.3 特定类型的交互2、 函数2.1 构造器2.2 常用函数2.3 工具函数DataView 的使用 一、 环境配置 首先&#xff0c;我们…