03-基于Feign的远程调用,详解Feign的自定义配置和优化,创建Feign模块

Feign远程调用

Feign替代RestTemplate

利用RestTemplate发起远程调用的代码的缺点

  • 代码可读性差编程体验不统一 , 面对参数复杂的URL难以维护
String url = "http://user-service/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);

Feign是一个声明式的http客户端,我们只需要把发请求需要的信息声明出来如请求方式,请求路径,请求参数等信息,剩下的由Fegin帮我们完成http请求的发送

第一步引入依赖:在order-service模块的pom文件中引入Feign的依赖spring-cloud-starter-openfeign

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

第二步开启Feign的功能:在order-service模块的启动类上添加@EnableFeignClients注解

第三步编写Feign客户端代码:在order-service模块的com.itcast.order.client包下新建UserClient接口,基于SpringMVC的注解来声明远程调用的信息

请求信息举例
请求的服务名称user-service
请求的方式GET或POST
请求的路径/user/{id}
请求的参数如用户的d
请求响应的返回值类型如User对象
// 封装了对user-service服务的远程调用的信息
@FeignClient("user-service")
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

第四步编写业务逻辑代码: 在order-service模块的OrderService类中的queryOrderById方法使用Feign客户端代替RestTemplate

第五步: 使用浏览器发起请求http://localhost:8080/order/101实现Fegin的远程调用

  • 观察user-service服务对应的多个实例的控制台信息,可以发现Feign不仅实现了远程调用还实现了负载均衡功能(因为内部集成了Ribbo组件)
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    // 注入Feign的客户端
    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
        // 1. 查询订单
        Order order = orderMapper.findById(orderId);
        // 2. 利用Feign的客户端发起http请求访问user-service查询用户信息
        User user = userClient.findById(order.getUserId());
        // 3. 封账user对象到order对象的user属性中
        order.setUser(user);
        // 4. 返回order对象
        return order;
    }
}

Feign的自定义配置

Feign可以支持很多的自定义配置但一般情况下默认值就能满足我们的使用,如果需要自定义配置只需要创建自定义的@Bean覆盖默认的Bean即可

类型作用说明
feign.Logger.Level修改日志级别,包含四种不同的级别NONE(默认值,不记录任何日志信息,提升性能)
BASIC(仅记录请求的方法,URL以及响应状态码和执行时间)
HEADERS(在BASIC的基础上额外记录了请求和响应头的信息)
FULL(记录所有请求和响应的明细包括头信息、请求体、元数据,调试时使用)
feign.codec.Decoder响应结果的解析器http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder请求参数编码将请求参数编码便于通过http请求发送
feign. Contract支持的注解格式默认是SpringMVC的注解
feign. Retryer失败重试机制(某个服务实例查询不到就换个服务实例)请求失败的重试机制(默认是没有),不过会使用Ribbon的重试

基于order-service模块的application,yml配置文件自定义日志配置

# 针对某个微服务的配置
feign:  
  client:
    config: 
      user-service: # 针对配置的服务名称
        loggerLevel: FULL #  日志级别
# 针对所有服务的配置        
feign:  
  client:
    config: 
      default: # default就是全局配置针对所有服务
        loggerLevel: FULL #  日志级别         

基于Java代码自定义日志配置: 先声明一个配置类(不用加注解), 然后声明一个Logger.Level的对象

  • 全局生效: 将配置类放到启动类的@EnableFeignClients注解中@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)
  • 局部生效: 将配置类放到对应@FeignClient注解中@FeignClient(value = "user-service", configuration = DefaultFeignConfiguration.class)
public class DefaultFeignConfiguration {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; //日志级别设置为 BASIC
    }
}

Feign的使用优化

Feign底层发起http请求需要依赖于其他框架, 其底层客户端实现包括三种,提高Frign的性能主要手段就是使用连接池代替默认的URLConnection

  • URLConnection: Feign底层默认会使用JDK自带的客户端但不支持连接池
  • Apache HttpClient: 支持连接池
  • OKHttp: 支持连接池

优化Feign性能的两种方式

  • 日志级别尽量使用BASIC或NONE
  • 使用支持连接池的HttpClient或OKHttp代替URLConnection

第一步引入依赖: 在order-service模块的pom文件中引入Apache的HttpClient依赖

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

第二步配置连接池: 在order-service模块的application.yml文件中添加配置,开启httpclient功能设置相关的连接池参数

feign:
  client:
    config:
      default: # default全局的配置
        logger-level: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持(默认是true,即如果引入了HttpClient依赖就可以使用)
    max-connections: 200 # 请求的最大的连接数
    max-connections-per-route: 50 # 分配给每个请求路径的最大连接数	

继承(面向契约思想)

由于Feign的客户端方法与服务提供者user-servie模块中UserController中对应的接口方法的代码除了方法名不同其余几乎一模一样

  • order-service模块基于Feign的客户端UserClient中定义的方法发起请求,user-servie模块接收并处理order-service模块发起的请求
