【Spring Cloud 五】OpenFeign服务调用

这里写目录标题

  • 系列文章目录
  • 背景
  • 一、OpenFeign是什么
    • Feign是什么
      • Feign的局限性
    • OpenFeign是什么
  • 二、为什么要有OpenFeign
  • 三、如何使用OpenFeign
    • 服务提供者order-service
      • pom文件
      • yml配置文件
      • 启动类
      • 实体
      • ParamController
    • 服务消费者user-service
      • pom文件
      • yml配置文件
      • 启动类
      • 接口类
      • UserController
    • 运行效果
  • 调用超时配置
  • 五、OpenFeign调用参数的处理
  • 六、OpenFeign日志打印功能
  • 总结

系列文章目录

【Spring Cloud一】微服务基本知识
【Spring Cloud 三】Eureka服务注册与服务发现
【Spring Cloud 四】Ribbon负载均衡

背景

目前开发的项目其微服务之间的调用方式使用的就是OpenFeign的方式,为了更加的体会到它代码的便捷和高效,所以博主对OpenFeign进行了再次学习和实践,加强对OpenFeign的整体理解。

一、OpenFeign是什么

在了解OpenFeign之前我们先来了解Feign,因为OpenFeign和Feign之间是一种继承关系。

Feign是什么

Feign是一个声明式的模块化的HTTP客户端工具,他是由Netflix开发。它简化了在Java应用中编写HTTP请求的方式,能够让开发者可以通过简单的注解来定义对其他服务的RESTFul调用,从而避免编写繁琐的HTTP请求。

在传统的HTTP客户端中,我们通常需要手动构建HTTP请求,包括设置请求的URL,方法、请求头、请求体等。而使用Feign,你只需要定义一个接口,并在接口的方法上添加注解,就可以实现对其他服务的调用。Feign在运行时会根据接口定义自动创建代理实现,帮助你处理底层的HTTP请求细节。

Netflix的Feign默认集成了Eureka和Ribbon。

Feign的局限性

  1. NetFlix Feign不支持Spring MVC注解,如果在Spring Cloud使用Spring MVC注解的话,可以考虑使用Spring Cloud OpenFeign。
  2. NetFlix Feign在2018年宣布不再对其进行积极开发,虽然设计任然在维护和改进Feign但是毕竟不那么积极了。

OpenFeign是什么

OpenFeign也是一个HTTP客户端工具,它是基于Feign的封装和增强,使得在Spring Cloud环境中使用Feign更加强大和灵活。

  1. OpenFeign继承了Feign的声明式HTTP客户端的特性,允许开发者使用接口和注解来定义对其他服务的RESTful调用,从而简化了服务间通信的代码。

  2. OpenFeign还增加了一些功能,如自动负载均衡、而在Feign中,你需要手动使用Ribbon的相关注解来实现负载均衡。

  3. 支持熔断器:OpenFeign整合了Hystrix,提供了熔断器的功能,可以在服务不可用时快速失败,防止级联故障。这使得系统在面对服务故障时更加稳健。

在Spring Cloud项目中推荐使用OpenFeign来实现服务间通信,以获得更好的功能和集成性能。

二、为什么要有OpenFeign

为什么要有OpenFeign,它解决了什么问题。

  1. 相比较于传动发送HTTP请求,使用OpenFeign发送跨服务请求更加方便、灵活和高效。
  2. 更好的与Spring Cloud集成与其他组件(Eureka、Ribbon、Hystrix等)无缝集成,更加方便和高效。
  3. 自动负载均衡:OpenFeign整合了Ribbon,可以自动实现负载均衡,将请求分发给多个服务实例,提高了系统的可用性和性能。

三、如何使用OpenFeign

整个系统中有三个服务,Eurka服务,一个服务提供者,一个服务消费者。
在这里插入图片描述

如何搭建Eurka服务可以访问这篇博客【Spring Cloud 三】Eureka服务注册与服务发现

服务提供者order-service

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.wangwei</groupId><artifactId>order-service</artifactId><version>0.0.1-SNAPSHOT</version><name>order-service</name><description>order-service</description><properties><java.version>8</java.version><spring-cloud.version>Hoxton.SR12</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

yml配置文件

server:port: 8080spring:application:name: order-serviceeureka:client:service-url: defaultZone: http://localhost:8761/eurekaregister-with-eureka: true #设置为fasle 不往eureka-server注册fetch-registry: true #应用是否拉取服务列表到本地registry-fetch-interval-seconds: 10 #为了缓解服务列表的脏读问题,时间越短脏读越少 性能相应的消耗回答instance: #实例的配置instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}hostname: localhost #主机名称或者服务ipprefer-ip-address: true #以ip的形式显示具体的服务信息lease-renewal-interval-in-seconds: 10 #服务实例的续约时间间隔

