SpringCloud学习笔记(三)Nacos配置管理与热更新、Feign远程调用替代RestTemplate

文章目录

  • 前言
  • 6 Nacos配置管理
    • 6.1 在Nacos中添加配置文件
    • 6.2 微服务拉取配置
    • 6.3 配置热更新
      • 6.3.1 方式一:`@RefreshScope`注解
      • 6.3.2 方式二:`@ConfigurationProperties`注解
    • 6.4 配置共享
      • 6.4.1 添加一个环境共享配置
      • 6.4.2 实现读取共享配置
    • 6.5 配置共享的优先级
  • 7 Feign远程调用
    • 7.1 使用Feign替代RestTemplate
    • 7.2 自定义配置
      • 7.2.1 配置文件方式
      • 7.2.2 Java代码方式

前言

SpringCloud学习笔记系列文章:

SpringCloud学习笔记(一)微服务介绍、服务拆分和RestTemplate远程调用、Eureka注册中心
SpringCloud学习笔记(二)Ribbon负载均衡、Nacos注册中心、Nacos与Eureka的区别

6 Nacos配置管理

Nacos除了可以做注册中心,还可以做配置管理。

当微服务部署的实例越来越多,达到数十、数百时,逐个修改微服务配置就会变得非常麻烦,而且很容易出错。因此,这就需要一个统一配置管理方案,可以集中管理所有实例的配置。

Nacos一方面可以将配置集中管理,另一方面可以在配置变更时,及时通知微服务,实现配置的热更新。如图:

6.1 在Nacos中添加配置文件

在Nacos管理页面,进入“配置管理”-“配置列表”页面,点击“创建配置”:

在“新建配置”页面填写配置信息:

填写完成后点击“发布”,即可新增一条配置:

要注意的是,一般是需要热更新的配置才有放到Nacos管理的必要,基本不会变更的配置还是保存在微服务本地比较好。

6.2 微服务拉取配置

微服务要拉取Nacos中管理的配置文件,并且与本地的application.yml配置文件合并,才能完成项目启动。但Nacos地址是配置在本地的application.yml文件中的,启动前服务尚未读取本地的application.yml,又如何得知Nacos地址呢?

为此,Spring引入了一种新的配置文件:bootstrap.yaml文件。它会在application.yml之前被读取,其流程如下:

  • 1)引入nacos-config依赖

在user-service工程中,引入nacos-config依赖:

<!--sc_demo\user-service\pom.xml--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
  • 2)添加bootstrap.yaml

在user-service工程的resources目录下,添加bootstrap.yaml文件,其内容如下:

# sc_demo\user-service\src\main\resources\bootstrap.yamlspring:application:# 服务名称name: user-serviceprofiles:#开发环境active: devcloud:nacos:# Nacos地址server-addr: localhost:8848 config:# 文件后缀名file-extension: yaml

通过该配置,可以根据spring.cloud.nacos.server-addr获取Nacos地址,再根据${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}作为文件id,去Nacos读取配置。在本例中,就是去读取user-service-dev.yaml

  • 3)读取Nacos配置

下面在UserController类中编写一个测试方法来读取Nacos配置:

// com.star.user.web.UserController@Value("${dir.upload}")
private String uploadDir;@GetMapping("/now")
public String now() {System.out.println("读取Nacos配置:dir.upload = " + uploadDir);return uploadDir;
}

调用http://127.0.0.1:8081/user/now接口,控制台打印信息如下:

读取Nacos配置:dir.upload = /usr/local/upload

可见,Nacos中的配置已被成功读取。

6.3 配置热更新

使用Nacos管理配置文件的目的,是修改Nacos中的配置后,微服务中无需重启即可让配置生效,也就是配置热更新

要实现配置热更新,有两种方式:

6.3.1 方式一:@RefreshScope注解

在使用@Value注解注入变量的类上添加@RefreshScope注解,例如UserController类:

