详解SpringCloud微服务技术栈:Feign远程调用、最佳实践、错误排查

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:详解SpringCloud微服务技术栈:Nacos配置管理
📚订阅专栏:微服务技术全家桶
希望文章对你们有所帮助

之前使用RestTemplate来实现远程调用,这种方式存在了一些问题,更优的解决方式是使用Feign来实现远程调用。
这里将会讲解如何用Feign实现远程调用,并进行最佳实践。

Feign的远程调用与最佳实践

  • 基于Feign实现远程调用
  • 自定义配置
  • 性能优化
  • Feign最佳实践
    • 分析
    • 实现

基于Feign实现远程调用

RestTemplate的问题:

1、代码可读性差,变成体验不统一
2、参数比较复杂的url,难以维护

Feign是一个声明式的http客户端,官方地址:Feign官网
声明式在Spring中开始提到,是利用配置文件来加事务。而声明式http客户端也是类似,我们只需要把发http请求所需要的信息声明出来即可,剩下的东西都交给Feign来实现。

使用Feign的步骤:
1、引入依赖:

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

2、在order-service的启动类添加开启Feign的功能:加注解@EnableFeignClients
3、做声明(编写Feign客户端):

@FeignClient("userservice") //声明出服务名称
public interface UserClient {@GetMapping("/user/{id}")User findById(@PathVariable("id") Long id);
}

主要是基于SpringMVC的注解来声明远程调用的信息,如服务名称、 请求方式、请求路径、请求参数、返回值类型等,直接声明这些信息就行。
这样的方式会简单很多,注解开发太方便了,节约了很多学习成本,即便url的参数很复杂,我们利用注解开发写参数列表也是很方便的。

现在我们可以直接使用这个客户端了,直接修改order查询的接口:

    @Resourceprivate OrderMapper orderMapper;@Resourceprivate UserClient userClient;public Order queryOrderById(Long orderId){//查询订单Order order = orderMapper.findById(orderId);//根据用户id来查询用户,用Feign实现远程调用User user = userClient.findById(order.getUserId());//将用户注入到order中order.setUser(user);// 4.返回return order;}

同时多次刷新网址,可以验证出Feign还集成了Ribbon负载均衡,是比较强大的。

总结Feign使用步骤:

引入依赖
添加@EnableFeignClients注解
编写FeignClient接口
使用FeignClient中定义的方法来代替RestTemplate

自定义配置

Feign可以让我们自定义配置来覆盖默认配置,一般需要配置的是日志级别的类型feign.Logger.Level。
配置Feign日志有2种方式。

方式一:配置文件
1、全局生效

feign:client:config:default:loggerLevel: FULL # 最高级别,日志中会包含发起的请求,以及远程调用等信息

在这里插入图片描述

2、局部生效

feign:client:config:userservice:loggerLevel: FULL

方式二:Java代码
先声明一个Bean:

public class DefaultFeignConfiguration {@Beanpublic Logger.Level LogLevel(){return Logger.Level.BASIC;}
}

想要这个类生效,需要配置。
1、全局配置:把它放到@EnableFeignClients这个注解中:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)

2、局部配置:把它放到@FeignClient这个注解中:

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration.class)

重启order-service,访问网址后查看控制台的日志,除了SQL语句之外,还有关于Feign的日志信息(只有请求行和相应行)

性能优化

Feign其实性能一直很不错了,但是还是可以被优化,Feign底层的客户端实现:

URLConnection:默认实现,不支持连接池
Apache HttpClient:支持连接池
OKHttp:支持连接池

Feign底层还是会用到其他的客户端,默认使用URLConnection,但是它不支持连接池,这就会使得性能不是太好。因此更推荐使用其他两种。

Feign的性能优化主要包括:

使用连接池代替默认的URLConnection
日志级别,最好用BASIC或NONE,日志级别太高也会造成一些性能损耗

