当前位置: 首页 > news >正文

SpringCloud 微服务全栈体系(五)

第七章 Feign 远程调用

  • 先来看我们以前利用 RestTemplate 发起远程调用的代码:

在这里插入图片描述

  • 存在下面的问题:

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

    • 参数复杂 URL 难以维护

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

  • 其作用就是帮助我们优雅的实现 http 请求的发送,解决上面提到的问题。

在这里插入图片描述

一、Feign 替代 RestTemplate

  • Fegin 的使用步骤如下:

1. 引入依赖

  • 我们在 order-service 服务的 pom 文件中引入 feign 的依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2. 添加注解

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

在这里插入图片描述

3. 编写 Feign 的客户端

  • 在 order-service 中新建一个接口,内容如下:
package com.alex.order.client;import com.alex.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 可以支持很多的自定义配置,如下表所示:
类型作用说明
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 即可。

  • 下面以日志为例来演示如何自定义配置。

1. 配置文件方式

  • 基于配置文件修改 feign 的日志级别可以针对单个服务:
feign:client:config:userservice: # 针对某个微服务的配置loggerLevel: FULL #  日志级别
  • 也可以针对所有服务:
feign:client:config:default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置loggerLevel: FULL #  日志级别
  • 而日志的级别分为四种:

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

2. Java 代码方式

  • 也可以基于 Java 代码来修改日志级别,先声明一个类,然后声明一个 Logger.Level 的对象:
public class DefaultFeignConfiguration  {@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.BASIC; // 日志级别为BASIC}
}
  • 如果要全局生效,将其放到启动类的@EnableFeignClients 这个注解中:
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)
  • 如果是局部生效,则把它放到对应的@FeignClient 这个注解中:
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)

三、Feign 使用优化

  • 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 # 每个路径的最大连接数
  • 接下来,在 FeignClientFactoryBean 中的 loadBalance 方法中打断点:

在这里插入图片描述

  • Debug 方式启动 order-service 服务,可以看到这里的 client,底层就是 Apache HttpClient:

在这里插入图片描述

3. 总结

  • Feign 的优化:

    • 日志级别尽量用 basic

    • 使用 HttpClient 或 OKHttp 代替 URLConnection

      • 引入 feign-httpClient 依赖

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

四、最佳实践

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

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

  • feign 客户端:

在这里插入图片描述

  • UserController:

在这里插入图片描述

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

1. 继承方式

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

    • 定义一个 API 接口,利用定义方法,并基于 SpringMVC 注解做声明。

    • Feign 客户端和 Controller 都集成改接口

在这里插入图片描述

  • 优点:

    • 简单
    • 实现了代码共享
  • 缺点:

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

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

2. 抽取方式

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

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

在这里插入图片描述

3. 实现基于抽取的最佳实践

3.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 项目中

在这里插入图片描述

3.2 在 order-service 中使用 feign-api
  • 首先,删除 order-service 中的 UserClient、User、DefaultFeignConfiguration 等类或接口。

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

<dependency><groupId>com.alex.demo</groupId><artifactId>feign-api</artifactId><version>1.0</version>
</dependency>
  • 修改 order-service 中的所有与上述三个组件有关的导包部分,改成导入 feign-api 中的包
3.3 重启测试
  • 重启后,发现服务报错了:

在这里插入图片描述

  • 这是因为 UserClient 现在在 com.alex.feign.clients 包下,

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

3.4 解决扫描包问题
3.4.1 方式一
  • 指定 Feign 应该扫描的包:
@EnableFeignClients(basePackages = "com.alex.feign.clients")
3.4.2 方式二
  • 指定需要加载的 Client 接口:
@EnableFeignClients(clients = {UserClient.class})

相关文章:

SpringCloud 微服务全栈体系(五)

第七章 Feign 远程调用 先来看我们以前利用 RestTemplate 发起远程调用的代码&#xff1a; 存在下面的问题&#xff1a; 代码可读性差&#xff0c;编程体验不统一 参数复杂 URL 难以维护 Feign 是一个声明式的 http 客户端&#xff0c;官方地址&#xff1a;https://github.…...

