草庐IT

Spring Cloud Alibaba全家桶(四)——微服务调用组件Feign

小新要变强 2023-09-14 原文

前言

本文小新为大家带来 微服务调用组件Feign 的相关知识,具体内容包含什么是FeignSpring Cloud Alibaba快速整合OpenFeignSpring Cloud Feign的自定义配置及使用(包括:日志配置契约配置自定义拦截器实现认证逻辑超时时间配置客户端组件配置GZIP 压缩配置)等~

不仅跬步,无以至千里;不积小流,无以成江海。每天进步一点点,在成为强者的路上,小新与大家共同成长!

📌博主主页:小新要变强 的主页
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)

↩️本文上接:Spring Cloud Alibaba全家桶(三)——微服务负载均衡器Ribbon与LoadBalancer


目录

微服务调用组件Feign


JAVA 项目中如何实现接口调用?

  • (1)Httpclient

HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 Http 协议的客户端编程工具包,并且它支持 HTTP 协议最新版本和建议。HttpClient相比传统 JDK 自带的 URLConnection,提升了易用性和灵活性,使客户端发送 HTTP 请求变得容易,提高了开发的效率。

  • (2)Okhttp

一个处理网络请求的开源项目,是安卓端最火的轻量级框架,由 Square 公司贡献,用于替代
HttpUrlConnection 和 Apache HttpClient。OkHttp 拥有简洁的 API、高效的性能,并支持多种协议(HTTP/2 和 SPDY)。

  • (3)HttpURLConnection

HttpURLConnection 是 Java 的标准类,它继承自 URLConnection,可用于向指定网站发送GET 请求、POST 请求。HttpURLConnection 使用比较复杂,不像 HttpClient 那样容易使用。

  • (4)RestTemplate WebClient

RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。上面介绍的是最常见的几种调用接口的方法,我们下面要介绍的方法比上面的更简单、方便,它就是 Feign。

一、什么是Feign

Feign是Netflix开发的声明式、模板化的HTTP客户端,其灵感来自Retrofit、JAXRS-2.0以及WebSocket。Feign可帮助我们更加便捷、优雅地调用HTTP API。

Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。

Spring Cloud openfeign对Feign进行了增强,使其支持Spring MVC注解,另外还整合了Ribbon和Nacos,从而使得Feign的使用更加方便

🍀优势

Feign可以做到使用 HTTP 请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。它像 Dubbo 一样,consumer 直接调用接口方法调用 provider,而不需要通过常规的 Http Client 构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

二、Spring Cloud Alibaba快速整合OpenFeign

🍀(1)引入依赖

<!‐‐ openfeign 远程调用 ‐‐>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐starter‐openfeign</artifactId>
</dependency>

🍀(2)编写调用接口+@FeignClient注解

@FeignClient(value = "mall‐order",path = "/order")
public interface OrderFeignService {

  @RequestMapping("/findOrderByUserId/{userId}")
  public R findOrderByUserId(@PathVariable("userId") Integer userId);
}

🍀(3)调用端在启动类上添加@EnableFeignClients注解

@SpringBootApplication
@EnableFeignClients
public class MallUserFeignDemoApplication {
  public static void main(String[] args) {
    SpringApplication.run(MallUserFeignDemoApplication.class, args);
  }
}

🍀(4)发起调用,像调用本地方式一样调用远程服务

@RestController
@RequestMapping("/user")
public class UserController {

  @Autowired
  OrderFeignService orderFeignService;

  @RequestMapping(value = "/findOrderByUserId/{id}")
  public R findOrderByUserId(@PathVariable("id") Integer id) {
    //feign调用
    R result = orderFeignService.findOrderByUserId(id);
    return result;
  }
}

三、Spring Cloud Feign的自定义配置及使用

Feign 提供了很多的扩展机制,让用户可以更加灵活的使用。

1️⃣日志配置

有时候我们遇到 Bug,比如接口调用失败、参数没收到等问题,或者想看看调用性能,就需要
配置 Feign 的日志了,以此让 Feign 把请求信息输出来。

🍀(1)定义一个配置类,指定日志级别

// 注意: 此处配置@Configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置
public class FeignConfig {
  /**
 * 日志级别
 *  * @return
  */
  @Bean
  public Logger.Level feignLoggerLevel() {
    return Logger.Level.FULL;
  }
}

通过源码可以看到日志等级有 4 种,分别是:

  • NONE【性能最佳,适用于生产】:不记录任何日志(默认值)。
  • BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。
  • HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
  • FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据。

🍀(2)局部配置,让调用的微服务生效,在@FeignClient 注解中指定使用的配置类

🍀(3)在yml配置文件中执行 Client 的日志级别才能正常输出日志,格式是 “logging.level. feign接口包路径=debug”

logging:
  level:
  com.tuling.mall.feigndemo.feign: debug

测试: BASIC级别日志

补充: 局部配置可以在yml中配置

对应属性配置类:
org.springframework.cloud.openfeign.FeignClientProperties.FeignClientConfiguration

feign:
  client:
  config:
  mall‐order: #对应微服务
  loggerLevel: FULL

2️⃣契约配置

Spring Cloud 在 Feign 的基础上做了扩展,使用 Spring MVC 的注解来完成Feign的功能。原生的 Feign 是不支持 Spring MVC 注解的,如果你想在 Spring Cloud 中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud 中默认的是 SpringMvcContract。

Spring Cloud 1 早期版本就是用的原生Fegin。随着netflix的停更替换成了Open feign。

🍀(1)修改契约配置,支持Feign原生的注解

/**
* 修改契约配置,支持Feign原生的注解
* @return
*/
@Bean
public Contract feignContract() {
  return new Contract.Default();
}

注意: 修改契约配置后,OrderFeignService 不再支持springmvc的注解,需要使用Feign原生的注解