将URLConnection换成Apache HttpClient:
1、引入依赖:

	<!--引入HttpClient依赖--><dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId></dependency>

2、配置连接池:

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

其中,最大连接数和单个路径最大连接数并不能那么容易确定,具体的连接数需要根据业务的情况,对于不同的业务,可以用jmeter进行压力测试。

Feign最佳实践

分析

方式一:继承

给消费者的FeignClient和提供者的controller定义统一的父接口作为标准

乍一看还是有点抽象的,但是我们可以打开一下order-service的UserClient接口与user-service的UserController:
在这里插入图片描述
在这里插入图片描述
这两个的函数其实是差不多的,因为消费者要通过Feign解析网址请求,就需要带上相应的信息(请求方式、网址、参数等),而提供者则需要提供正确的方式给消费者,因此信息上两者基本上都是差不多的。
所以理论上可以定义一个统一的父接口来作为标准。

public interface UserAPI{@GetMappingUser findById(@PathVariable("id") Long id);
}

而消费者和提供者只需要分别继承和实现这个接口就可以了。
但是这种方式有一定的问题,Spring官方也不推荐让客户端和服务器端共用一个接口,因为这样的耦合度太高了。

方式二:抽取

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

解析一下,在之前的代码中,order-service的UserClient会去调用user-service中的UserController,但是如果还有很多模块的UserClient都要调用,可能就会有很多地方重复写了,因此可以专门定义一个feign-api,在里面声明UserClient,并且涉及到的实体类、默认配置都在feign-api中实现。而order-service要使用的时候,只需要引入feign-api的依赖就可以了。

实现

这里将会实现方式二,步骤如下:
1、新建module,命名为feign-api,然后引入feign的starter依赖

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

2、将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中
在这里插入图片描述
上面拥有的部分,在order-service里面都可以直接删除了,以后需要直接去用feign-api里面的东西就可以了。

3、在order-service中引入feign-api的依赖

	<dependency><!--groupId是你创建api的这个module时候的相关包--><groupId>com.wang</groupId><artifactId>feign-api</artifactId><version>1.0</version></dependency>

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

5、重启测试

运行后发现会报错,查看报错信息:
在这里插入图片描述
没有找到UserClient的对象,但是编译没有报错,只是运行报错了,查看OrderService:
在这里插入图片描述
可以想到,Spring没有获得这个容器的对象,这种情况的发生是因为扫描包出现了问题,只是因为启动类指定的Mapper是在cn.itcast.order下面的,然而UserClient是在cn.itcast.feign下面的。
在这里插入图片描述
简单粗暴的解决方式是直接把MapperScan扫描范围扩大,但是这肯定是不合适的,启动类应该默认扫描的范围就是所在的包下面的,应该想想别的办法。

方式一:指定FeignClient所在包(全盘拿来)

@EnableFeignClients(basePackages = "cn.itcast.feign.clients", defaultConfiguration = DefaultFeignConfiguration.class)

方式二:指定FeignClient字节码(精准定位,推荐方案)

@EnableFeignClients(clients = {UserClient.class}, defaultConfiguration = DefaultFeignConfiguration.class)

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

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

相关文章

蓝桥杯青少年创意编程大赛:激发少儿编程潜能,培养未来科技之星

随着科技的飞速发展&#xff0c;编程已经成为了当今世界的一项重要技能。为了培养更多的编程人才&#xff0c;蓝桥杯官网显示&#xff0c;蓝桥杯青少年创意编程大赛应运而生。作为国内有影响力的少儿编程赛事之一&#xff0c;蓝桥杯青少年创意编程大赛旨在激发青少年对编程的兴…

​Portkey AI网关:一个用来连接多种人工智能模型的开源工具

