http 客户端 Feign【微服务】

文章目录

    • 1. 基于 Feign 的远程调用
    • 2. Feign 自定义配置
    • 3. Feign 性能优化
    • 4. Feign 的最佳实践
      • 4.1 继承
      • 4.2 抽取

1. 基于 Feign 的远程调用

Feign 是一个声明式的 http 客户端,它可以帮助我们优雅地发送 http 请求。

在学习 Feign 之前先来看一下我们以前利用 RestTemplate 是如何发起远程调用请求的。

String url = "http://userserver/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);

存在下面的问题:
① 代码可读性差,编程体验不统一;
② 对于参数复杂的 URL 难以维护。

使用 Feign 的步骤如下:

① 引入依赖

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

在这里插入图片描述

② 在启动类上添加注解 @EnableFeignClients,开启自动装配功能

在这里插入图片描述

③ 编写 user 客户端做接口声明,我们就可以通过调用该接口里面的方法,来向 user 服务端(userserver)发起 http 请求

package com.zxe.orderserver.clients;import com.zxe.orderserver.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;//指定请求的服务名称
@FeignClient("userserver")
public interface UserClient {//指定请求路径及请求方式@GetMapping("/user/{id}")//方法的返回值就是最终请求到的结果User findById(@PathVariable("id") Long id);
}

在这里插入图片描述

在这里插入图片描述

④ 使用客户端,直接调用 UserClient 中的方法完成远程调用

在这里插入图片描述

⑥ 添加负载均衡依赖,Feign 内部已经集成了 Ribbon 负载均衡规则,可以直接实现负载均衡

在这里插入图片描述

⑦ 启动项目测试一下,可以看到我们已经实现了远程调用

在这里插入图片描述

2. Feign 自定义配置

Feign 运行自定义配置来覆盖默认配置,一般我们需要配置的就是日志级别。

在这里插入图片描述

配置 Feign 日志有两种方式:

① 配置文件方式

default代表全局配置,也可以把 default 换成具体的服务名,就是局部配置!

#配置Feign日志
feign:client:config:default: logger-level: Full

启动项目,可以看到完整的日志信息:

在这里插入图片描述

② Java 代码方式

需要先声明一个 Bean:

package com.zxe.orderserver.config;import feign.Logger;
import org.springframework.context.annotation.Bean;public class DefaultFeignConfiguration {@Beanpublic Logger.Level logLevel() {return Logger.Level.BASIC;}
}

在这里插入图片描述

在这里插入图片描述

如果是全局配置,则把它放到启动类的 @EnableFeignClients 注解中;如果是局部配置,就把它放到 @FeignClient 这个注解中。

在这里插入图片描述

在这里插入图片描述

日志记录还是需要消耗一些性能的,所以日志级别我们一般用 BASIC 就可以了!

3. Feign 性能优化

Feign 是一个声明式客户端,它只是把我们的声明变成一个 http 请求,而最终发起 http 请求的其实是其它的客户端,默认用的是 URLConnection。

Feign 底层的客户端实现:
① URLConnection:默认实现,不支持连接池;
② Apache HttpClient:支持连接池;
③ OKHttp:支持连接池。

URLConnection 不支持连接池,那么每次连接与断开都需要经历三次握手和四次挥手,对性能的损耗是比较大的,因此我们可以使用另外两种客户端来代替默认的 URLConnection。

因此 Feign 的性能优化主要包括以下两点:
① 使用连接池代替默认的 URLConnection;
② 日志级别,最好用 basic 或 none。

① 引入 HttpClient 依赖

Spring 已经管理了 HttpClient,所以不需要加版本号!

<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>

在这里插入图片描述

② 开启 Feign 对 HttpClient 的支持,并配置连接池

最大连接数的设置要根据真实情况去设置!

feign:httpclient:enabled: true #开启Feign对HttpClient的支持max-connections: 200 #最大连接数max-connections-per-route: 50 #单个路径的最大连接数

4. Feign 的最佳实践

4.1 继承

仔细观察你会发现,UserClient 中的 findById 和 UserController 的 findById 方法是一模一样的,因为一个是客户端一个是服务端,想要建立连接,访问路径肯定是完全一样的。既然是重复的东西,写两遍会不会有点冗余?

在这里插入图片描述

在这里插入图片描述

解决办法就是给消费者的 FeignClient 和提供者的 controller 定义统一的父接口作为标准。

但是在两个独立的微服务之间共享接口,肯定是不合理的,因为这会造成紧耦合。而且方法参数是无法继承的,也就是说 controller 接口还得自己实现 findById。虽然它有这么多的缺点,但是它遵循的是面向契约的思想,使用的还是比较多的。

4.2 抽取