@FeignClient(value = "user-service",configuration = DefaultFeignConfiguration.class)
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}
@RestController
@RequestMapping("/user")
@RefreshScope
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id) {
        return userService.queryById(id);
    }
}

第一步: 通过继承来共享Feign客户端和Controller中相同的代码,先定义一个API接口, 通过定义接口方法并基于SpringMVC注解的方式声明发送Http请求的信息

public interface UserAPI{
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id); 
}

第二步: Feign的客户端UserClient继承定义好的UserAPI接口,而UserController实现UserAPI接口

@FeignClient(value = "user-service")
public interface UserClient extends UserAPI{}
@RestController
public class UserController implents UserAPI{
    public User findById(@PathVariable("id") Long id){
        // ...实现业务逻辑
    }
}

基于继承方式的优缺点

  • 优点: 简单并且实现了代码共享

  • 缺点: 服务提供方和服务消费方紧耦合, 参数列表中的注解映射并不会继承,所以Controller中需要再次声明方法、参数列表、注解

基于抽取的最佳实践

Feign的客户端抽取为独立模块,并且把接口有关的POJO和默认的Feign配置都放到这个模块中,服务消费者引用该依赖包后即可使用

  • 缺点: 如果某个微服务只想要使用模块的部分功能也要把整个模块引入

在这里插入图片描述

第一步: 创建一个新的modulefeign-api模块并在pom.xml文件中引入feign的starter依赖spring-cloud-starter-openfeign

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

第二步: 将order-service模块中编写的UserClient、User、DefaultFeignConfiguration都转移到feign-api模块中
第三步: 在order-service模块中的pom.xml文件中引入我们自己编写的依赖feign-api

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

解决自动注入失败问题: order-service模块的@EnableFeignClients注解是在cn.itcast.order包下显然无法扫描到cn.itcast.feign.clients包下的UserClient

// 方式一:指定Feign应该扫描的包
@EnableFeignClients(basePackages = "cn.itcast.feign.clients")

// 方式二: 指定需要加载的XxxClient接口
@EnableFeignClients(clients = {UserClient.class})

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

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

相关文章

【Proteus仿真】【Arduino单片机】多功能数字时钟设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用PCF8574、LCD1602液晶、DS1302温度传感器、DS1302时钟、按键、蜂鸣器等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示当前日期…

【DevOps】Git 图文详解(六):Git 利器 - 分支

Git 利器 - 分支 1.分支 Branch2.分支指令 &#x1f525;3.分支的切换 checkout4.合并 merge & 冲突4.1 &#x1f538; 快速合并&#xff08;Fast forward&#xff09;4.2 &#x1f538; 普通合并4.3 处理冲突 <<<<<<< HEAD 5.变基 rebase 分支是从主…

【C++进阶之路】第十一篇:C++的IO流

文章目录 1. C语言的输入与输出2. 流是什么3. CIO流3.1 C标准IO流3.2 C文件IO流 4.stringstream的简单介绍 1. C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输入设备(键盘)读取数据&#xff0c;并将值存放在变量中。prin…

【鸿蒙应用ArkTS开发系列】- 灌水区,鸿蒙ArkTs开发有问题可以在该帖中反馈

大家好, 这是一篇水贴&#xff0c;给大家提供一个交流沟通鸿蒙开发遇到问题的地方。 新增新增这个文章呢&#xff0c;大家在开发使用ArkTS开发鸿蒙应用或者鸿蒙服务的时候&#xff0c;有遇到疑问或者问题&#xff0c;可以在本文章评论区提问&#xff0c;我看到了如果知道怎么…

【内网穿透】在Ubuntu搭建Web小游戏网站,并将其发布到公网访问

目录 前言 1. 本地环境服务搭建 2. 局域网测试访问 3. 内网穿透 3.1 ubuntu本地安装cpolar 3.2 创建隧道 3.3 测试公网访问 4. 配置固定二级子域名 4.1 保留一个二级子域名 4.2 配置二级子域名 4.3 测试访问公网固定二级子域名 前言 网&#xff1a;我们通常说的是互…

Ubuntu文件系统损坏:The root filesystem on /dev/sda5 requires a manual fsck

前言 Ubuntu在启动过程中&#xff0c;经常会遇到一些开故障&#xff0c;导致设备无法正常开机&#xff0c;例如文件系统损坏等。 故障描述 Ubuntu系统启动过程中&#xff0c;出现以下文件系统损坏错误&#xff1a; 产生原因 该故障是由磁盘检测不能通过导致&#xff0c;可能是因…

竞赛 题目:基于深度学习的手势识别实现

文章目录 1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估 6 识别效果7 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的手势识别实现 该项目较为新颖&#xff0c;适合作为竞赛课题…