简介 它允许开发者通过一个简单的API接口来访问超过100种不同的大语言模型。包括OpenAI、Anthropic、Mistral、LLama2、Anyscale、Google Gemini等。安装体积只有45kb&#xff0c;处理速度提升了9.9倍&#xff0c;可以在多个不同的AI模型中来回切换。可以根据自己的需要进行灵…

找不到mfc100.dll的解决方法,怎么修复mfc100.dll文件

当我们在使用电脑时&#xff0c;时常可能会遇到各类系统提示的错误信息。"找不到mfc100.dll" 就是这些错误之一&#xff0c;该错误提示会妨碍我们执行一些应用程序或特定代码。为了帮助读者克服这个技术障碍&#xff0c;本篇文章将详尽阐明导致该问题的根本原因&…

【Flutter 问题系列第 80 篇】TextField 输入框组件限制可输入的最大长度后,输入的内容中包含表情符号时,获取输入的内容数还是会超出限制的问题

这是【Flutter 问题系列第 80 篇】&#xff0c;如果觉得有用的话&#xff0c;欢迎关注专栏。 博文当前所用 Flutter SDK&#xff1a;3.10.5、Dart SDK&#xff1a;3.0.5 一&#xff1a;问题描述 在输入用户名称、简介等内容时&#xff0c;一般我们都会限制输入框内最大可输入…

FFMPEG解码实时流,支持cpu、gpu解码

官网下载的ffmpeg目前只能下载到X64版本的库&#xff0c;具体编译请参考windows编译ffmpeg源码&#xff08;32位库&#xff09;_windows 32位ffmpeg动态库-CSDN博客 直接上代码 int VideoDecodeModule::Open(std::string strUrl) {AVFormatContext *pFormatCtx nullptr;AVCo…

电脑本地连接不见了怎么恢复?5个方法轻松解决问题!

“我在使用电脑时&#xff0c;突然发现我的本地连接不见了&#xff0c;这是怎么回事呢&#xff1f;有什么方法可以解决这个问题吗&#xff1f;” 电脑的本地连接是一种将电脑与局域网连接的方式。局域网是一种小型的网络&#xff0c;通常在建筑物内或地理位置相近的少量计算机之…

Python数据分析案例33——新闻文本主题多分类(Transformer, 组合模型) 模型保存

案例背景 对于海量的新闻&#xff0c;我们可能需要进行文本的分类。模型构建很重要&#xff0c;现在对于自然语言处理基本都是神经网络的方法了。 本次这里正好有一组质量特别高的新闻数据&#xff0c;涉及 教育 科技 社会 时政 财经 房产 家居 七大主题&#xff0c;基本涵盖…

Grafana(三)Grafana 免密登录-隐藏导航栏-主题变换

一. 免密登录 Grafana 的常用方式&#xff1a; 将配置好的Grafana图嵌入到系统页面中 为了实现可免登录访问&#xff0c;可以通过如下方式进行设置&#xff1a; 1. 修改Grafana配置文件 在Grafana的配置文件 /etc/grafana/grafana.ini 中&#xff0c;找到 [auth.anonymous] 配…

P9842 [ICPC2021 Nanjing R] Klee in Solitary Confinement 题解(SPJ!!!)

[ICPC2021 Nanjing R] Klee in Solitary Confinement 题面翻译 给定 n , k n,k n,k 和一个长为 n n n 的序列&#xff0c;你可以选择对区间 [ l , r ] [l, r] [l,r] 的数整体加上 k k k&#xff0c;也可以不加。最大化众数出现次数并输出。 题目描述 Since the travele…

MySQL命令大全和实例

文章目录 1. 数据库管理2. 表操作3. 数据操作&#xff08;CRUD&#xff09;4. 条件查询与排序5. 聚合函数和分组6. 用户权限管理7. 其他操作8. 视图操作9. 索引操作10. 子查询与连接查询11. 插入多行数据12. 删除满足特定条件的表中所有数据13. 清空表&#xff08;保留表结构&a…

rust跟我学五:是否安装双系统