比如 A 服务会用到 userserver,B 服务也会用到 userserver,这时候 A 和 B 服务中都需要编写 FeignClient 代码,且这个代码是完全一样的,那么就没必要写两次了。

所以我们可以将 FeignClient 抽取为独立模块(feign-api),并且把接口相关的 POJO、默认的 Feign 配置也都放到这个模块中,提供给所有消费者使用,消费者之间引依赖远程调用即可。

抽取方式的耦合度就很低了,但是它也有自己的缺点。其实 feign-api 里面不止放 userserver 的客户端,还会放大量的其它微服务的客户端,这时我们只想使用某一个,却把所有的都给引进来了,当然没有一个解决办法是完美的,我们需要根据实际情况选择合适的解决办法。

① 创建一个 module,命名为 feign-api,然后引入 feign 的 starter 依赖

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

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

② 将 orderserver 中编写的 UserClient、User、DefaultFeignConfiguration 都复制到 feign-api 项目中,记得把包名也改成 feignapi

在这里插入图片描述

在这里插入图片描述

③ 在 orderserver 中引入 feign-api 的依赖,并把刚刚复制到 feign-api 的内容都删掉

<dependency><groupId>com.zxe</groupId><artifactId>feign-api</artifactId><version>0.0.1-SNAPSHOT</version>
</dependency>

在这里插入图片描述

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

在这里插入图片描述

⑤ 单独指定需要加载的客户端,因为启动 orderserver 的时候并不会加载 feign-api 下的包,会报错

在这里插入图片描述

⑥ 重启测试

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kubernetes volume 数据存储详解

写在前面&#xff1a;如有问题&#xff0c;以你为准&#xff0c; 目前24年应届生&#xff0c;各位大佬轻喷&#xff0c;部分资料与图片来自网络 内容较长&#xff0c;页面右上角目录方便跳转 概述 容器的生命周期可能很短&#xff0c;会被频繁的创建和销毁 保存在容器中的…

人类的失误、错误与机器的失误、错误

人类的失误和错误是指人类在认知、判断、决策和行动过程中出现的错误或差错。这些错误可能是由于认知偏差、信息不完全、判断错误、行为失控等原因造成的。人类的失误和错误是不可避免的&#xff0c;而且在很多领域都有广泛的存在&#xff0c;包括工作、学习、社交、交通等方面…

【Java集合篇】HashMap的put方法是如何实现的?

HashMap的put方法是如何实现的 ✔️典型解析✔️ 拓展知识仓✔️HashMap put方法的优缺点有哪些✔️如何避免HashMap put方法的哈希冲突✔️如何避免HashMap put方法的哈希重 ✔️源码解读✔️putVal 方法主要实现如下&#xff0c;为了更好的帮助大家阅读&#xff0c;提升效率&…

C++力扣题目--94,144,145二叉树非递归(迭代)遍历

为什么可以用迭代法&#xff08;非递归的方式&#xff09;来实现二叉树的前后中序遍历呢&#xff1f; 我们在栈与队列&#xff1a;匹配问题都是栈的强项 (opens new window)中提到了&#xff0c;递归的实现就是&#xff1a;每一次递归调用都会把函数的局部变量、参数值和返回地…

04、Kafka ------ 各个功能的作用解释(Cluster、集群、Broker、位移主题、复制因子、领导者副本、主题)

目录 启动命令&#xff1a;CMAK的用法★ 在CMAK中添加 Cluster★ 在CMAK中查看指定集群★ 在CMAK中查看 Broker★ 位移主题★ 复制因子★ 领导者副本和追随者副本★ 查看主题 启动命令&#xff1a; 1、启动 zookeeper 服务器端 小黑窗输入命令&#xff1a; zkServer 2、启动 …

1.1map

unordered_map和map的使用几乎是一致的&#xff0c;只是头文件和定义不同 #include<iostream> #include<map>//使用map需要的头文件 #include<unordered_map>//使用unordered_map需要的头文件 #include<set>//使用set需要的头文件 #include<uno…

【C#】网址不进行UrlEncode编码会存在一些问题

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是2024年第3篇文章&#xff0c;此篇文章是C#知识点实践序列文章&#xff0c;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言数据丢失效果请求端代码接口端代码…

2024--Django平台开发-Django知识点(四)

1.知识回顾 创建项目&#xff1a;新项目、别人项目、新版版、老版本 项目目录&#xff08;v1.0版本&#xff09; 路由系统 常见路由编写加粗样式 /index/ 函数 /index/<str:v1> 函数 re_path(ryy/(\d{4})-(\d{2})-(\d{2})/, views.yy), re_path(ryy/(?…

1.6PTA集练7-5~7-24、7-1、7-2,堆的操作,部落冲突(二分查找)