启动类

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

实体

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Order {private Integer id;private String name;private Double price;private Date time;}

ParamController

@RestController
public class ParamController {@GetMapping("testUrl/{name}/and/{age}")public String testUrl(@PathVariable("name")String name ,@PathVariable("age")Integer age){System.out.println(name+":"+age);return "ok";}@GetMapping("oneParam")public String oneParam(@RequestParam(required = false)String name){System.out.println(name);return "ok";}@GetMapping("twoParam")public String twoParam(@RequestParam(required = false)String name,@RequestParam(required = false)Integer age){System.out.println(name+":"+age);return "ok";}@PostMapping("oneObj")public String oneObj(@RequestBody Order order){System.out.println(order);return "ok";}@PostMapping("oneObjOneParam")public String twoParam(@RequestBody Order order,@RequestParam("name")String name){System.out.println(order+":"+name);return "ok";}
}

服务消费者user-service

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.wangwei</groupId><artifactId>user-service</artifactId><version>0.0.1-SNAPSHOT</version><name>user-service</name><description>user-service</description><properties><java.version>8</java.version><spring-cloud.version>Hoxton.SR12</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

yml配置文件

server:port: 8081spring:application:name: user-serviceeureka:client:service-url: defaultZone: http://localhost:8761/eurekaregister-with-eureka: true #设置为fasle 不往eureka-server注册fetch-registry: true #应用是否拉取服务列表到本地registry-fetch-interval-seconds: 10 #为了缓解服务列表的脏读问题,时间越短脏读越少 性能相应的消耗回答instance: #实例的配置instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}hostname: localhost #主机名称或者服务ipprefer-ip-address: true #以ip的形式显示具体的服务信息lease-renewal-interval-in-seconds: 10 #服务实例的续约时间间隔

启动类

package com.wangwei.userservice;import feign.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //开启feign的客户端,才可以帮助我们发送调用
public class UserServiceApplication {public static void main(String[] args) {SpringApplication.run(UserServiceApplication.class, args);}
}

接口类

package com.wangwei.userservice.feign;import com.wangwei.userservice.domain.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;/*** @FeignClient(value = "order-service")* value就是提供者的应用名称*/
@FeignClient(value = "order-service")
public interface UserOrderFeign {/*** 你需要调用哪个controller 就写它的方法签名(除了方法体的一个方法的所有属性* @return*/@GetMapping("doOrder")String doOrder();@GetMapping("testUrl/{name}/and/{age}")public String testUrl(@PathVariable("name")String name , @PathVariable("age")Integer age);@GetMapping("oneParam")public String oneParam(@RequestParam(required = false)String name);@GetMapping("twoParam")public String twoParam(@RequestParam(required = false)String name,@RequestParam(required = false)Integer age);@PostMapping("oneObj")public String oneObj(@RequestBody Order order);@PostMapping("oneObjOneParam")public String oneObjOneParam(@RequestBody Order order,@RequestParam("name")String name);
}

UserController

package com.wangwei.userservice.controller;import com.wangwei.userservice.domain.Order;
import com.wangwei.userservice.feign.UserOrderFeign;
import feign.Feign;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Date;@RestController
public class UserController {@Autowiredprivate UserOrderFeign userOrderFeign;/*** 总结:* feign的默认等待时间为1s* 超过1s就直接报错了** @return*/@GetMapping("userDoOrder")public String userDoOrder(){//这里发起远程调用String result = userOrderFeign.doOrder();return result;}@GetMapping("testParam")public String testParam(){String url = userOrderFeign.testUrl("David", 18);System.out.println(url);String david = userOrderFeign.oneParam("David");System.out.println(david);String wangwei = userOrderFeign.twoParam("wangwei", 18);System.out.println(wangwei);Order order = Order.builder().name("西蓝花").price(5D).time(new Date()).id(1).build();String s = userOrderFeign.oneObj(order);System.out.println(s);String wangwei1 = userOrderFeign.oneObjOneParam(order, "wangwei");System.out.println(wangwei1);return "ok";}
}

运行效果

先启动Eureka服务再启动服务提供者,最后启动服务消费者。

如下图所示已经调用成功。
在这里插入图片描述

在这里插入图片描述

调用超时配置

因为ribbon默认调用超时时长为1s,可以进行修改,可以查看DefaultClientConfigImpl。

我们在服务提供者order-service中新建一个controller,进行超时测试。

@RestController
public class OrderController {@GetMapping("doOrder")public String doOrder(){try{//模拟操作数据库等 耗时2sTimeUnit.SECONDS.sleep(2);}catch (InterruptedException e){e.printStackTrace();}return "牛奶-鸡蛋-麦片";}
}

然后我们通过服务消费者user-service进行调用测试:
可以发现出现了超时。
在这里插入图片描述
我们可以在消费者的配置文件中声明Ribbon的超时时间。

# feign只是帮你封装了远程调用的功能 底层还是ribbon 所以我们需要去修改ribbon的时间ribbon:ReadTimeout: 3000 # 3s超时时间(从服务器读取到可用资源所用的时间)ConnectTimeout: 3000 #连接服务超时时间

添加这个配置就行了。

五、OpenFeign调用参数的处理

首先传参确保消费者和提供者的参数列表一致,包括返回值,方法签名。

