SpringCloud OpenFeign + Nacos正确打开方式!

d496e75e5d8cfeb123673fdd103251e0.png

作者 | 磊哥

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

Nacos 支持两种 HTTP 服务请求,一个是 REST Template,另一个是 Feign Client。之前的文章咱们介绍过 Rest Template 的调用方式,主要是通过 Ribbon(负载均衡) + RestTemplate 实现 HTTP 服务调用的,请求的核心代码是这样的:

@RestController
public class ConsumerController {@Resourceprivate RestTemplate restTemplate;@GetMapping("/consumer")public String consumer(@RequestParam String name) {// 请求并获取结果(springcloud-nacos-provider 是 nacos 中的服务id)String result = restTemplate.getForObject("http://springcloud-nacos-provider/call/" + name, String.class);return result;}
}

从上述的实现代码我们可以看出一个问题,虽然以上代码可以实现 HTTP 服务调用,但需要开发者手动拼接调用地址和参数,并且远程服务调用和客户端自身的业务逻辑实现是混合在一起,不利于后期的维护与扩展,那如何要解决这个问题呢?这就是我们今天要介绍的 OpenFeign 的原因了。

OpenFeign 介绍

OpenFeign 的全称是 Spring Cloud OpenFeign,它是 Spring 官方推出的一种声明式服务调用和负载均衡组件。它的出现就是为了替代已经进入停更维护状态的 Feign(Netflix Feign)的。也就是说 OpenFeign(Spring Cloud OpenFeign)是 Feign 的升级版,它们的关系如下图所示:741846f83d7b54855fcc676b1dfdb6f3.png因为 Feign 停更维护了,所以 Spring 官方需要推出了一个新的新的框架来对 Feign 功能进行升级和扩展。

OpenFeign 常用注解

OpenFeign 声明式服务调用和负载均衡组件,因此它的核心是使用注解 + 接口的方式实现服务调用,所以了解 OpenFeign 的注解就至关重要了。对于 Feign 框架来说,它只支持 Feign 注解和 JAX-RS 注解,但 OpenFeign 在 Feign 的基础上还增加了对 Spring MVC 注解的支持,例如 @RequestMapping、@GetMapping 和 @PostMapping 等注解。OpenFeign 常用注解有以下几个:

  1. @EnableFeignClients:该注解用于开启 OpenFeign 功能,当 Spring Cloud 应用启动时,OpenFeign 会扫描标有 @FeignClient 注解的接口,生成代理并注册到 Spring 容器中。

  2. @FeignClient:该注解用于通知 OpenFeign 组件对 @RequestMapping 注解下的接口进行解析,并通过动态代理的方式产生实现类,实现负载均衡和服务调用。

  3. @RequestMapping:向服务提供者发起 Request 请求(默认为 GET 方式请求),这里需要注意 @RequestMapping/@GetMapping/@PostMapping 和 Spring MVC 中的同名注解的含义是完全不同的。

  4. @GetMapping:向服务提供者发起 GET 请求。