7-5 大師と仙人との奇遇 分数 20 #include<iostream> #include<queue> using namespace std; int n; long long ans0,num; priority_queue<long long,vector<long long>,greater<long long>>q;//记录之前买的,用小顶堆&#xff0c;最上面就是最…

用开源大语言模型开发的智能对话机器人初版原型验证

用开源大语言模型开发的智能对话机器人初版原型验证 0. 背景1. 初版检证效果展示2. 验证效果总结3. 20240108 更新 0. 背景 同事要想做一个智能对话机器人&#xff0c;特别的需求有有些几点&#xff0c; 通过预置提示词&#xff08;包括确认事项&#xff09;&#xff0c;让大…

【习题】应用程序框架

判断题 1. 一个应用只能有一个UIAbility。错误(False) 正确(True)错误(False) 2. 创建的Empty Ability模板工程&#xff0c;初始会生成一个UIAbility文件。正确(True) 正确(True)错误(False) 3. 每调用一次router.pushUrl()方法&#xff0c;页面路由栈数量均会加1。错误(Fal…

环信IM Demo登录方式如何修改为自己项目的?

在环信即时通讯云IM 官网下载Demo&#xff0c;本地运行只有手机验证码的方式登录&#xff1f;怎么更改为自己项目的Appkey和用户去进行登录呢&#xff1f; &#x1f447;&#x1f447;&#x1f447;本文以Web端为例&#xff0c;教大家如何更改代码来实现 1、 VUE2 Demo vue2…

自定义列表里面实现多选功能

需求 我们在开发过程中有时候会遇到列表里面会有多选&#xff0c;然后列表样式也要进行自定义。这里我们如果直接使用ElementUI组件el-table表格的时候这里实现起来可能比较复杂不方便&#xff0c;我们这里手写自定义一下列表里面多选的功能。 实现效果如下图所示&#xff1a…

云渲染适合什么场景下使用?

云渲染作为影视动画主流的渲染方案&#xff0c;通常云渲染服务商拥有专属的渲染农场&#xff0c;通过渲染农场庞大的高新能数量机器&#xff0c;可协助你在短时间内完成渲染任务。 云渲染使用场景有哪些&#xff1f; 1、硬件限制&#xff1a; 如果你的个人或公司电脑硬件不足…

Java内存模型(JMM)是基于多线程的吗

Java内存模型&#xff08;JMM&#xff09;是基于多线程的吗 这个问题按我的思路转换了下&#xff0c;其实就是在问&#xff1a;为什么需要Java内存模型 总结起来可以由几个角度来看待「可见性」、「有序性」和「原子性」 面试官&#xff1a;今天想跟你聊聊Java内存模型&#…

重新认识一下 vue3 应用实例

重新认识一下 vue 应用实例 &#x1f495; 创建应用实例 每个 Vue 应用都是通过 createApp 函数创建一个新的 应用实例 应用实例必须在调用了 .mount() 方法后才会渲染出来。该方法接收一个“容器”参数&#xff0c;可以是一个实际的 DOM 元素或是一个 CSS 选择器字符串 //…

【bug】【VSCode】远程终端TERMINAL打不开

【bug】【VSCode】远程终端TERMINAL打不开 可能的原因现象分析解决 可能的原因 昨天晚上vscode在打开多个TERMINAL的情况下&#xff0c;挂了一晚上&#xff0c;今早上来看的时候全都lost connections…。然后关闭再打开就出现了如上现象。 早上一来到实验室就要debug… 现象…

【UE Niagara学习笔记】03 - 火焰喷射效果

目录 效果 步骤 一、创建粒子系统 二、制作火焰动画 三、改为GPU粒子 四、循环播放粒子动画 五、火焰喷射效果雏形 六、火焰颜色 效果 步骤 一、创建粒子系统 1. 新建一个Niagara系统&#xff0c;选择模板 命名为“NS_Flame_Thrower”&#xff08;火焰喷射&#…

IntelliJ IDEA 如何编译 Maven 工程项目

在当今的Java开发领域&#xff0c;Maven已经成为项目构建和依赖管理的标准工具。IntelliJ IDEA作为一款集成度高的Java开发环境&#xff0c;提供了许多强大的功能来简化和优化Maven项目的构建流程。本文将深入介绍如何使用IntelliJ IDEA编译Maven工程的详细步骤以及一些高级技巧…

day6:进程间的通信

思维导图&#xff1a; 实现多个进程之间的收发信息操作 create.c&#xff1a; #include <head.h> int main(int argc, const char *argv[]) {if(mkfifo("a_send_b",0664)!0){perror("");return -1;}if(mkfifo("b_send_a",0664)!0){perro…