基于C#实现AC自动机算法

我要检查一篇文章中是否有某些敏感词&#xff0c;这其实就是多模式匹配的问题。当然你也可以用 KMP 算法求出&#xff0c;那么它的时间复杂度为 O(c*(mn))&#xff0c;c&#xff1a;为模式串的个数。m&#xff1a;为模式串的长度,n:为正文的长度&#xff0c;那么这个复杂度就不…

Macs Fan Control Pro:掌握您的Mac风扇,提升散热效率

在Mac的世界里&#xff0c;每一个细节都显得格外重要。而其中&#xff0c;风扇的控制与调节则显得尤为重要。然而&#xff0c;原生的Mac系统并不提供直观的风扇控制工具&#xff0c;这使得许多Mac用户在处理高负荷任务时&#xff0c;风扇无法有效地进行散热&#xff0c;导致机器…

TensorFlow实战教程(十八)-Keras搭建卷积神经网络及CNN原理详解

从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章详细讲解了Keras实现分类学习,以MNIST数字图片为例进行讲解。本篇文章详细讲解了卷积神经网络CNN原理,并通过Keras编写CNN实现了MNIST分类学习案例。基础性文章,希望对您有所帮助! 一…

体感互动游戏VR游戏AR体感游戏软件开发

随着科技的不断发展&#xff0c;体感互动游戏正逐渐成为游戏行业的一个重要趋势。这类游戏通过利用传感器、摄像头和运动控制器等技术&#xff0c;使玩家能够通过身体动作与游戏进行实时互动&#xff0c;极大地提升了娱乐体验。 1. 游戏设计与互动元素 体感互动游戏的核心在于…

使用kafka_exporter监控Kafka

prometheus 监控 kafka 常见的有两种开源方案,一种是传统的部署 exporter 的方式,一种是通过 jmx 配置监控, 项目地址: kafka_exporter:https://github.com/danielqsj/kafka_exporterjmx_exporter:https://github.com/prometheus/jmx_exporter本文将采用kafka_exporter方…

使用Navicat将SQL server数据库导入mysql数据库

使用Navicat将SQL server数据库导入mysql数据库 1、使用Navicat Premium打开MySql数据库&#xff0c;然后新建一个数据库名&#xff08;该数据库名称为需要从SqlServer数据库导过来的名称&#xff0c;mysql只有小写&#xff0c;不影响&#xff09; 比如需要将SqlServer数据库…

NGINX缓存详解之服务端缓存

服务端缓存 proxy cache属于服务端缓存,主要实现 nginx 服务器对客户端数据请求的快速响应。 nginx 服务器在接收到被代理服务器的响应数据之后,一方面将数据传递给客户端,另一方面根据proxy cache的配置将这些数据缓存到本地硬盘上。 当客户端再次访问相同的数据时,nginx…

谈谈你对mvc和mvvm的理解

MVC和MVVM是软件开发中两种常见的架构模式&#xff0c;各自有不同的优缺点。 MVC&#xff08;Model-View-Controller&#xff09;是一种经典的架构模式&#xff0c;将应用程序分为三个部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和…

中国城镇化时空分异及影响因素数据集(2010-2020)

基于《中国统计年鉴》、各省份统计年鉴及EPS全球统计数据库等相关统计数据&#xff0c;从人居生活、人文环境、人城关系等维度界定了城镇化内涵框架与指标体系&#xff0c;利用改进的熵值法计算综合评价指数&#xff0c;并运用泰尔指数、方差分解及地理探测器等方法&#xff0c…

ventoy安装操作系统

下载ventoy https://github.com/ventoy/Ventoy/releases/download/v1.0.96/ventoy-1.0.96-windows.zip 解压后执行 Ventoy2Disk 2、安装后将ISO放入U盘大的分区&#xff0c;通过U盘启动就可以识别到ISO镜像开始装系统

2021秋招-总目录

2021秋招-目录 知识点总结 预训练语言模型: Bert家族 1.1 BERT、attention、transformer理解部分 B站讲解–强烈推荐可视化推倒结合代码理解代码部分常见面试考点以及问题: word2vec 、 fasttext 、elmo;BN 、LN、CN、WNNLP中的loss与评价总结 4.1 loss_function&#xff1…

【Java】异常处理及其语法、抛出异常、自定义异常(完结)

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;Java ⭐每日一句&#xff1a;道阻且长&#xff0c;行则将至 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️ 文章目录 一.&#x1f510;异…

centos7卸载mongodb数据重新安装时无法安装的问题

如果卸载不干净直接用 sudo find / -name mongo 查询所有关于mongo的文件&#xff0c;然后一个个去删除。 当然最好的办法还是去看日志信息。 直接去查看日志信息 sudo cat /var/log/mongodb/mongod.log 根据提示信息说这个没有权限操作 直接删除即可&#xff0c;都是之前…