首页 > 其他分享 >SpringCloud篇(服务拆分/远程调用 - 远程调用 - Fegin)

SpringCloud篇(服务拆分/远程调用 - 远程调用 - Fegin)

时间:2024-11-12 22:46:05浏览次数:3  
标签:Feign 调用 service Fegin feign order 日志 远程 请求

目录

一、为什么要使用Feign远程调用

二、什么是Feign

三、Feign替代RestTemplate

1. 引入依赖

2. 添加注解

3. 编写Feign的客户端

4. 测试

5. 总结

四、自定义配置

1. 配置文件方式

2. Java代码方式

五、Feign性能优化

1. 简介

2. 引入依赖

3. 配置连接池

4. 结论

六、最佳实践

1. 起初

2. 继承方式

3. 抽取方式

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

4.1. 抽取

4.2. 在order-service中使用feign-api

4.3. 重启测试

4.4 解决扫描包问题


一、为什么要使用Feign远程调用

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

存在下面的问题:

  • 代码可读性差,编程体验不统一
  • 参数复杂URL难以维护

二、什么是Feign

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.cloud.order.client;

import com.cloud.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:

这样写代码,让我们看起来非常优雅,解决了硬编码问题!

测试地址:http://localhost:8080/order/101

5. 总结

Fegin 使用步骤

① 引入依赖

② 添加@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即可

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

Feign的日志的级别分为四种:

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

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  {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class) 

如果是局部生效,则把它放到对应的@FeignClient这个注解中:

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

五、Feign性能优化

1. 简介

Feign底层发起http请求,依赖于其它的框架。

其底层客户端实现包括:

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

因此提高Feign的性能主要手段就是使用连接池代替默认的 URLConnection

使用连接池的好处:

连接池可以减少连接的创建和销毁这个性能损耗,因为我们知道每次连接都要进行三次握手、四次挥手,

这样将会导致效率极其低下且浪费资源,

我们将不采取默认的客户端实现,而是采用支持连接池的客户端实现,从而达到性能优化的目的

这里我采用的是 Apache 的 HttpClient 来演示

2. 引入依赖

在order-service的pom文件中引入Apache的HttpClient依赖:

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

    <artifactId>feign-httpclient</artifactId>

</dependency>

3. 配置连接池

在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:

4. 结论

  1. 日志级别尽量用basic
  2. 使用HttpClient或OKHttp代替URLConnection

① 引入feign-httpClient依赖

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

六、最佳实践

1. 起初

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

feign客户端:

UserController:

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

2. 继承方式

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

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

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

优点:

  • 简单
  • 实现了代码共享

缺点:

  • 服务提供方、服务消费方紧耦合
  • 参数列表中的注解映射并不会继承,因此Controller中必须再次声明方法、参数列表、注解

3. 抽取方式

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

费者使用。

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

接使用。

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

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

4.2. 在order-service中使用feign-api

首先,删除order-service中的UserClient、User、DefaultFeignConfiguration等类或接口。

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

<dependency>
    <groupId>com.cloud.demo</groupId>

    <artifactId>feign-api</artifactId>

    <version>1.0</version>

</dependency>

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

4.3. 重启测试

重启后,发现服务报错了:

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

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

UserClient。

4.4 解决扫描包问题

方式一:

指定Feign应该扫描的包:

@EnableFeignClients(basePackages = "com.cloud.feign.clients")

方式二:

指定需要加载的Client接口:

@EnableFeignClients(clients = {UserClient.class})

标签:Feign,调用,service,Fegin,feign,order,日志,远程,请求
From: https://blog.csdn.net/qq_51226710/article/details/143726042

相关文章

  • 调用分页的 API 接口,如何快速返回全部数据?
    当调用分页的API接口并希望快速返回全部数据时,可以采用以下策略:一、优化网络请求并发请求原理:大多数现代编程语言都支持并发编程。通过并发地发送多个分页请求,可以大大减少获取全部数据所需的总时间。例如,在Python中,可以使用asyncio库(对于异步操作)或者concurrent.fu......
  • 调用百度的接口,实现多种语言的翻译
    先把工具类下载下来,直接拖进去:/***Base64工具类*/publicclassBase64Util{privatestaticfinalcharlast2byte=(char)Integer.parseInt("00000011",2);privatestaticfinalcharlast4byte=(char)Integer.parseInt("00001111",2);p......
  • 高级语言调用C接口(一)基础类型与基础类型指针的对应关系
    基础类型C变量类型Java变量类型C#变量类型python变量类型arkts变量类型备注intintintc_intnumberunsignedintlonguintc_uintnumbershortshortshortc_shortnumberunsignedshortintushortc_ushortnumberlongintintc_longnumber32位系统中,C中的long型占4字节,可以当作in......
  • Lec 04 系统调用
    Lec04系统调用(参考来源:上海交通大学并行与分布式系统研究所+操作系统课程ppt)CreativeCommonsAttribution4.0LicenseContents4.1系统调用硬件提供了一对指令svc/eret指令在用户态/内核态间切换系统调用(1)用户与操作系统之间,类似于过程调用的接口(2)通过受限的......
  • vm安装ubuntu 20.04 server并用vscode进行ssh远程连接
    最近写专业课作业需要用到vscode进行SSH连接ubuntuserver,自己摸索了一会终于实现效果,秉承着“取之于网络,还之于网络”的开源精神写了一篇总结博客,欢迎大家参考,如有不足之处也欢迎大家指出。文章参考:VSCodeSSH远程连接Ubuntu_visualstudio连接到本地unbuntu远程系统-CSDN博......
  • 【Playwright + Python】系列(九)Playwright 调用 Chrome 插件,小白也能事半功倍
    哈喽,大家好,我是六哥!今天我来给大家分享一下如何使用playwight调用chrome插件,面向对象为功能测试及零基础小白,我尽量用大白话的方式举例讲解,力求所有人都能看懂,建议大家先收藏,以免后面找不到。......
  • 开源三代示波器的高速波形刷新方案开源,支持VNC远程桌面,手机,Pad,电脑均可访问(2024-11-11
    说明:1、本来这段时间是一年一度Hackaday硬件设计开源盛宴,但hackaday电子大赛在去年终结了。所以我开源个我的吧。2、三代示波器的高速波形刷新方案,前两年就做好了,这两年忙H7-TOOL的更新比较多,三代示波器的更新就搁置了。但刷新方案是没问题的,开源分享给大家。3、V7板子主频400M......
  • Idea调用WebService
    Idea调用WebService​WebService是一种基于网络的技术,它允许不同的应用程序在互联网上相互通信。要进行WebService对接,以下是一些关键步骤和注意事项:一、理解WebService的基本概念定义:WebService是一种基于标准化协议和格式的应用程序接口(API),它使用XML和HTTP来进行通信......
  • LangGraph进阶:条件边与工具调用Agent实现
    在前两篇文章中,我们讨论了LCEL和AgentExecutor的局限性,以及LangGraph的基础概念。今天,我们将深入探讨LangGraph的高级特性,重点关注条件边的使用和如何实现一个完整的工具调用Agent。条件边的高级用法条件边是LangGraph中最强大的特性之一,它允许我们基于状态动态决定执行流......
  • vue跨页面调用函数
    1、在utils文件夹下创建中间件middle.js//中间件实现跨页面调用方法importVuefrom'vue'exportdefaultnewVue2、被调用页面代码<template></template><script>importMiddlefrom'@/utils/middle.js';exportdefault{mounted(){let......