  5. @PostMapping:向服务提供者发起 POST 请求。

OpenFeign 使用

OpenFeign 是用在服务消费端的,有消费端就得有服务提供端,它们的关系如下图所示:33a94dbeda612856a03faf454a5e2f50.png所以我们先要创建一个服务提供者 Provider,创建步骤如下。

创建服务提供者

第一步:先创建一个 Spring Boot 项目(Spring Cloud 项目是基于 Spring Boot 创建的),添加 spring-web 和 nacos-discovery 依赖,具体依赖信息如下:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加 Nacos 支持 -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

第二步:设置 Nacos 相关配置,在 application.yml 中添加以下配置:

spring:application:name: springcloud-nacos-provider # 项目名称(nacos 注册的服务名)cloud:nacos:discovery:username: nacos # nacos 登录用户名password: nacos666 # nacos 密码server-addr: 127.0.0.1:8848 # nacos 服务端地址
server:port: 8081 # 项目启动端口号

第三步:添加服务方法,如下代码所示:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@SpringBootApplication
@RestController
public class HttpProviderApplication {public static void main(String[] args) {SpringApplication.run(HttpProviderApplication.class, args);}/*** 为客户端提供可调用的接口*/@RequestMapping("/call/{name}")public String call(@PathVariable String name) {return LocalTime.now() + "——服务提供者1:" + name;}
}

创建服务消费者

第一步:创建一个 Spring Boot 项目,添加 spring-web、nacos-discovery 和 openfeign 依赖,具体依赖内容如下:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加 nacos 框架依赖 -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 添加 openfeign 框架依赖 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

第二步:设置 Nacos 相关配置,在 application.yml 中添加以下配置:

spring:application:name: springcloud-nacos-consumer # 项目名称(nacos 注册的服务名)cloud:nacos:discovery:username: nacos # nacos 登录用户名password: nacos666 # nacos 密码server-addr: 127.0.0.1:8848 # nacos 服务端地址
server:port: 8093 # 项目启动端口号

第三步:在 Spring Boot 项目的启动文件上添加 @EnableFeignClients 注解,开启 OpenFeign,具体实现代码如下:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableFeignClients // 启用 OpenFeign
public class OpenfeignConsumerApplication {public static void main(String[] args) {SpringApplication.run(OpenfeignConsumerApplication.class, args);}
}

第四步:最重要的一步,创建 OpenFeign 与服务提供者的调用接口,实现代码如下:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient("springcloud-nacos-provider") // nacos 服务 id
public interface SpringCloudNacosProviderClient {@GetMapping("/call/{name}") // 使用 get 方式,调用服务提供者的 /call/{name} 接口public String call(@PathVariable(value = "name") String name);
}

第五步:编写服务调用者代码,经过了上一步对服务提供者的封装之后,在控制器中我们可以像调用本地方法一样调用远程接口了,具体实现代码如下:

import com.example.openfeignconsumer.feignclient.SpringCloudNacosProviderClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;@RestController
public class ConsumerController {@Resourceprivate SpringCloudNacosProviderClient providerClient; // 加载 openfeign client@GetMapping("/consumer")public String consumer(@RequestParam String name) {// 向调用本地方法一样,调用 openfeign client 中的方法return providerClient.call(name);}
}

然后分别启动服务提供者和服务调用者程序,执行结果如下图所示:3e9692390a5b6eecaa6fb0968e098a0e.png

注意事项

OpenFeign 默认的接口超时时间为 1s,所以如果接口的执行时间超过 1s,那么程序调用就会报错。接下来,我们编写程序测试一下,将服务提供者的代码休眠 2s,具体实现代码如下:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalTime;
import java.util.concurrent.TimeUnit;@SpringBootApplication
@RestController
public class HttpProviderApplication {public static void main(String[] args) {SpringApplication.run(HttpProviderApplication.class, args);}/*** 为客户端提供可调用的接口*/@RequestMapping("/call/{name}")public String call(@PathVariable String name) throws InterruptedException {// 让程序休眠 2sTimeUnit.SECONDS.sleep(2);return LocalTime.now() + "——服务提供者1:" + name;}
}

之后使用 OpenFeign 客户端访问服务,就会出现如下报错信息:7eaaba03e13c15a15b1299af73e18d03.pnga92563df7bca2e7161c63f3afee8d0da.png解决方案:通过修改配置文件中的超时时长,也就是手动调节接口的超时时长来解决此问题,因为 1s 确实太短了,修改的配置信息如下:

ribbon:ReadTimeout: 5000 # 请求连接的超时时间ConnectionTimeout: 10000 # 请求处理的超时时间

总结

OpenFeign 是基于 Feign 实现的,是 Spring Cloud 官方提供的注解式调用 REST 接口框架,OpenFeign/Feign 底层是基于 Ribbon 实现负载均衡的。使用 OpenFeign 有三个关键步骤,首先在 Spring Boot 启动类上使用注解 @EnableFeignClients 开启 OpenFeign;第二,使用 @FeignClient + @GetMapping/@PostMapping 调用服务提供者的接口;第三,在客户端中注入 Feign Client 对象,像调用本地方法一样调用远程接口。

项目源码

https://gitee.com/mydb/spring-cloud-alibaba-example

参考 & 鸣谢

c.biancheng.net/springcloud/open-feign.html

是非审之于己,毁誉听之于人,得失安之于数。

公众号:Java中文社群

Java面试合集:https://gitee.com/mydb/interview

a9481de64c81f083ac764a6283b1163d.gif

往期推荐

a8b54216231a3188b5f552c55d6b2d58.png

SpringCloud Ribbon中的7种负载均衡策略!


eda4c27171bb69a08a58796458f62b15.png

SpringCloud Nacos + Ribbon 调用服务的 2 种方法!


de4d111223a25182cc83f76c87907785.png

Spring Cloud Alibaba Nacos 的 2 种健康检查机制!


4b4c7ea0c7af481180ddf1f415ec88a2.gif

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

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

相关文章

array.unshift_Ruby中带有示例的Array.unshift()方法

array.unshiftArray.unshift()方法 (Array.unshift() Method) In this article, we will study about Array.unshift() Method. You all must be thinking the method must be doing something which is related to unshifting of objects in the Array instance. It is not as…

为什么创建线程池一定要用ThreadPoolExecutor?

作者 | 磊哥来源 | Java面试真题解析&#xff08;ID&#xff1a;aimianshi666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;在 Java 语言中&#xff0c;并发编程都是依靠线程池完成的&#xff0c;而线程池的创建方式又有很多&#xff0c;但从…

ruby array_Ruby中带有示例的Array.fill()方法(3)

ruby arrayArray.fill()方法 (Array.fill() Method) In this article, we will study about Array.fill() method. You all must be thinking the method must be doing something related to populate the Array instance. Well, we will figure this out in the rest of our …

Objects.equals有坑

前言最近review别人代码的时候&#xff0c;发现有个同事&#xff0c;在某个业务场景下&#xff0c;使用Objects.equals方法判断两个值相等时&#xff0c;返回了跟预期不一致的结果&#xff0c;引起了我的兴趣。原本以为判断结果会返回true的&#xff0c;但实际上返回了false。记…

strtoupper 小写_PHP strtoupper()函数与示例

strtoupper 小写PHP strtoupper()函数 (PHP strtoupper() function) strtoupper() function is a string function it accepts the string and returns an uppercase string. strtoupper()函数是一个字符串函数&#xff0c;它接受字符串并返回大写字符串。 Syntax: 句法&#…

Java 18 正式发布,默认 UTF-8,finalize 被弃用,别再乱用了!

JDK 18 正式发布JDK 17 刚发布半年&#xff0c;JDK 18 又如期而至&#xff0c;JDK 版本号这算是成年了&#xff1f;JDK 18 发布了&#xff0c;栈长继续为大家解读&#xff01;JDK 18 延续了 JDK 17 开创的免费策略&#xff0c;但&#xff0c;JDK 18&#xff5e;20 不是长期支持…

Spring官方推荐的@Transactional还能导致生产事故?

在Spring中进行事务管理非常简单&#xff0c;只需要在方法上加上注解Transactional&#xff0c;Spring就可以自动帮我们进行事务的开启、提交、回滚操作。甚至很多人心里已经将Spring事务与Transactional划上了等号&#xff0c;只要有数据库相关操作就直接给方法加上Transactio…

python函数实例化_用Python实例化函数

python函数实例化In terms of Mathematics and Computer science, currying is the approach/technique by which we can break multiple-argument function to single argument function. 从数学和计算机科学的角度来看&#xff0c; 柯里化是一种方法/技术&#xff0c;通过它我…

京东二面:MySQL 主从延迟、读写分离 7 种解决方案!

我们都知道互联网数据有个特性&#xff0c;大部分场景都是 读多写少&#xff0c;比如&#xff1a;微博、微信、淘宝电商&#xff0c;按照 二八原则&#xff0c;读流量占比甚至能达到 90%结合这个特性&#xff0c;我们对底层的数据库架构也会做相应调整。采用 读写分离处理过程&…

array_keys_PHP array_keys()函数与示例

array_keysPHP array_keys()函数 (PHP array_keys() function) array_keys() function is used to get the keys of an array, it accepts an array as an argument and returns a new array containing keys. array_keys()函数用于获取数组的键&#xff0c;它接受一个数组作为…

再见Postman,这款API神器更好用!

代码未动&#xff0c;文档先行其实大家都知道 API 文档先行的重要性&#xff0c;但是在实践过程中往往会遇到很多困难。程序员最讨厌的两件事&#xff1a;1. 写文档&#xff0c;2. 别人不写文档。大多数开发人员不愿意写 API 文档的原因是写文档短期收益远低于付出的成本&#…

strtolower_PHP strtolower()函数与示例

strtolowerPHP strtolower()函数 (PHP strtolower() function) strtolower() function is a string function, it accepts the string and returns an lowercase string. strtolower()函数是一个字符串函数&#xff0c;它接受该字符串并返回小写字符串。 Syntax: 句法&#xf…

如何保证数据库和缓存双写一致性?

前言数据库和缓存&#xff08;比如&#xff1a;redis&#xff09;双写数据一致性问题&#xff0c;是一个跟开发语言无关的公共问题。尤其在高并发的场景下&#xff0c;这个问题变得更加严重。我很负责的告诉大家&#xff0c;该问题无论在面试&#xff0c;还是工作中遇到的概率非…

面试官:AtomicInteger是如何保证线程安全?

blog.csdn.net/nanhuaibeian/article/details/120936139一、为什么引入 AtomicInteger &#xff1f;谈到线程安全&#xff0c;会首先想到了synchronized 和 Lock,但是这种方式又有一个名字&#xff0c;叫做互斥锁&#xff0c;一次只能有一个持有锁的线程进入&#xff0c;再加上…

机器学习 训练验证测试_测试前验证| 机器学习

机器学习 训练验证测试In my previous article, we have discussed about the need to train and test our model and we wrote a code to split the given data into training and test sets. 在上一篇文章中&#xff0c;我们讨论了训练和测试模型的必要性&#xff0c;并编写了…

如何判断线程池已经执行完所有任务了?

作者 | 磊哥来源 | Java面试真题解析&#xff08;ID&#xff1a;aimianshi666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;很多场景下&#xff0c;我们需要等待线程池的所有任务都执行完&#xff0c;然后再进行下一步操作。对于线程 Thread …

IRCTC的完整形式是什么?

IRCTC&#xff1a;印度铁路餐饮和旅游公司 (IRCTC: Indian Railways Catering and Tourism Corporation) IRCTC is an abbreviation of Indian Railways Catering and Tourism Corporation. It is a subsidiary of the Indian Railway established by the Ministry of Railways…

分布式锁的 3 种实现方案!

前言 大家好&#xff0c;我是磊哥。今天跟大家探讨一下分布式锁的设计与实现。希望对大家有帮助&#xff0c;如果有不正确的地方&#xff0c;欢迎指出&#xff0c;一起学习&#xff0c;一起进步哈~分布式锁概述数据库分布式锁Redis分布式锁Zookeeper分布式锁三种分布式锁对比1.…

java学习笔记16--异常

java学习笔记16--异常 异常 异常时导致程序中断运行的一种指令流&#xff0c;如果不对异常进行正确的处理&#xff0c;则可能导致程序的中断执行&#xff0c;造成不必要的损失&#xff0c; 所以在程序的设计中必须要考虑各种异常的发生&#xff0c;并正确的做好相应的处理&am…

ruby hash添加数据_如何在Ruby中向Hash添加元素?

ruby hash添加数据Before going through the ways to add elements to the hash instances, let us understand what could be called as a hash element. So, Hash is the collection of keys and their values. For example, 在介绍向哈希实例添加元素的方法之前&#xff0c;…