msvcp140.dll丢失的正确解决方法

在使用电脑中我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140.dll丢失”。这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要采取一些措施来修复丢失的msvcp140.dll文件。本文将介绍6个不同的解决方法&#xff0c;帮助读者解决…...

go pprof 如何使用 --chatGPT

gpt: pprof 是 Go 语言的性能分析工具&#xff0c;它可以用来检测 CPU 使用情况、内存使用情况、以及阻塞情况。你可以使用 pprof 来帮助诊断程序的性能问题&#xff0c;包括内存泄漏。 以下是如何使用 pprof 来分析内存泄漏的基本步骤&#xff1a; 1. **导入 pprof 包**&am…...

大数据可视化BI分析工具Apache Superset实现公网远程访问

大数据可视化BI分析工具Apache Superset实现公网远程访问 文章目录 大数据可视化BI分析工具Apache Superset实现公网远程访问前言1. 使用Docker部署Apache Superset1.1 第一步安装docker 、docker compose1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网…...

软考系统架构师知识点集锦二:软件工程

一、考情分析 二、考点精讲 2.1 软件过程模型 &#xff08;1&#xff09;原型模型 典型的原型开发方法模型。适用于需求不明确的场景,可以帮助用户明确需求。可以分为[抛弃型原型]与[演化型原型] 原型模型两个阶段: 1、原型开发阶段;2、目标软件开发阶段。 &#x…...

Go并发:使用sync.Pool来性能优化

简介 在Go提供如何实现对象的缓存池功能&#xff1f;常用一种实现方式是&#xff1a;sync.Pool, 其旨在缓存已分配但未使用的项目以供以后重用&#xff0c;从而减轻垃圾收集器&#xff08;GC&#xff09;的压力。 快速使用 sync.Pool的结构也比较简单&#xff0c;常用的方法…...

git stash的使用方法

git stash的使用方法 应用场景 当我们在开发一个新功能的时候&#xff0c;或者开发到一半&#xff0c;然后就收到了线上master 出现了bug&#xff0c;当分支开发已经进行了或者进行到一半了&#xff0c;这时怎么办呢&#xff1f; 这时解决方案有两种&#xff1a;一种是先先将当…...

【影刀演示_发送邮件的格式化HTML留存】

发送邮件的格式化HTML留存 纯文本&#xff1a; 亲爱的小张: 端午节将至&#xff0c;公司为了感谢大家一年以来的辛勤工作和付出&#xff0c;特别为大家准备了京客隆超市福利卡&#xff0c;希望为大家带来些许便利和节日的喜悦。 以下是您的福利卡卡号和密码&#xff0c;请您…...

深度学习(4)---生成式对抗网络(GAN)

文章目录 一、原理讲述1.1 概念讲解1.2 生成模型和判别模型 二、训练过程2.1 训练原理2.2 损失函数 三、应用 一、原理讲述 1.1 概念讲解 1. 生成式对抗网络&#xff08;Generative Adversarial Network&#xff0c;GAN&#xff09;是一种深度学习模型&#xff0c;是近年来复杂…...

ThinkPad电脑HDMI接口失灵如何解决?

ThinkPad电脑HDMI接口失灵如何解决&#xff1f; 如果平时正常使用的外接显示器&#xff0c;某天突然无法使用了&#xff0c;重新插拔依然无信号的话&#xff0c;可以打开系统的设备管理器&#xff08;快捷键winx&#xff09;&#xff0c;首先看一下监视器的识别情况&#xff0c…...

第四部分:JavaScript

一&#xff1a;jQuery 1.1&#xff1a;jQuery介绍 什么是jQuery&#xff1f; jQuery是JavaScript和查询&#xff08;Query&#xff09;&#xff0c;它是辅助JavaScript开发的js类库 jQuery的核心思想 核心思想是write less&#xff0c;do more&#xff0c;所以它实现了很多浏览…...