// com.star.user.web.UserController@Slf4j
@RestController
@RequestMapping("/user")
@RefreshScope
public class UserController {@Value("${dir.upload}")private String uploadDir;// ...
}

重启user-service(8081)服务后,修改Nacos中的配置:

再次调用http://127.0.0.1:8081/user/now接口,控制台打印信息如下:

可见,user-service(8081)服务发现了配置的修改,并自动更新。

6.3.2 方式二:@ConfigurationProperties注解

在user-service工程中,添加一个ConfigProperties配置类用于读取配置:

// com.star.user.config.ConfigProperties@Component
@Data
@ConfigurationProperties(prefix = "dir")
public class ConfigProperties {private String upload;
}

然后在UserController类中直接注入ConfigProperties类,以替代@Value注解:

// com.star.user.web.UserController// @Value("${dir.upload}")
// private String uploadDir;@Autowired
private ConfigProperties configProperties;@GetMapping("/now")
public String now() {// System.out.println("读取Nacos配置:dir.upload = " + uploadDir);// return uploadDir;System.out.println("通过ConfigProperties读取Nacos配置:dir.upload = " + configProperties.getUpload());return configProperties.getUpload();
}

重启user-service(8081)服务后,修改Nacos中的配置:

user-service(8081)服务检测到了配置的修改,在控制台打印修改信息:

再次调用http://127.0.0.1:8081/user/now接口,控制台打印信息如下:

可见,user-service(8081)服务发现了配置的修改,并自动更新。

6.4 配置共享

微服务在启动时,会去Nacos读取多个配置文件,包括:

  • [spring.application.name]-[spring.profiles.active].yaml,例如:user-service-dev.yaml
  • [spring.application.name].yaml,例如:user-service.yaml

第一种即上文读取的配置文件,而第二种[spring.application.name].yaml不包含环境信息,因此可以被多个环境共享。

6.4.1 添加一个环境共享配置

6.4.2 实现读取共享配置

在user-service工程中,修改ConfigProperties类,添加要读取的共享属性:

// com.star.user.config.ConfigProperties@Component
@Data
@ConfigurationProperties(prefix = "dir")
public class ConfigProperties {private String upload;private String envSharedValue;
}

修改UserController类,添加一个读取共享属性方法:

// com.star.user.web.UserController@Autowired
private ConfigProperties configProperties;@GetMapping("/share")
public ConfigProperties share() {return configProperties;
}

配置user-service(8081)服务的profile为dev,user-service(8082)服务的profile为test,启动这两个服务:

调用http://127.0.0.1:8081/user/share接口,返回结果如下:

再调用http://127.0.0.1:8082/user/share接口,返回结果如下:

可见,不同的服务实例都读取到了user-service.yaml文件的配置,但只有配置了profile为dev的实例才能读取user-service-dev.yaml文件的配置。

6.5 配置共享的优先级

当Nacos、服务本地同时出现相同配置属性时,优先级有高低之分,如图:

7 Feign远程调用

目前,项目中是利用RestTemplate发起远程调用,但这种编码方式存在一些问题:

  • 存在硬编码,代码可读性差
  • 参数复杂时,URL难以维护

为了解决以上问题,推荐使用Feign来代替RestTemplate,更加优雅地实现http请求的发送。

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

7.1 使用Feign替代RestTemplate

  • 1)引入Feign依赖

在order-service工程的pom.xml文件中引入Feign依赖:

<!--sc_demo\order-service\pom.xml--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 2)添加@EnableFeignClients注解

在order-service工程的启动类OrderApplication中添加@EnableFeignClients注解,开启Feign功能:

// com.star.order.ShopApplication@EnableFeignClients
@MapperScan("com.star.order.mapper")
@SpringBootApplication
public class OrderApplication {...
}
  • 3)编写并使用Feign客户端

在order-service中新建一个接口,标注@FeignClient注解,表示该接口是一个Feign客户端,其完整内容如下:

// com.star.shop.feign.UserClient@FeignClient("user-service")
public interface UserClient {@GetMapping("/user/{id}")User findById(@PathVariable Long id);
}

Feign客户端主要是基于SpringMVC的注解来声明远程调用的信息,如上例中:

  • 服务名称:user-service,从Nacos中获取具体的ip和端口
  • 请求方式:GET
  • 请求路径:/user/{id}
  • 请求参数:Long id
  • 返回值类型:User

然后修改OrderService类的queryOrderById()方法,使用Feign客户端来发起http请求:

// com.star.order.service.OrderService@Autowired
private UserClient userClient;public Order queryOrderById(Long orderId) {// 1.查询订单Order order = orderMapper.findById(orderId);// 2.远程查询用户信息// String url = "http://127.0.0.1:8081/user/" + order.getUserId();// 2.1 使用服务名代替ip和端口// String url = "http://user-service/user/" + order.getUserId();// User user = restTemplate.getForObject(url, User.class);// 2.2 使用Feign客户端来发起http请求User user = userClient.findById(order.getUserId());order.setUser(user);// 3.返回return order;
}
  • 4)功能测试

重启order-service(8080)服务,调用http://127.0.0.1:8080/order/101接口:

可见,用户信息被成功查询,Feign客户端正常工作。

7.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的重试

一般情况下,默认值就能满足使用。如果需要自定义,只需要通过配置文件继续配置或创建自定义的@Bean覆盖默认Bean即可。

下面以修改日志级别为例来说明如何使用自定义配置:

7.2.1 配置文件方式

基于配置文件修改Feign日志级别可以针对单个服务,也可以针对所有服务::

# sc_demo\order-service\src\main\resources\application.ymlfeign:client:config:user-service: # 针对单个微服务的配置,填写 服务名# default: # 针对所有微服务的配置,填写 defaultloggerLevel: FULL #  日志级别

Feign日志级别分为四种:

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

重启order-service(8080)服务,调用http://127.0.0.1:8080/order/101接口,控制台打印Feign调用http请求的信息:

7.2.2 Java代码方式

先注释掉上面配置文件中的Feign日志级别配置,然后在order-service工程中新建一个配置类:

// com.star.order.feign.DefaultFeignConfiguration@Configuration
public class DefaultFeignConfiguration {@Beanpublic Logger.Level feignLogLevel() {// 日志级别为BASICreturn Logger.Level.BASIC;}
}

如果要全局生效,则将该类配置到启动类的@EnableFeignClients注解中:

// com.star.order.OrderApplication@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)
@MapperScan("com.star.order.mapper")
@SpringBootApplication
public class OrderApplication {...
}

如果要局部生效,则将该类配置到对应Feign客户端的@FeignClient注解中:

// com.star.order.feign.UserClient@FeignClient(value = "user-service", configuration = DefaultFeignConfiguration.class)
public interface UserClient {...
}

重启order-service(8080)服务,调用http://127.0.0.1:8080/order/101接口,控制台打印Feign调用http请求的信息:

可见,日志只记录了请求的方法、URL以及响应状态码和执行时间等,符合BASIC日志级别。

本节完,更多内容请查阅分类专栏:SpringCloud学习笔记

本文涉及代码下载地址:https://gitee.com/weidag/springcloud_learning.git

感兴趣的读者还可以查阅我的另外几个专栏:

  • SpringBoot源码解读与原理分析(已完结)
  • MyBatis3源码深度解析(已完结)
  • Redis从入门到精通(已完结)
  • MyBatisPlus详解(已完结)
  • 再探Java为面试赋能(持续更新中…)

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

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

相关文章

Agent AI智能体:未来社会的无形引领者

目录 前言1. 智能体说明1.1 定义1.2 作用1.3 类型介绍1.4 核心技术 2. 技术进步与创新2.1 机器学习的进步2.2 深度学习与神经网络2.3 强化学习2.4 转移学习与多任务学习2.5 自然语言处理(NLP)的革新2.6 知识图谱与推理 3. 行业领域应用场景3.1 游戏行业3.2 医疗健康3.3 金融服务…

【译】Celery文档1:First Steps with Celery——安装和配置Celery

https://docs.celeryq.dev/en/stable/getting-started/first-steps-with-celery.html#first-steps Celery的第一步 Celery时一个自带电池的任务队列。 本教程内容&#xff1a; 安装消息传输代理(broker)安装Celery并创建第一个任务(task)启动Celery工作进程(worker)并执行任务…

【Harmony3.1/4.0】笔记七-选项卡布局

概念 当页面信息较多时&#xff0c;为了让用户能够聚焦于当前显示的内容&#xff0c;需要对页面内容进行分类&#xff0c;提高页面空间利用率。Tabs组件可以在一个页面内快速实现视图内容的切换&#xff0c;一方面提升查找信息的效率&#xff0c;另一方面精简用户单次获取到的…

源码编译framework.jar 并成功导入android studio 开发

一、不同安卓版本对应路径 Android N/O: 7 和 8 out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar Android P/Q: 9 和 10 out/soong/.intermediates/frameworks/base/framework/android_common/combined/framework.jar Android R: 11以上 out/so…

第1章 手写WebServer

1.1 Web原理 1.1.1 Web概述 Web是指互联网上的万维网&#xff08;World Wide Web&#xff09;&#xff0c;是一个由超文本、超链接和多媒体内容组成的信息空间。Web的基础技术是HTTP协议、URL、HTML、CSS和JavaScript等。Web被广泛应用于信息检索、在线购物、社交媒体、在线游…

揭秘APP收益:养机流程带来的盈利秘诀

在这个高速发展的数字时代&#xff0c;手机应用&#xff08;APP&#xff09;已成为人们日常生活中不可或缺的工具。随着移动设备的普及和网络技术的不断进步&#xff0c;APP市场呈现出前所未有的活力和潜力。今天&#xff0c;我们将深入探讨一个特殊的高效APP运营模式——通过广…

18 如何设计微服务才能防止宕机?

在上一讲里&#xff0c;介绍了构建一个稳健的微服务的具体法则&#xff1a;防备上游、做好自己、怀疑下游&#xff0c; 并介绍了为什么要防备上游&#xff0c;以及一些防备上游的具体手段。 在本讲里&#xff0c;咱们一起来学习&#xff0c;做好微服务自身的设计和代码编写的常…

大小鼠无创血压测量系统KT-104

大小鼠无创血压测量分析系统又称鼠尾动脉血压仪&#xff0c;是新一代测量鼠血压产品&#xff0c;系统包含软件、采集器、充放气装置等组成。 详情介绍&#xff1a; 一、工作原理&#xff1a; 该仪器测量工作原理与用普通人体血压计量人体动脉血压的克氏音原理类似。高敏脉搏换…

《QT实用小工具·四十八》趣味开关

1、概述 源码放在文章末尾 该项目实现了各种样式的趣味开关&#xff1a; 1、爱心形状的switch开关&#xff0c;支持手势拖动、按压效果 2、线条样式的3种开关 项目demo演示如下所示&#xff1a; 使用方式&#xff1a; 1、sapid_switch文件夹加入工程&#xff0c;.pro文件中…

最新版pycharm安装教程

目录 PyCharm 简介 访问 PyCharm 官网&#xff1a; 选择版本&#xff1a; 这里我们选择社区版即可 环境变量的配置 第一步 第二步 第三步 Pycharm的使用 【报错解决】 通用注意事项&#xff1a; PyCharm 简介 ​ PyCharm是一种Python IDE&#xff08;Integrated Devel…

ABB机械臂3HAC2492-1控制柜电缆维修思路

ABB机器人控制柜是机器人运行的核心部件&#xff0c;而电缆则是控制柜与机器人之间的桥梁。当出现ABB工业机械手控制柜电缆故障时&#xff0c;会影响机器人的正常运行&#xff0c;甚至可能导致安全事故。ABB机械臂3HAC2492-1控制柜信号线缆维修步骤 1. 拆下控制柜电缆&#xff…

Oracle索引组织表与大对象平滑迁移至OceanBase的实施方案

作者简介&#xff1a;严军(花名吉远)&#xff0c;十年以上专注于数据库存储领域&#xff0c;精通Oracle、Mysql、OceanBase&#xff0c;对大数据、分布式、高并发、高性能、高可用有丰富的经验。主导过蚂蚁集团核心系统数据库升级&#xff0c;数据库LDC单元化多活项目&#xff…

C语言例题31:在屏幕上显示一个菱形

题目要求&#xff1a;在屏幕上显示一个菱形 #include <stdio.h>void main() {int i, j;int x;printf("输入菱形行数(3以上的奇数&#xff09;&#xff1a;");scanf("%d", &x);//显示菱形上面的大三角形for (i 1; i < (x 1) / 2; i) {for (…

缓解程序员工作压力:保持高效创新的方法与经验分享

文章目录 每日一句正能量前言工作与休息的平衡心理健康与自我关怀社交与网络建设后记 每日一句正能量 不要抱怨你的伴侣丑&#xff0c;不要抱怨你没有一个好爸爸&#xff0c;不要抱怨你的工作差&#xff0c;不要抱怨没人赏识你。现实有太多的不如意&#xff0c;就算生活 给你的…

汇川AM400PLC编码器转速测量功能块(M法测速)

M法测速的原理和相关代码,大家可以参考相关专栏文章,常用链接如下: 1、编码器M法测速仿真 编码器M法测速仿真(Simulink)_mt法测速 simulink-CSDN博客文章浏览阅读2k次。编码器M法和T法测速的详细讲解可以参看下面的文章链接,这里不再赘述,这里主要介绍Simulink里建模仿真…

python程序设计语言超详细知识总结

Python 首先 python 并不是简单&#xff0c;什么语言都有基础和高级之分&#xff0c;要想掌握一门语言&#xff0c;必须把高级部分掌握才行。 HelloWorld helloWorld.py print(hello, world)数据类型与变量 变量的数据类型数据类型描述变量的定义方式整数型 (int)整数&…

吴恩达2022机器学习专项课程(一)8.1 过拟合

目录 什么是过拟合&#xff1f;如何解决过拟合&#xff1f;什么是泛化&#xff1f;它跟过拟合有什么关系&#xff1f;过拟合案例线性回归线性回归的欠拟合线性回归较好的拟合线性回归的过拟合 逻辑回归逻辑回归的欠拟合逻辑回归的较好的拟合逻辑回归的过拟合 总结 什么是过拟合…

Prometheus+Grafana多方位监控

PrometheusGrafana多方位监控 契机 ⚙ 最近发现火山引擎有托管的Prometheus,可是当前是邀测阶段。并且发现火山云的ECS是自带开机自启的exporter的。刚好需要搭建一套服务器监控&#xff0c;所以研究了一套Prometheus监控&#xff0c;包含linux主机监控nginx监控es监控rabbitM…

数据库(MySQL)—— 数据类型

数据库&#xff08;MySQL&#xff09;—— 数据类型 MySQL中的数据类型数值类型字符串类型时间戳类型 一个实例 我们今天来看MySQL中的数据类型&#xff1a; MySQL中的数据类型 MySQL中的数据类型有很多&#xff0c;主要分为三类&#xff1a;数值类型、字符串类型、日期时间类…

Linux的学习之路:21、线程(1)

摘要&#xff1a; 本章说一下线程 目录 摘要&#xff1a; 一、回忆一下 二、如何理解线程 三、命令行看线程 四、利用函数进行使用 五、本章总结 1、线程的优点 2、线程的缺点 3、线程的异常 4、线程的用途 一、回忆一下 1、exe就是一个文件 2、我们的可执行程序…