🍀(2)OrderFeignService 中配置使用Feign原生的注解

@FeignClient(value = "mall‐order",path = "/order")
public interface OrderFeignService {
  @RequestLine("GET /findOrderByUserId/{userId}")
  public R findOrderByUserId(@Param("userId") Integer userId);
}

🍀(3)补充,也可以通过yml配置契约

feign:
  client:
  config:
  mall‐order: #对应微服务
  loggerLevel: FULL
  contract: feign.Contract.Default #指定Feign原生注解契约配置

3️⃣自定义拦截器实现认证逻辑

public class FeignAuthRequestInterceptor implements RequestInterceptor {
  @Override
  public void apply(RequestTemplate template) {
    // 业务逻辑
    String access_token = UUID.randomUUID().toString();
    template.header("Authorization",access_token);
  }
}

@Configuration // 全局配置
public class FeignConfig {
  @Bean
  public Logger.Level feignLoggerLevel() {
    return Logger.Level.FULL;
  }
  /**
  * 自定义拦截器
  * @return
  */
  @Bean
  public FeignAuthRequestInterceptor feignAuthRequestInterceptor(){
    return new FeignAuthRequestInterceptor();
  }
}

测试:

补充: 可以在yml中配置

feign:
  client:
  config:
  mall‐order: #对应微服务
  requestInterceptors[0]: #配置拦截器
  com.tuling.mall.feigndemo.interceptor.FeignAuthRequestInterceptor

mall-order端可以通过 @RequestHeader获取请求参数,建议在filter,interceptor中处理

4️⃣超时时间配置

通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接的超时时间(ms),默认值是 2s;第二个是请求处理的超时时间(ms),默认值是 5s。

🍀(1)全局配置

@Configuration
public class FeignConfig {
  @Bean
  public Request.Options options() {
    return new Request.Options(5000, 10000);
  }
}

🍀(2)yml中配置

feign:
  client:
  config:
  mall‐order: #对应微服务
  # 连接超时时间,默认2s
  connectTimeout: 5000
  # 请求处理超时时间,默认5s
  readTimeout: 10000

补充说明: Feign的底层用的是Ribbon,但超时时间以Feign配置为准

测试超时情况:

返回结果:

5️⃣客户端组件配置

Feign 中默认使用 JDK 原生的 URLConnection 发送 HTTP 请求,我们可以集成别的组件来替换掉 URLConnection,比如 Apache HttpClient,OkHttp。

Feign发起调用真正执行逻辑:feign.Client#execute (扩展点)

🍀(1)配置Apache HttpClient

引入依赖:

<!‐‐ Apache HttpClient ‐‐>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign‐httpclient</artifactId>
<version>10.1.0</version>
</dependency>

然后修改yml配置,将 Feign 的 Apache HttpClient启用 :

feign:
  #feign 使用 Apache HttpClient 可以忽略,默认开启
  httpclient:
  enabled: true

关于配置可参考源码: org.springframework.cloud.openfeign.FeignAutoConfiguration

测试: 调用会进入feign.httpclient.ApacheHttpClient#execute

🍀(2)配置 OkHttp

引入依赖:

<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign‐okhttp</artifactId>
</dependency>

然后修改yml配置,将 Feign 的 HttpClient 禁用,启用 OkHttp,配置如下:

feign:
  #feign 使用 okhttp
  httpclient:
  enabled: false
  okhttp:
  enabled: true

关于配置可参考源码: org.springframework.cloud.openfeign.FeignAutoConfiguration

测试: 调用会进入feign.okhttp.OkHttpClient#execute

6️⃣GZIP 压缩配置

开启压缩可以有效节约网络资源,提升接口性能,我们可以配置 GZIP 来压缩数据:

feign:
  # 配置 GZIP 来压缩数据
  compression:
    request:
      enabled: true
      # 配置压缩的类型
      mime‐types: text/xml,application/xml,application/json
      # 最小压缩值
      min‐request‐size: 2048
    response:
      enabled: true

注意: 只有当 Feign 的 Http Client 不是 okhttp3 的时候,压缩才会生效,配置源码在FeignAcceptGzipEncodingAutoConfiguration

核心代码就是 @ConditionalOnMissingBean(type=“okhttp3.OkHttpClient”),表示Spring BeanFactory 中不包含指定的 bean 时条件匹配,也就是没有启用 okhttp3 时才会进行压缩配置。


后记

👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~

有关Spring Cloud Alibaba全家桶(四)——微服务调用组件Feign的更多相关文章

  1. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  4. ruby - 调用其他方法的 TDD 方法的正确方法 - 2

    我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent

  5. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  6. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  7. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  8. ruby - 如何找到调用当前方法的方法 - 2

    如何找到调用此方法的位置?defto_xml(options={})binding.pryoptions=options.to_hifoptions&&options.respond_to?(:to_h)serializable_hash(options).to_xml(options)end 最佳答案 键入caller。这将返回当前调用堆栈。文档:Kernel#caller.例子[0]%rspecspec10/16|===================================================62=====

  9. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  10. ruby - 为什么当我调用类的实例方法时,初始化不显示为方法? - 2

    我正在写一篇关于在Ruby中几乎一切都是对象的博客文章,我试图通过以下示例来展示这一点:classCoolBeansattr_accessor:beansdefinitialize@bean=[]enddefcount_beans@beans.countendend所以从类中我们可以看出它有4个方法(当然,除非我错了):它可以在创建新实例时初始化一个默认的空bean数组它可以计算它有多少个bean它可以读取它有多少个bean(通过attr_accessor)它可以向空数组写入(或添加)更多bean(也通过attr_accessor)但是,当我询问类本身它有哪些实例方法时,我没有看到默认

随机推荐