欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > SpringCloud-快速通关(一)

SpringCloud-快速通关(一)

2025/4/18 4:52:38 来源:https://blog.csdn.net/weixin_46990523/article/details/146983646  浏览:    关键词:SpringCloud-快速通关(一)

本文是基于【雷丰阳老师:尚硅谷2025最新SpringCloud - 快速通关】进行实践操作,并对雷神的笔记做一个更详细的补充,供大家学习参考,一起加油!

视频地址:SpringCloud快速通关_教程简介_哔哩哔哩_bilibili

笔记链接:3. SpringCloud - 快速通关

资料:资料.zip(代码+课件+逻辑图)

SpringCloud-快速通关(一)

  • 一、分布式基础
    • 1.1、微服务
    • 1.2、集群&分布式&节点
    • 1.3、远程调用
    • 1.4、负载均衡
    • 1.5、服务注册/发现&注册中心
    • 1.6、配置中心
    • 1.7、服务熔断&服务降级
    • 1.8、API 网关
  • 二、Spring Cloud
    • 2.1、简介
    • 2.2、技术配置
    • 2.3、版本
    • 2.4、实践
      • 2.4.1、建springcloud-demo项目
      • 2.4.2、导依赖
      • 2.4.3、建services模块
      • 2.4.4、建service-order/product模块
  • 三、Nacos - 注册/配置中心
    • 3.1、基础入门
    • 3.2、注册中心
      • 3.2.1、依赖引入
      • 3.2.2、整合配置
      • 3.2.3、服务注册
      • 3.2.4、服务发现
      • 3.2.5、远程调用
      • 3.2.6、负载均衡
    • 3.3、配置中心
      • 3.3.1、整合配置
      • 3.3.2、动态刷新
      • 3.3.3、NacosConfigManager 监听配置变化
      • 3.3.4、数据隔离
    • 3.4、小结

一、分布式基础

1.1、微服务

微服务架构风格,就像是把一个单独的应用程序开发为一套小服务,每个小服务运行在自己的进程中,并使用轻量级机制通信,通常是 HTTP API。这些服务围绕业务能力来构建, 并通过完全自动化部署机制来独立部署。这些服务使用不同的编程语言书写,以及不同数据存储技术,并保持最低限度的集中式管理。

简而言之:拒绝大型单体应用,基于业务边界进行服务微化拆分,各个服务独立部署运行。

在这里插入图片描述

1.2、集群&分布式&节点

集群是个物理形态,分布式是个工作方式。

只要是一堆机器,就可以叫集群,他们是不是一起协作着干活,这个谁也不知道;

《分布式系统原理与范型》定义:

  • “分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”
  • 分布式系统(distributed system)是建立在网络之上的软件系统。

分布式是指将不同的业务分布在不同的地方。

集群指的是将几台服务器集中在一起,实现同一业务。

例如:京东是一个分布式系统,众多业务运行在不同的机器,所有业务构成一个大型的业务集群。每一个小的业务,比如用户系统,访问压力大的时候一台服务器是不够的。我们就应该将用户系统部署到多个服务器,也就是每一个业务系统也可以做集群化

分布式中的每一个节点,都可以做集群。 而集群并不一定就是分布式的。

节点:集群中的一个服务器

1.3、远程调用

在分布式系统中,各个服务可能处于不同主机,但是服务之间不可避免的需要互相调用,我们称为远程调用。 SpringCloud 中使用 HTTP+JSON 的方式完成远程调用
在这里插入图片描述

1.4、负载均衡

分布式系统中,A 服务需要调用 B 服务,B 服务在多台机器中都存在,A 调用任意一个服务器均可完成功能。 为了使每一个服务器都不要太忙或者太闲,我们可以负载均衡的调用每一个服务器,提升网站的健壮性。

常见的负载均衡算法

  • 轮询:为第一个请求选择健康池中的第一个后端服务器,然后按顺序往后依次选择,直到最后一个,然后循环。
  • 最小连接:优先选择连接数最少,也就是压力最小的后端服务器,在会话较长的情况下可以考虑采取这种方式。
  • 散列:根据请求源的 IP 的散列(hash)来选择要转发的服务器。这种方式可以一定程度上保证特定用户能连接到相同的服务器。如果你的应用需要处理状态而要求用户能连接到和之前相同的服务器,可以考虑采取这种方式。
    在这里插入图片描述

