SpringCloud微服务 【实用篇】| http客户端Feign

目录

一:http客户端Feign

1. Feign替代RestTemplate

2. 自定义配置

3. Feign性能优化

4. 最佳实践


前言 

前些天突然发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家,感兴趣的同学可以进行学习人工智能学习网站

一:http客户端Feign

1. Feign替代RestTemplate

RestTemplate方式调用存在的问题

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

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

存在下面的问题:

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

②参数复杂URL难以维护;

Feign的介绍

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

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

定义和使用Feign客户端

第一步:引入依赖

在order-service服务的pom文件中引入openfeign的依赖

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

 第二步:添加注解,开启自动装配

在order-service的启动类添加@EnableFeginClients注解开启Fegin的功能

第三步:编写Fegin客户端

在order-service中新建一个UserClient接口,并添加@FeginClient注解里面用来封装所有对user-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("user-service") // 服务名称
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

这个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:

  • 服务名称:user-service

  • 请求方式:GET

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

  • 请求参数:Long id

  • 返回值类型:User

这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。

第四步:定义和使用Feign客户端

注:此时就完全废弃使用RestTempalte。修改order-service中的OrderService类中的queryOrderById方法,使用Feign客户端代替RestTemplate。

package cn.itcast.order.service;

import cn.itcast.order.client.UserClient;
import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

   /* // 注入RestTemplate
    @Autowired
    private RestTemplate restTemplate;*/

    // ------------------注入UserClient接口
    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.发出请求查询用户信息
        // String url = "http://localhost:8081/user/"+order.getUserId();
        /*String url = "http://user-service/user/"+order.getUserId();
        User user = restTemplate.getForObject(url, User.class);*/
        // 2. ---------------------利用Fegin发起http请求,查询用户
        User user = userClient.findById(order.getUserId());
        // 3. 把用户信息封装到order
        order.setUser(user);
        // 4.返回
        return order;
    }
}

也能执行成功,同时也能完成负载均衡!

2. 自定义配置

Feign运行自定义配置来覆盖默认配置,可以修改的配置如下:

类型

作用

说明

feign.Logger.Level

修改日志级别

包含四种不同的级别:

NONE、BASIC、HEADERS、FULL

feign.codec.Decoder

响应结果的解析器

http远程调用的结果做解析,

例如解析json字符串为java对象

feign.codec.Encoder

请求参数编码

将请求参数编码,便于通过http请求发送

feign.Contract

支持的注解格式

默认是SpringMVC的注解

feign.Retryer

失败重试机制

请求失败的重试机制,

默认是没有,不过会使用Ribbon的重试

一般我们需要配置的就是日志级别:

NONE:不记录任何日志信息,这是默认值。

BASIC:仅记录请求的方法,URL以及响应状态码和执行时间。

HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息。

FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

配置Feign日志有两种方式

第一种方式:配置文件方式

①全局生效:

feign:
  client:
    config: 
      default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

②局部生效:

feign:
  client:
    config: 
      user-service: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别

第二种方式:java代码方式

创建一个类,声明一个Bean

注:这个类没有声明注解,所以目前肯定还没有起作用!

package cn.itcast.order.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;

public class DefaultFeignConfiguration {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

①全局生效:放到@EnableFeignClients这个注解中(放到整个OrderApplication启动类上的注解)

// 放到启动类上,使用defaultConfiguratio属性指定上面的类
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class) 

②局部生效:放到@FeignClient这个注解中(放到具体UserFegin接口上的注解)

// 放到具体的接口上,使用configuratio属性指定上面的类
@FeignClient(value = "user-service", configuration = DefaultFeignConfiguration .class) 

Feign的日志配置总结:

方式一是配置文件,feign.client.config.xxx.loggerLevel

①如果xxx是default则代表全局;

②如果xxx是服务名称,例如userservice则代表某服务;

方式二是java代码配置Logger.Level这个Bean

①如果在@EnableFeignClients注解声明则代表全局;

②如果在@FeignClient注解中声明则代表某服务;

3. Feign性能优化

Fegin底层的客户端实现方式有三种:

①URLConnection:默认实现,不支持连接池;

②Apache HttpClient :支持连接池;

③OKHttp:支持连接池;

因此优化Feign的性能主要包括两个点:

①使用连接池代替默认的URLConnection

②日志级别,不要用full,最好用basic或none;

Feign的性能优化-连接池配置

第一步:order-service下引入fegin-httpClient依赖

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

第二步:application.yml配置连接池

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

Feign的优化总结:

1. 日志级别尽量用basic;

2. 使用HttpClient或OKHttp代替URLConnection;

①引入feign-httpClient依赖;

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

4. 最佳实践

所谓最近实践,就是使用过程中总结的经验,最好的一种使用方式。 通过仔细观察发现:Feign的客户端order-service与服务提供者user-service的controller代码非常相似!