【游戏开发】【心法】游戏设计心法系列1-以玩法为核心去设计游戏

游戏的本质 游戏的魔法在于寻找隐藏事物之间的联系。 游戏的魅力在于随着玩家逐渐发现并了解游戏世界的方方面面&#xff0c;他会得到一种丰富而深厚的体验。 挑战&#xff0c;竞争和互动是游戏玩法的三大要素。 规则&#xff0c;过程&#xff0c;目标则是游戏内容的要素。 如…...

chrome谷歌浏览器取消网页所有剪切板的授权方法步骤

地址栏输入 chrome://settings/content/clipboard选择 不允许网站查看您剪贴板中的文字或图片 ———————————————— 版权声明&#xff1a;本文为CSDN博主「一切V随缘」的原创文章&#xff0c;遵循CC 4.0 BY-SA版权协议&#xff0c;转载请附上原文出处链接及本声明…...

目标检测算法改进系列之嵌入Deformable ConvNets v2 (DCNv2)

Deformable ConvNets v2 简介&#xff1a;由于构造卷积神经网络所用的模块中几何结构是固定的&#xff0c;其几何变换建模的能力本质上是有限的。在DCN v1中引入了两种新的模块来提高卷积神经网络对变换的建模能力&#xff0c;即可变形卷积 (deformable convolution) 和可变形…...

最新发布!阿里云卓越架构框架重磅升级

云布道师 10 月 19 日阿里云峰会山东上&#xff0c;阿里云重磅升级《阿里云卓越架构白皮书》&#xff0c;助力企业在阿里云上构建更加安全、高效、稳定的云架构。《阿里云卓越架构白皮书》在今年的阿里云峰会粤港澳大湾区首度亮相&#xff0c;这是阿里云基于多年服务各行各业客…...

如何监听/抓取两个设备/芯片之间“UART串口”通信数据--监视TXD和RXD

案例背景&#xff1a;全网仅此一篇&#xff01;&#xff01;&#xff01; 两个设备/芯片之间采用UART串口通信。我们如何实现芯片1 TXD – > 芯片2 RXD&#xff0c;芯片2 TXD --> 芯片1 RXD两个单线链路上的数据抓取和监听&#xff1f;这篇博客将告诉您。 目录 1 什么是…...

JDK项目分析的经验分享

基本类型的包装类(Character放在最后) String、StringBuffer、StringBuilder、StringJoiner、StringTokenizer(补充正则表达式的知识) CharacterIterator、StringCharacterIterator、CharsetProvider、CharsetEncoder、CharsetDecoder(较难) java.util.function下的函数表…...

Java创建一个长度为10的数组,利用Arrays.sort(), 为数组元素排序

程序要求&#xff1a;1&#xff09;创建一个整型数组&#xff0c;数组的长度为10. 2&#xff09;给数组元素赋值&#xff0c;要求乱序。 3&#xff09;利用fori循环将数组元素依次输出。 4&#xff09;利用Arrays.sort(), 为数组元素排序 5&#xff09;采用增加for循环将排…...

python 动态加载C# 动态库的一些问题

python导入C#动态库问题 背景介绍 我使用的python是3.7&#xff0c;需要调用之前已经用于其他项目的C#编写的动态库(xx.dll).由于调用方法很简单&#xff0c;可以参考下这个调用动态库,这里主要说一下我遇到的问题。 试图加载格式不正确的程序 这个问题实际是由于目标程序和…...

代码审计-锐捷NBR路由器 EWEB网管系统 远程命令执行

那天下着很大的雨&#xff0c;母亲从城里走回来的时候&#xff0c;浑身就是一个泥人&#xff0c;那一刻我就知道我没有别的选择了 出现漏洞的文件在 /guest_auth/guestIsUp.php 审查源码我们发现通过命令拼接的方式构造命令执行 构造payload&#xff1a; /guest_auth/guestI…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...