1.5、服务注册/发现&注册中心

A 服务调用 B 服务,A 服务并不知道 B 服务当前在哪几台服务器有,哪些正常的,哪些服务已经下线。解决这个问题可以引入注册中心;

在这里插入图片描述
如果某些服务下线,我们其他人可以实时的感知到其他服务的状态,从而避免调用不可用的服务。

1.6、配置中心

每一个服务最终都有大量的配置,并且每个服务都可能部署在多台机器上。我们经常需要变更配置,我们可以让每个服务在配置中心获取自己的配置。

配置中心用来集中管理微服务的配置信息

在这里插入图片描述

1.7、服务熔断&服务降级

在微服务架构中,微服务之间通过网络进行通信,存在相互依赖,当其中一个服务不可用时,有可能会造成雪崩效应。要防止这样的情况,必须要有容错机制来保护服务。

在这里插入图片描述
1)、服务熔断
设置服务的超时,当被调用的服务经常失败到达某个阈值,我们可以开启断路保护机制,后来的请求不再去调用这个服务。本地直接返回默认的数据

2)、服务降级
在运维期间,当系统处于高峰期,系统资源紧张,我们可以让非核心业务降级运行。降级:某些服务不处理,或者简单处理【抛异常、返回 NULL、调用 Mock 数据、调用 Fallback 处理逻辑】

1.8、API 网关

在微服务架构中,API Gateway 作为整体架构的重要组件,它抽象了微服务中都需要的公共功能,同时提供了客户端负载均衡,服务自动熔断,灰度发布,统一认证,限流流控,日志统计等丰富的功能,帮助我们解决很多 API 管理难题。

在这里插入图片描述

二、Spring Cloud

2.1、简介

Spring Cloud是分布式系统一站式解决方案。

什么是分布式系统?

架构分:单体和分布式。集群只是一种物理形态,分布式是工作方式。

架构演进单体架构集群架构分布式架构
定义所有功能模块都在一个项目里单体的多服务器版本一个大型应用被拆分成很多小应用分布部署在各个机器;
优点开发部署简单解决大并发解决了单体+集群的问题
缺点无法应对高并发问题1:模块块升级 麻烦 问题2:多语言团队 交互不通

基于自己的理解:分布式架构(模拟用户访问)

  1. 通过网关来发送各个微服务的请求(请求路由)。用gateway。网关需要对请求进行分发,所以要注册到注册中心。
  2. 将各微服务布置到各服务器,即微服务(自治) 独立部署、数据隔离、语言无关,将不同模块部署到多个服务器,每个模块都要有副本服务器。不能让每个模块只部署到一个服务器,会出现单点故障问题:如果这个服务器崩了,那应用就不能提供完整服务了
  3. 如果模块跨服务器之间调用会遇到什么问题?远程调用RPC。如果远程调用怎么让应用知道调用哪个服务器的微服务。此时就需要用到nacos注册中心和配置中心,注册中心有两个功能:服务注册(监控服务上下线)和服务发现(远程调用之前要发现对方在哪)。配置中心:统一管理配置文件+推送配置的变更。Nacos+OpenFeign
  4. 如果模块之间调用失败导致服务调用链整体阻塞甚至雪崩,怎么办?服务熔断(快速失败机制),及时释放资源,防止资源耗尽。Sentinal
  5. 如果有一个操作需要多个数据库合作,而不同数据库部署在不同服务器,这就需要用到分布式事务。Seata

2.2、技术配置

Spring Cloud 系列

  • 官网:https://spring.io/projects/spring-cloud
  • 远程调用:OpenFeign
  • 网关:Gateway

Spring Cloud Alibaba 系列

  • 官网:https://sca.aliyun.com/
  • 注册中心/配置中心:Nacos
  • 服务保护:Sentinel
  • 分布式事务:Seata

2.3、版本

在这里插入图片描述

2.4、实践

2.4.1、建springcloud-demo项目

先用手脚架快速搭建框架

在这里插入图片描述
在这里插入图片描述

2.4.2、导依赖

pom父模块

注意:springboot, springcloud, springcloud-alibaba的版本

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.4</version><relativePath/> <!-- lookup parent from repository --></parent><modelVersion>4.0.0</modelVersion><groupId>com.atguigu</groupId><artifactId>spring-cloud-demo</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring-cloud.version>2023.0.3</spring-cloud.version><spring-cloud-alibaba.version>2023.0.3.2</spring-cloud-alibaba.version></properties><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><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement></project>