图为RUST吉祥物 大家好,我是get_local_info作者带剑书生,这里用一篇文章讲解get_local_info是怎么得到检测双系统的。 首先,先要了解get_local_info是什么? get_local_info是一个获取linux系统信息的rust三方库,并提供一些常用功能,目前版本0.2.4。详细介绍地址:[我的Ru…

IOS-高德地图路径绘制显示交通状况-Swift

本文基于&#xff1a;高德地图路径绘制进行了路径绘制的优化&#xff0c;添加了根据交通信息&#xff08;是否拥堵&#xff09;来显示路况&#xff0c;效果如图&#xff1a; 图标资源&#xff1a; custtexture_bad custtexture_green custtexture_slow custtexture_serio…

关于C语言整型提升的讲解

目录 1.什么是整型提升 2.整型提升的意义 3.整型提升是怎么提升的 4.整型提升的实例 1.什么是整型提升 C语言中的整型算术运算总是以缺省&#xff08;默认&#xff09;整型类型的精度来进行的。为了获得这个精度&#xff0c;表达式中的字符和短整型操作数在使用之前会被转换…

web练习2

需求 1.计算用户指定的数值内的奇数和。例如用户输入的是10则计算13579的和 <!doctype html> <html lang"en"> <head><meta charset"utf-8"><title>作业1</title></head> <body> <script>//计算用…

使用 Python 创造你自己的计算机游戏(游戏编程快速上手)第四版:第十五章到第十八章

十五、反转棋游戏 原文&#xff1a;inventwithpython.com/invent4thed/chapter15.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 在本章中&#xff0c;我们将制作反转棋&#xff0c;也称为黑白棋或奥赛罗。这个双人棋盘游戏是在网格上进行的&#xff0c;因此我们…

2024“华数杯”(A题)放射性 Tritium 污染问题国际大学生数学建模竞赛| 建模秘籍文章代码思路大全

铛铛&#xff01;小秘籍来咯&#xff01; 小秘籍希望大家都能轻松建模呀&#xff0c;华数杯也会持续给大家放送思路滴~ 抓紧小秘籍&#xff0c;我们出发吧~ 完整内容可以在文章末尾领取&#xff01; 问题重述&#xff1a; 2024 “Huashu Cup” 国际数学建模大赛 - Proble…

机器学习平台建设(一)

一、概述 下图是较简化的机器学习平台架构&#xff0c;概括了机器学习平台的主要功能和流程。本章会进行简要介绍&#xff0c;在功能章节再展开详述。机器学习最主要的三个步骤可概括为&#xff1a;数据处理、建模以及部署。 数据处理&#xff0c;即所有和数据相关的工作&…

一种基于YOLO改进的高效且轻量级的表面缺陷检测网络, NEU-DET和GC10-DET涨点明显

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文摘要&#xff1a;一种基于YOLO改进的高效且轻量级的表面缺陷检测&#xff0c; 在NEU-DET和GC10-DET任务中涨点明显 目录 1.轻量且高效的YOLO 1.1 SCRB介绍 1.1.1 ScConv介绍 1.2 GSConvns 1.3 od_mobilenetv2_050 1.4 对应ya…

linux多进程基础(6):setitimer(间隔定时器)和signal(信号处理函数)

1.setitimer函数 setitimer函数用于设置一个间隔定时器,它会在指定的时间间隔到达时向进程发送一个信号。其定义如下: #include <sys/time.h> int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value); 该函数一共有三个参数,其…

2024年华数杯国际赛A题赛题

问题A&#xff1a;来自日本的放射性废水 背景 2011年3月&#xff0c;日本东海岸发生的地震引发了福岛第一核电站的事故。一场大规模海啸摧毁了该核电站的冷却系统&#xff0c;导致三个核反应堆熔毁&#xff0c;核燃料碎片熔化。为了冷却熔化的核燃料&#xff0c;海水不断地注入…