feign客户端: UserClient接口

UserController:

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

第一种方式:继承方式

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

优点:

①简单,实现了代码共享;

缺点:

①服务提供方、服务消费方紧耦合;

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

第二种方式:抽取方式

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

问题:假如现在有两个微服务都需要查询user-service,此时order-service和pay-service各写各的Client,造成了代码重复!

解决:都不用写,服务提供者提供一个API:把Client实体类配置等全都写好;将来消费者order-service和pay-service想要使用的话直接引依赖的jar包,然后直接调!

抽取Client步骤

第一步:先创建一个Modul,命名为fegin-api,然后引入openfegin的start依赖

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

第二步:将order-service中编写的UserClient(原来定义的接口)、User(实体类)、DefaultFeginConfiguration(配置日志的类)都复制到fegin-api项目中

第三步:在order-service中引入fegin-api依赖

首先,删除order-service中的UserClient、User、DefaultFeignConfiguration等类或接口。 然后在order-service的pom文件中中引入feign-api的依赖:

 <!--引入feign统一api-->
<dependency>
    <groupId>cn.itcast.demo</groupId>
    <artifactId>fegin-api</artifactId>
    <version>1.0</version>
</dependency>

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

第五步:重启测试

思考:此时报错找不到UserClient,明明我们注入的时候没有问题;此时是ComponentScan注解的范围问题。这是因为UserClient现在在cn.itcast.clients包下,而order-service的@EnableFeignClients注解是在cn.itcast.order包下,不在同一个包,无法扫描到UserClient。

解决扫描包的问题:在@EnableFeignClients主类上添加包扫描

方式一:在启动类上使用basePackages属性指定Feign应该扫描的包

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class, basePackages = "cn.itcast.client")
public class OrderApplication {
}

方式二:在启动类上使用client属性指定某个需要加载的Client接口

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

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

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

相关文章

开启三层交换机DHCP服务

二层交换机上不需要配置任何东西&#xff0c;只需要在pc机上开启dhcp服务&#xff0c;配置好LSW1后就可以自动获取到IP地址。 sys Enter system view, return user view with CtrlZ. [Huawei]sys sw1 [sw1]dhcp enable Info: The operation may take a few seconds. Please wai…

MES管理系统在生产计划排程中的应用与价值

随着制造业市场竞争的日益激烈和客户需求的多样化&#xff0c;传统的生产计划排程方式已经无法满足企业的需求。为了提升生产计划的效率和准确性&#xff0c;越来越多的企业开始引入MES管理系统这一先进的工具。那么&#xff0c;MES管理系统到底是什么&#xff0c;又是如何解决…

基于c++版本的数据结构改-python栈和队列思维总结

##栈部分-&#xff08;叠猫猫&#xff09; ##抽象数据类型栈的定义&#xff1a;是一种遵循先入后出的逻辑的线性数据结构。 换种方式去理解这种数据结构如果我们在一摞盘子中取到下面的盘子&#xff0c;我们首先要把最上面的盘子依次拿走&#xff0c;才可以继续拿下面的盘子&…

Nodejs+vue+ElementUi自动排课系统

使用自动排课系统分为管理员和学生、教师三个角色的权限子模块。 管理员所能使用的功能主要有&#xff1a;首页、个人中心、学生管理、教师管理、班级信息管理、专业信息管理、教室信息管理、课程信息管理、排课信息管理、系统管理等。 学生可以实现首页、个人中心、排课信息管…

uni-app 微信小程序之新增 添加小程序的交互

文章目录 1. 实现效果2. 提示组件 1. 实现效果 2. 提示组件 在 components 中新增 struggler-uniapp-add-tip 提示添加小程序 组件默认展示&#xff0c;通过点击将 SHOW_TIP 存储本地进行隐藏 <template><view><view class"uni-add-tips-box" v-if&…

【LeetCode】2629. 复合函数

复合函数 题目题解 题目 请你编写一个函数&#xff0c;它接收一个函数数组 [f1, f2, f3&#xff0c;…&#xff0c; fn] &#xff0c;并返回一个新的函数 fn &#xff0c;它是函数数组的 复合函数 。 [f(x)&#xff0c; g(x)&#xff0c; h(x)] 的 复合函数 为 fn(x) f(g(h(x…

深度学习在单线性回归方程中的应用--TensorFlow实战详解

深度学习在单线性回归方程中的应用–TensorFlow实战详解 文章目录 深度学习在单线性回归方程中的应用--TensorFlow实战详解1、人工智能<-->机器学习<-->深度学习2、线性回归方程3、TensorFlow实战解决单线性回归问题人工数据集生成构建模型训练模型定义损失函数定义…

bpftrace原理与使用方法