2.4.3、建services模块

services模块作为管理所有service-xxx 模块的父模块

在这里插入图片描述
导入依赖,在service中导入nacos-discovery依赖

<dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
</dependencies>

2.4.4、建service-order/product模块

注意父模块是services

在这里插入图片描述

三、Nacos - 注册/配置中心

3.1、基础入门

官网:https://nacos.io/zh-cn/docs/v2/quickstart/quick-start.html
Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

下载nacos的服务端:nacos server 账号密码都是nacos

安装:

  • Docker 安装

    docker run -d -p 8848:8848 -p 9848:9848 -e MODE=standalone --name nacos nacos/nacos-server:v2.4.3
    
  • 下载软件包:nacos-server-2.4.3.zip
    在这里插入图片描述

  • 启动:startup.cmd -m standalone

    在这里插入图片描述

  • 启动成功

    在这里插入图片描述

3.2、注册中心

3.2.1、依赖引入

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

3.2.2、整合配置

1、在 application.properties中配置如下

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848#暂未用到配置中心功能,需要关闭配置检查
#spring.cloud.nacos.config.import-check.enabled=false

2、开启服务注册/发现功能

@EnableDiscoveryClient //核心注解
@SpringBootApplication
public class OrderMainApplication {public static void main(String[] args) {SpringApplication.run(OrderMainApplication.class, args);}}

3.2.3、服务注册

作用:将微服务注册到nacos中进行统一管理

在这里插入图片描述

service-order, service-product都加依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>

service-order模块

  • application.properties
server.port=8000
spring.application.name=service-order
spring.cloud.nacos.server-addr=127.0.0.1:8848
  • 启动类
@SpringBootApplication
public class OrderMainApplication {public static void main(String[] args) {SpringApplication.run(OrderMainApplication.class, args);}
}

service-product模块

  • application.properties
server.port=9000
spring.application.name=service-product
spring.cloud.nacos.server-addr=127.0.0.1:8848
  • 启动类
@SpringBootApplication
public class ProductMainApplication {public static void main(String[] args) {SpringApplication.run(ProductMainApplication.class, args);}
}

效果
在这里插入图片描述
在这里插入图片描述
查看效果

访问:http://localhost:8848/nacos 可以看到服务已经注册上来;

在这里插入图片描述
启动集群

例如:service-order启动两个,service-product启动3个

  • order端口:8000/8001

  • product端口:9000/9001/9002

在这里插入图片描述
在这里插入图片描述

3.2.4、服务发现

服务发现的作用是:服务间的远程调用通过nacos发现对方的服务,然后进行调用,后续不用手动调,这里只要加上注解,两个API作为了解。

在这里插入图片描述

  • 启动类加注解@EnableDiscoveryClient
@EnableDiscoveryClient
@SpringBootApplication
public class ProductMainApplication {public static void main(String[] args) {SpringApplication.run(ProductMainApplication.class, args);}
}
  • 测试类:测试类的包和启动类的包保持一致
@SpringBootTest
public class ProductApplicationTest {@AutowiredDiscoveryClient discoveryClient;@AutowiredNacosDiscoveryClient nacosDiscoveryClient;//二者效果一样,这个依赖nacos@Testpublic void discoveryClientTest(){List<String> services = discoveryClient.getServices();for (String service : services) {System.out.println("service = " + service);List<ServiceInstance> instances = discoveryClient.getInstances(service);for (ServiceInstance instance : instances) {System.out.println("instance.getHost() = " + instance.getHost());System.out.println("instance.getPort() = " + instance.getPort());}}}@Testpublic void nacosDiscoveryClientTest(){List<String> services = nacosDiscoveryClient.getServices();for (String service : services) {System.out.println("service = " + service);List<ServiceInstance> instances = nacosDiscoveryClient.getInstances(service);for (ServiceInstance instance : instances) {System.out.println("instance.getHost() = " + instance.getHost());System.out.println("instance.getPort() = " + instance.getPort());}}}
}

3.2.5、远程调用