  1. 通过URL传参,GET请求,参数列表使用@PathVariable
  2. 如果是GET请求,每个基本参数必须加上@RequestParam
  3. 如果是POST请求,而且是对象集合等参数,必须加上@RequestBody或者@RequestParam

六、OpenFeign日志打印功能

OpenFeign还提供了日志打印功能,通过日志打印功能,能够清晰的看到发送的HTTP请求中的细节。

总结

在Spring Cloud中是OpenCluod的步骤主要是,引入openFeign依赖;启动类添加开启openFeign客户端;声明与服务端相同的方法并添加对应注册;需要注意根据项目情况配置调用服务的超时时间。

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

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

相关文章

vue3—SCSS的安装、配置与使用

SCSS 安装 使用npm安装scss&#xff1a; npm install sass sass-loader --save-dev 配置 配置到全局 &#x1f31f;附赠代码&#x1f31f; css: {preprocessorOptions: {scss: {additionalData:import "./src/Function/Easy_I_Function/Echarts/ToSeeEcharts/utill.…

嵌入式软件工程师和嵌入式硬件工程师的区别

嵌入式软件工程师和嵌入式硬件工程师的区别&#xff1a; 什么是嵌入式工程师&#xff1f;在我们生活中离不开电子产品&#xff0c;大件的比如冰箱、空调、洗衣机&#xff0c;到小件的比如音箱、剃须刀等。要设计这些电子产品除了外观设计之外还有一些核心的部件就是电路板&…

使用css和js给按钮添加微交互的几种方式

使用css和js给按钮添加微交互的几种方式 在现实世界中&#xff0c;当我们轻弹或按下某些东西时&#xff0c;它们会发出咔嗒声&#xff0c;例如电灯开关。有些东西会亮起或发出蜂鸣声&#xff0c;这些响应都是“微交互”&#xff0c;让我们知道我们何时成功完成了某件事。在本文…

大数据Flink(五十五):Flink架构体系

文章目录 Flink架构体系 一、 Flink中的重要角色 二、Flink数据流编程模型 三、Libraries支持

最全大数据毕业设计题目 - 100例

文章目录 0 前言1 如何选题1.1 选题技巧&#xff1a;如何避坑(重中之重)1.2 为什么这么说呢&#xff1f;1.3 难度把控1.4 题目名称1.5 最后 2 大数据 - 选题推荐2.1 大数据挖掘类2.2 大数据处理、云计算、区块链 毕设选题2.3 大数据安全类2.4 python大数据 游戏设计、动画设计类…

PyTorch代码实战入门

人这辈子千万不要马虎两件事 一是找对爱人、二是选对事业 因为太阳升起时要投身事业 太阳落山时要与爱人相拥 一、准备数据集 蚂蚁蜜蜂数据集 蚂蚁蜜蜂的图片&#xff0c;文件名就是数据的label 二、使用Dataset加载数据 打开pycharm&#xff0c;选择Anaconda创建的pytorch环…

深度学习(34)—— StarGAN(2)

深度学习&#xff08;34&#xff09;—— StarGAN&#xff08;2&#xff09; 完整项目在这里&#xff1a;欢迎造访 文章目录 深度学习&#xff08;34&#xff09;—— StarGAN&#xff08;2&#xff09;1. build model&#xff08;1&#xff09;generator&#xff08;2&#…

ORACLE常用基础

. 1.oracle开机启动流程 su - oracle lsnrctl start lsnrctl status sqlplus / as sysdba startup 2、如何查看数据库版本 select * from v$version; 3.如何查看用户从那个设备连接的数据库 SELECT DISTINCT machine , terminal FROM V$SESSION; 4.如何查看表结构 selec…

css实现水平居中

代码示例 <div class"box"><div class"box1"></div> </div>1.弹性布局&#xff1a;&#xff08;推荐&#xff09; display:flex&#xff1b; 这些要添加在父级的&#xff0c;是父级的属性 //父级添加display:flex; //父级添加jus…

docker安装MinIO

简介 Minio 是一个面向对象的简单高性能存储服务。使用 Go 语言编写&#xff0c;性能高、具有跨平台性。 Minio 官网为&#xff1a;https://min.io &#xff0c;有一个中文站点&#xff0c;单内容更新不是很及时&#xff0c;建议从原始官网学习。 本文采用 Docker 安装&…

Compose:从重组谈谈页面性能优化思路,狠狠优化一笔

作者&#xff1a;晴天小庭 前言&#xff1a; 随着越来越多的人使用Compose开发项目的组件或者页面&#xff0c;关于使用Compose构建的组件卡顿的反馈也愈发增多&#xff0c;特别是LazyColumn这些重组频率较高的组件&#xff0c;因此很多人质疑Compose的性能过差&#xff0c;这…

Filebeat+ELK 部署

Node1节点&#xff08;2C/4G&#xff09;&#xff1a;node1/192.168.8.10 Elasticsearch Kibana Node2节点&#xff08;2C/4G&#xff09;&#xff1a;node2/192.168.8.11 Elasticsearch Apache节点&#xff1a;apache/192.168.8.13 …

神码ai伪原创工具【php源码】

大家好&#xff0c;小编为大家解答python炫酷烟花表白源代码的问题。很多人还不知道html代码烟花特效python&#xff0c;现在让我们一起来看看吧&#xff01; 火车头采集ai伪原创插件截图&#xff1a; 目录 前言 环境准备 代码编写 效果展示 前言 Python实现浪漫的烟花特效 现在…

HTTP协议 和 HTTPS协议的区别(4点) HTTPS的缺点 HTTP如何使用SSL/TLS协议加密过程 CA证书干啥的

&#xff08;一&#xff09;HTTP协议 和 HTTPS协议的区别&#xff08;4点&#xff09;&#xff1a; 1. HTTP协议的端口号是80&#xff0c; HTTPS协议的端口号是443 2. HTTP协议使用的URL是以 http:// 开头&#xff0c;HTTPS协议使用的URL是以https://开头 3. HTTP协议和HTTP…

PHP8的运算符-PHP8知识详解

运算符是可以通过给出的一或多个值&#xff08;用编程行话来说&#xff0c;表达式&#xff09;来产生另一个值&#xff08;因而整个结构成为一个表达式&#xff09;的东西。 PHP8的运算符有很多&#xff0c;按类型分有一元运算符、二元运算符、三元运算符。 一元运算符只对一…

ruby调试

如果下载 ruby-debug-ide gem install ruby-debug-ide vscode 下载 ruby扩展 1&#xff0c; ruby 2&#xff0c;修改launch.json

FBX SDK开发快速上手指南

一段时间以来&#xff0c;我一直想制作一个 FBX Exporter 将 FBX 文件转换为我自己的格式。 整个过程不是很顺利&#xff0c;主要是FBX的官方文档不是很清楚。 另外&#xff0c;由于 FBX 格式被许多应用程序使用&#xff0c;而不仅仅是游戏引擎&#xff0c;因此提供的示例代码没…

什么是注意力机制?注意力机制的计算规则

我们观察事物时&#xff0c;之所以能够快速判断一种事物(当然允许判断是错误的)&#xff0c;是因为我们大脑能够很快把注意力放在事物最具有辨识度的部分从而作出判断&#xff0c;而并非是从头到尾的观察一遍事物后&#xff0c;才能有判断结果&#xff0c;正是基于这样的理论&a…

广州银行信用卡中心:强化数字引擎安全,实现业务稳步增长

广州银行信用卡中心是全国城商行中仅有的两家信用卡专营机构之一&#xff0c;拥有从金融产品研发至销售及后期风险控制、客户服务完整业务链条&#xff0c;曾获“2016年度最佳创新信用卡银行”。 数字引擎驱动业务增长 安全左移降低开发风险 近年来&#xff0c;广州银行信用卡…

java中使用Jsoup和Itext实现将html转换为PDF

1.在build.gradle中安装所需依赖&#xff1a; implementation group: com.itextpdf, name: itextpdf, version: 5.5.13 implementation group: com.itextpdf.tool, name: xmlworker, version: 5.5.13 implementation group: org.jsoup, name: jsoup, version: 1.15.32.创建工具…