Bpftrace 概念和原理bpftrace安装bpftrace 语法结构bpftrace 变量内置变量自定义变量Map变量 内置函数Bpftrace操作案例文件系统磁盘进程内存 bpftrace是一种基于eBPF&#xff08;Extended Berkeley Packet Filter&#xff09;的跟踪工具&#xff0c;用于在Linux系统中进行动态…

金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞复现 [附POC]

文章目录 金山终端安全系统V9.0 update_software_info_v2.php处SQL注入漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议参考链接&#xff1a; 金山终端安全系统V9.0 update_software_info_v2.php处…

国产麒麟操作系统部署记录

前提&#xff1a;部署项目首先要安装各种软件&#xff0c;在内网环境下无法在线下载。 思路&#xff1a;首先部署一台能上网的系统&#xff0c;在此系统下只下载包&#xff0c;然后传到另一台内网系统下进行安装&#xff1b; 1、最开始yum未安装&#xff0c;因此需要先安装yu…

Leetcode每日一题学习训练——Python3版(到达首都的最少油耗)

版本说明 当前版本号[20231205]。 版本修改说明20231205初版 目录 文章目录 版本说明目录到达首都的最少油耗理解题目代码思路参考代码 原题可以点击此 2477. 到达首都的最少油耗 前去练习。 到达首都的最少油耗 ​ 给你一棵 n 个节点的树&#xff08;一个无向、连通、无环…

7nm项目之顶层规划——01数据导入

1.创建workspace 创建workspace后&#xff0c;在其目录下产生。 CORTEXA53.json文件是将有默认配置的文件master.json、有library的.config.json文件、tunes下CORTEXA53.tunes.json文件合并 注&#xff1a;tunes下的CORTEXA53.tunes.json文件可以覆盖一些master.json的设置…

企业定制CRM系统:不可忽视的关键功能

虽然市场上有许多成熟的CRM系统供企业选择&#xff0c;但是市场上现有的标准化CRM系统可能无法满足那些有着独特需求的企业。企业想要拥有适合自身业务的CRM系统就需要进行CRM系统定制。那么&#xff0c;企业如何定制CRM系统要注意哪些功能&#xff1f; 一、为什么企业需要CRM…

23款奔驰GLC260L升级原厂360全景影像 超广角的视野

360全景影像影像系统提升行车时的便利&#xff0c;不管是新手或是老司机都将是一个不错的配置&#xff0c;无论是在倒车&#xff0c;挪车以及拐弯转角的时候都能及时关注车辆所处的环境状况&#xff0c;避免盲区事故发生&#xff0c;提升行车出入安全性。 360全景影像包含&…

synchronized关键字-监视器锁(monitor lock)

这就是我们上一篇中代码提到的加锁的主要方式,本质上是调用系统api进行加锁,系统api本质是靠cpu特定指令加锁. synchronize的特性 互斥性 synchronized会起到互斥效果,某个线程执行到某个对象的synchronized中时,,其它线程如果也执行到同一个对象synchronized就会阻塞等待(锁…

什么是可靠性测试,常见的可靠性测试标准有哪些?

1、可靠性试验背景介绍 为了测定、验证或提高产品可靠性而进行的试验称为可靠性试验&#xff0c;它是产品可靠性工作的一个重要环节。 2、通常&#xff0c;对产品进行可靠性试验的目的如下&#xff1a; (1)在研制阶段使产品达到预定的可靠性指标。为了使产品能达到预定的可靠性…

Python绘图坐标轴数字要求三位分节的处理方法

比如说1000&#xff0c;用三位分节法的写法就是1 000&#xff0c;咱们操作的时候可以先式化字符串&#xff0c;用千位分隔符表示数字就是1,000&#xff0c;再把逗号换成空格。 import matplotlib.pyplot as plt import matplotlib.ticker as ticker# 示例数据 x [1000, 2000, …

品牌要随时监测电商价格现实吗

电商渠道中的价格信息如果存在低价&#xff0c;那需要及时治理&#xff0c;否则低价会蔓延开来&#xff0c;影响渠道的发展&#xff0c;所以在治理前的监测工作非常重要&#xff0c;监测越全面&#xff0c;越准确&#xff0c;品牌进行渠道管控时会更有方向感&#xff0c;治理成…

Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal

目录 笔记后续的创新方向摘要引言 Lattice-Based Blind Signatures: Short, Efficient, and Round-Optimal CCS 2023 笔记 该文档提出了一种基于格子密码学的2轮盲签名协议。该协议是四舍五入最优的&#xff0c;签名大小为 22 KB&#xff0c;使其比其他基于格的方案更短。该文…

竞赛活动过程中评委亮灯是如何实现的

选秀节目中用到的那种评委爆灯效果要通过软件和硬件一起实现&#xff0c;软件实现在新一轮开始时&#xff0c;统一灭灯&#xff0c;评委通过按钮触发软件打开相应的灯&#xff0c;并自动发出声音。其实用到的物料包括&#xff1a;软件、按钮、灯、工业控制器。软件是核心&#…