在这里插入图片描述
在这里插入图片描述

  • 新建model模块和services模块平级,实体类的统一管理

    在这里插入图片描述

  • 导入依赖

    <dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>annotationProcessor</scope></dependency>
    </dependencies>
    
  • 实体类:com.atguigu.bean

    @Data
    public class Order {private Long id;private BigDecimal totalAmount;private Long userId;private String nickName;private String address;private List<Product> productList;
    }
    
    @Data
    public class Product {private Long id;private BigDecimal price;private String productName;private int num;
    }
    
  • 在services的pom文件中导入model,就可以用了

    <dependency><groupId>com.atguigu</groupId><artifactId>model</artifactId><version>1.0-SNAPSHOT</version>
    </dependency>
    

回到service业务类

  • service-product
    • controller

      @RestController
      public class ProductController {@AutowiredProductService productService;@GetMapping(value = "/productId/{id}")public Product getProductById(@PathVariable("id") Long productId) {Product product = productService.getProductById(productId);return product;}
      }
      
    • service

      public interface ProductService {Product getProductById(Long productId);
      }
      
      @Service
      public class ProductServiceImpl implements ProductService {@Overridepublic Product getProductById(Long productId) {Product product = new Product();product.setId(productId);product.setPrice(new BigDecimal("99"));product.setProductName("苹果-" + productId);product.setNum(11);return product;}
      }
      
    • 测试:http://localhost:9000/product/2

      在这里插入图片描述

  • service-order
    • controller
      @RestController
      public class OrderController {@AutowiredOrderService orderService;@GetMapping(value = "/create")public Order createOrder(@RequestParam("userId") Long userId, @RequestParam("productId") Long productId) {Order order = orderService.createOrder(userId, productId);return order;}
      }
      
    • service
      public interface OrderService {Order createOrder(Long userId, Long productId);
      }
      
    • 此处需要对service-product服务进行远程调用,稍后处理,先测试
      @Service
      public class OrderServiceImpl implements OrderService {@Overridepublic Order createOrder(Long userId, Long productId) {Order order = new Order();order.setId(1L);//TODO 总金额order.setTotalAmount(new BigDecimal("0"));order.setUserId(userId);order.setNickName("张三");order.setAddress("火星");//TODO 远程查询商品列表order.setProductList(null);return order;}
      }
      
    • 可以自动生成getter/setter方法的IDEA插件
      在这里插入图片描述
    • 测试:http://localhost:8000/create?userId=2&productId=23
      在这里插入图片描述

完善业务类中远程调用

  • service-order
    • config:将RestTemplate加入到spring容器
      @Configuration
      public class OrderConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
      }
      
    • service
      @Service
      @Slf4j
      public class OrderServiceImpl implements OrderService {@AutowiredDiscoveryClient discoveryClient;@AutowiredRestTemplate restTemplate;@Overridepublic Order createOrder(Long userId, Long productId) {Product product = getProductFromRemote(productId);Order order = new Order();order.setId(1L);// 总金额=价格*数量BigDecimal price = product.getPrice();//价格int num = product.getNum();//数量order.setTotalAmount(price.multiply(new BigDecimal(num)));//总价order.setUserId(userId);order.setNickName("张三");order.setAddress("火星");// 远程查询商品列表order.setProductList(Arrays.asList(product));return order;}//远程调用获取商品信息public Product getProductFromRemote(Long productId) {//1、获取到商品服务所在的所有机器IP+portList<ServiceInstance> instances = discoveryClient.getInstances("service-product");ServiceInstance instance = instances.get(0);//远程URLString url = "http://" + instance.getHost() + ":" + instance.getPort() + "/productId/" + productId;log.info("远程请求:{}", url);//2、给远程发送请求Product product = restTemplate.getForObject(url, Product.class);return product;}
      }
      
    • 测试:http://localhost:8000/create?userId=2&productId=23
      在这里插入图片描述

在这里插入图片描述

3.2.6、负载均衡

1、使用 LoadBalancerClient

在这里插入图片描述

  • 在services模块加入依赖

    <!--负载均衡-->
    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
    
  • 测试
    前提:只能负载均衡注册到nacos的服务

    @SpringBootTest
    public class OrderApplicationTest {@AutowiredLoadBalancerClient loadBalancerClient;@Testpublic void test() {ServiceInstance choose = loadBalancerClient.choose("service-product");System.out.println("choose.getHost()+choose.getPort() = " + choose.getHost() + ":" + choose.getPort());choose = loadBalancerClient.choose("service-product");System.out.println("choose.getHost()+choose.getPort() = " + choose.getHost() + ":" + choose.getPort());choose = loadBalancerClient.choose("service-product");System.out.println("choose.getHost()+choose.getPort() = " + choose.getHost() + ":" + choose.getPort());choose = loadBalancerClient.choose("service-product");System.out.println("choose.getHost()+choose.getPort() = " + choose.getHost() + ":" + choose.getPort());choose = loadBalancerClient.choose("service-product");System.out.println("choose.getHost()+choose.getPort() = " + choose.getHost() + ":" + choose.getPort());}
    }
    
  • 效果
    在这里插入图片描述

  • 改造service-order 的OrderServiceImpl的远程调用product服务的方法

    @Service
    @Slf4j
    public class OrderServiceImpl implements OrderService {@AutowiredDiscoveryClient discoveryClient;@AutowiredRestTemplate restTemplate;@AutowiredLoadBalancerClient loadBalancerClient;@Overridepublic Order createOrder(Long userId, Long productId) {//        Product product = this.getProductFromRemote(productId);Product product = this.getProductFromRemoteWithLoadBalance(productId);Order order = new Order();order.setId(1L);// 总金额=价格*数量BigDecimal price = product.getPrice();//价格int num = product.getNum();//数量order.setTotalAmount(price.multiply(new BigDecimal(num)));//总价order.setUserId(userId);order.setNickName("张三");order.setAddress("火星");// 远程查询商品列表order.setProductList(Arrays.asList(product));return order;}//阶段二:加入负载均衡public Product getProductFromRemoteWithLoadBalance(Long productId) {//1、获取到商品服务所在的所有机器IP+portServiceInstance choose = loadBalancerClient.choose("service-product");//远程URLString url = "http://" + choose.getHost() + ":" + choose.getPort() + "/productId/" + productId;log.info("远程请求:{}", url);//2、给远程发送请求Product product = restTemplate.getForObject(url, Product.class);return product;}//远程调用获取商品信息public Product getProductFromRemote(Long productId) {//1、获取到商品服务所在的所有机器IP+portList<ServiceInstance> instances = discoveryClient.getInstances("service-product");ServiceInstance instance = instances.get(0);//远程URLString url = "http://" + instance.getHost() + ":" + instance.getPort() + "/productId/" + productId;log.info("远程请求:{}", url);//2、给远程发送请求Product product = restTemplate.getForObject(url, Product.class);return product;}
    }
    
  • 效果
    在这里插入图片描述

2、使用@LoadBalanced注解

  • config

    @Configuration
    public class OrderConfig {@LoadBalanced //基于注解式的负载均衡@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
    }
    
  • ProductController

    @RestController
    public class ProductController {@AutowiredProductService productService;@GetMapping(value = "/productId/{id}")public Product getProductById(@PathVariable("id") Long productId) {System.out.println("正在远程调用service-product...");Product product = productService.getProductById(productId);return product;}
    }
    
  • OrderServiceImpl

    @Service
    @Slf4j
    public class OrderServiceImpl implements OrderService {@AutowiredDiscoveryClient discoveryClient;@AutowiredRestTemplate restTemplate;@AutowiredLoadBalancerClient loadBalancerClient;@Overridepublic Order createOrder(Long userId, Long productId) {//        Product product = this.getProductFromRemote(productId);//        Product product = this.getProductFromRemoteWithLoadBalance(productId);Product product = this.getProductFromRemoteWithLoadBalanceAnnotation(productId);Order order = new Order();order.setId(1L);// 总金额=价格*数量BigDecimal price = product.getPrice();//价格int num = product.getNum();//数量order.setTotalAmount(price.multiply(new BigDecimal(num)));//总价order.setUserId(userId);order.setNickName("张三");order.setAddress("火星");// 远程查询商品列表order.setProductList(Arrays.asList(product));return order;}//阶段三:于注解的负载均衡public Product getProductFromRemoteWithLoadBalanceAnnotation(Long productId) {//给远程发送请求;;service-product会被动态替换String url = "http://service-product/productId/" + productId;Product product = restTemplate.getForObject(url, Product.class);return product;}//阶段二:加入负载均衡public Product getProductFromRemoteWithLoadBalance(Long productId) {//1、获取到商品服务所在的所有机器IP+portServiceInstance choose = loadBalancerClient.choose("service-product");//远程URLString url = "http://" + choose.getHost() + ":" + choose.getPort() + "/productId/" + productId;log.info("远程请求:{}", url);//2、给远程发送请求Product product = restTemplate.getForObject(url, Product.class);return product;}//远程调用获取商品信息public Product getProductFromRemote(Long productId) {//1、获取到商品服务所在的所有机器IP+portList<ServiceInstance> instances = discoveryClient.getInstances("service-product");ServiceInstance instance = instances.get(0);//远程URLString url = "http://" + instance.getHost() + ":" + instance.getPort() + "/productId/" + productId;log.info("远程请求:{}", url);//2、给远程发送请求Product product = restTemplate.getForObject(url, Product.class);return product;}
    }
    
  • 效果:http://localhost:8000/create?userId=2&productId=23
    分别在各个service-product打印
    在这里插入图片描述

思考:注册中心宕机,远程调用还能成功吗?

在这里插入图片描述

可以进行实验
实验一:五个服务启动,在nacos中有注册,但是没有执行http://localhost:8000/create?userId=2&productId=23测试,也就是没有经过远程调用,然后将nacos关闭,再调用请求测试
结论:不能调用,因为远程调用由于nacos宕机找不到地址
实验一:五个服务启动,在nacos中有注册,但是执行http://localhost:8000/create?userId=2&productId=23测试,已经经过远程调用,然后将nacos关闭,再调用请求测试
结论:可以调用,因为缓存中有地址。但如果对方服务宕机则也调不通。
原理
第一次远程调用要经过两个步骤:1.拿到nacos服务地址列表 2.给对方服务的某个地址发送请求。
第二次及后续:就会将步骤1省略,已经将地址列表放到缓存中了,即使nacos宕机也能远程调用,并且能负载均衡。

小结

  1. 使用 RestTemplate 可以获取到远程数据
  2. 必须精确指定地址和端口
  3. 如果远程宕机将不可用

在这里插入图片描述

3.3、配置中心

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3.1、整合配置

  1. services导入依赖

    <!--配置中心-->
    <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    
  2. service-order的配置文件application.properties

    导入了配置中心的依赖但是没设置(用到)配置中心就会报错,解决办法,关闭自动检查

    在这里插入图片描述

    server.port=8000
    spring.application.name=service-order
    spring.cloud.nacos.server-addr=127.0.0.1:8848
    spring.config.import=nacos:service-order.properties
    #暂未用到配置中心功能,需要关闭配置检查
    spring.cloud.nacos.config.import-check.enabled=false
    

    service-product

    spring.application.name=service-product
    spring.cloud.nacos.server-addr=127.0.0.1:8848
    #暂未用到配置中心功能,需要关闭配置检查
    spring.cloud.nacos.config.import-check.enabled=false
    
  3. 在nacos服务端进行配置

    在这里插入图片描述
    在这里插入图片描述
    代码测试 order: controller

    @RestController
    public class OrderController {@AutowiredOrderService orderService;@Value("${order.timeout}")String orderTimeout;@Value("${order.auto-confirm}")String orderAutoConfirm;@GetMapping("/config")public String getConfig() {return "OrderTimeout+OrderAutoConfirm = " + orderTimeout+" : " + orderAutoConfirm;}@GetMapping(value = "/create")public Order createOrder(@RequestParam("userId") Long userId, @RequestParam("productId") Long productId) {Order order = orderService.createOrder(userId, productId);return order;}
    }
    

3.3.2、动态刷新

  1. @Value(“${xx}”) 获取配置 + @RefreshScope 实现自动刷新

    在这里插入图片描述

    但是会产生一个问题:nacos配置中修改后,不重启服务,发请求不能自动更新修改后的数据

    在这里插入图片描述
    实时更新配置显示的办法:在@RestController上加@RefreshScope即可

    @RefreshScope//自动刷新
    @RestController
    public class OrderController {@AutowiredOrderService orderService;@Value("${order.timeout}")String orderTimeout;@Value("${order.auto-confirm}")String orderAutoConfirm;@AutowiredOrderProperties orderProperties;@GetMapping("/config")public String config(){return "order.timeout="+orderProperties.getTimeout()+"; " +"order.auto-confirm="+orderProperties.getAutoConfirm() +";"+"order.db-url="+orderProperties.getDbUrl();}
    }
    
  2. @ConfigurationProperties 无感自动刷新

    无需 @RefreshScope,自动绑定配置,动态更新

    加com.atguigu.order.properties.OrderProperties

    @Component
    @ConfigurationProperties(value = "order")//配置批量绑定在nacos下,可以无需@RefreshScope就能实现自动刷新
    @Data
    public class OrderProperties {String timeout;String autoConfirm;
    }
    

    service-order: controller

    //@RefreshScope
    @RestController
    public class OrderController {@AutowiredOrderService orderService;//    @Value("${order.timeout}")//    String orderTimeout;//    @Value("${order.auto-confirm}")//    String orderAutoConfirm;@AutowiredOrderProperties orderProperties;@GetMapping("/config")public String getConfig() {return "OrderTimeout+OrderAutoConfirm = " + orderProperties.getTimeout() + " : " + orderProperties.getAutoConfirm();}@GetMapping(value = "/create")public Order createOrder(@RequestParam("userId") Long userId, @RequestParam("productId") Long productId) {Order order = orderService.createOrder(userId, productId);return order;}
    }
    

3.3.3、NacosConfigManager 监听配置变化

在启动类中添加ApplicationRunner实例,是一个一次性任务,项目启动他就会执行

@SpringBootApplication
public class OrderMainApplication {public static void main(String[] args) {SpringApplication.run(OrderMainApplication.class, args);}//1、项目启动就监听配置文件变化//2、发生变化后拿到变化值//3、发送邮件@BeanApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager) {
//        return new ApplicationRunner() {
//            @Override
//            public void run(ApplicationArguments args) throws Exception {
//
//            }
//        }return args -> {//这个监听的服务和application.yml中naocs的配置中心有关ConfigService configService = nacosConfigManager.getConfigService();configService.addListener("service-order.properties", "DEFAULT_GROUP", new Listener() {@Overridepublic Executor getExecutor() {return Executors.newFixedThreadPool(4);}@Overridepublic void receiveConfigInfo(String s) {System.out.println("变化的配置信息:" + s);System.out.println("邮件通知....");}});System.out.println("=========");};}
}

测试效果

在这里插入图片描述

思考: Nacos中的数据集 和 application.properties 有相同的 配置项,哪个生效?

以配置中心为准,不然要配置中心干什么

在这里插入图片描述

3.3.4、数据隔离

作用:配置中心基于项目激活哪个环境标识,动态指定名称空间,动态加载指定文件和配置

在这里插入图片描述

推荐用法

在这里插入图片描述

创建几个namespace和Group等方便测试

在这里插入图片描述

按需加载,设置application.yml配置文件,将application.properties注释掉

server:port: 8000
spring:profiles:active: prodapplication:name: service-ordercloud:nacos:server-addr: 127.0.0.1:8848config:import-check:enabled: falsenamespace: ${spring.profiles.active:public}---
spring:config:import:- nacos:common.properties?group=order- nacos:database.properties?group=orderactivate:on-profile: dev---
spring:config:import:- nacos:common.properties?group=order- nacos:database.properties?group=order- nacos:haha.properties?group=orderactivate:on-profile: test---
spring:config:import:- nacos:common.properties?group=order- nacos:database.properties?group=order- nacos:hehe.properties?group=orderactivate:on-profile: prod

代码层面

OrderProperties

@Component
@ConfigurationProperties(value = "order")//配置批量绑定在nacos下,可以无需@RefreshScope就能实现自动刷新
@Data
public class OrderProperties {String timeout;String autoConfirm;String dbUrl;
}

OrderController

//@RefreshScope
@RestController
public class OrderController {@AutowiredOrderService orderService;
//    @Value("${order.timeout}")
//    String orderTimeout;
//    @Value("${order.auto-confirm}")
//    String orderAutoConfirm;@AutowiredOrderProperties orderProperties;@GetMapping("/config")public String getConfig() {return orderProperties.getTimeout() + " : " + orderProperties.getAutoConfirm() + " : " + orderProperties.getDbUrl();}@GetMapping(value = "/create")public Order createOrder(@RequestParam("userId") Long userId, @RequestParam("productId") Long productId) {Order order = orderService.createOrder(userId, productId);return order;}
}

测试效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.4、小结

在这里插入图片描述

  • 多环境(public, dev, test, prod)=》用namespace管理
  • 多服务(order, product)=》group
  • 多配置(xxx.properties)=》具体xxx.properties
  • 多配置项

参考链接:
https://blog.csdn.net/weixin_56884174/article/details/145573890
https://www.yuque.com/leifengyang/sutong/oz4gbyh5maa0rmxu#tHTwd

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词