5.谷粒商城20-27文字版

20、分布式组件-SpringCloud Alibaba简介

    前面呢,我们创建出了,几个基本的微服务,并且呢,用逆向工程,为它们生成了基本的增删改查代码,接下来呢,我们需要搭建出我们分布式系统的基本环境。
    首先在我们分布式开发里边,我们需要知道注册中心、配置中心、以及网关,这三个基本概念,在分布式开发里边,如果我们有各个微服,我们首先呢,每一个微服上线都应该将它自己注册到注册中心,这样做的好处就是,如果我们订单服务想调用商品服务,我们订单服务呢,可以先去注册中心,看一下,哪几个商品服务,都注册进来了,比如1号机器的商品服务,2号机器的商品服务,都注册进来了,那么订单服务呢,就可以随便挑一个商品服务,来进行远程调用,这是我们之前说的注册中心的一个基本作用。
    其次呢,我们还需要有一个配置中心,那么各个微服务的配置众多,比如,我们商品微服,现在呢,在十台机器上,我们想要改商品服务的某一项配置, 那么这十台机器都要改,挺麻烦的,我们希望呢,有一个配置中心,来集中管理配置,说到商品服务呢,从配置中心获取他自己的配置,我们在配置中心改掉某一个配置,同样的,这些服务,实时修改掉,这是我们说的控制中心。
    同样我们还需要有一个网关, 那么我们所有前端的请求,先通过网关,进行统一的,比如我们的健全、过滤、路由等等,有我们的网关,抵达给我们的其它服务,来做一些预先的工作。
    那么注册中心、配置中心、API网关,这几个功能呢,在SpringCloud初代产品中,分别对应这么几个组件。
    我们来,可以搜索一下,spring cloud,我们来到他的官网。
【https://spring.io/projects/spring-cloud】
    我们来看一下,springCloud的所有项目,注册中心呢,我们以前,用的是Spring Cloud里边的,我们来找一下,在Netflix这个组件里边,有一个eureka,我们来看,Spring Cloud NetFlix,它包含,我们这个服务的注册发现, 是使用eureka,包括呢,我们的配置中心,在Spring Cloud里边呢,对应的是我们这个组件,这个Spring Cloud Config,它是我们的这个配置中心,它帮我们来集中管理配置,网关呢,它使用的是NetFlix组件里边的Zuul,我们来找一下,Spring Cloud NetFlix,好,这里边呢,有eureka注册中心,包括网关,Zuul,包括呢,咱们这个断路保护Hystrix等等。
    而在我们这个项目里面呢,我们的注册中心,不来使用eureka,包括网关也不用Zuul。
    我们用呢,Spring Cloud Alibaba给我们提供的一些组件,详细的资料呢,我们可以打开,我们给大家发的基础篇,文档里边的,课件里边Spring Cloud组件。然后呢,我们来看一下,我们说到这个Spring Cloud Alibaba,他呢,是我们阿里在一八年的时候,给我们开源的,微服开发的一站式解决方案,它里边呢,给我们提供了,分布式应用里边,所必需的一些组件,比如我们的注册中心,配置中心等等,而且呢,它的最大的优点是,我们只需要一些少量的注解,以及少量的配置,就呢,可以完全的接入我们以前微服务系统里边,能帮我们快速的搭建出我们分布式的应用系统,当然,它的整个get hub的地址,就在这。【https://github.com/alibaba/spring-cloud-alibaba】
    至于我们为什么要用它,最大的原因,如果大家去来搜索,eureka停止维护相关的信息,我们就会发现网上一大片,都在说我们这个eureka停止维护了,停止开源了,官方这个维护又失败了,等等,一堆的问题。
    其实呢,我们使用Spring Cloud alibaba,最重要的原因,在于这,首先呢,我们如果用Spring Cloud给我们带的那些组件,当然Spring Cloud带的组件也不是自己写的,他是整合外部的,而外部的这些组件呢,有部分的组件,都已经停止更新和维护了,比如我们说的eureka,Netflix的好多组件也停止了开源,给我们开发呢,带来了很多的不方便,而且呢,包括部分环境搭建起来非常复杂,特别是呢,我们在做服务熔断的时候,要有一些可视化界面,这个可视化界面呢,也不完善,环境搭建呢,也比较复杂等等,我们如果想订制一些东西,我们还需要大量的二次开发。
    包括呢。我们Spring Cloud原身配的那些组件,好多的配置复杂 ,难以上手,而且呢部分配置的差别比较细,我们需要呢,对他有一个细致的把握,才能合理应用等等,这是我们以前用Spring Cloud给我们带的那些组建的一些痛点。
    而Spring Cloud Alibaba,他呢,就非常优秀了,他给我们提供了非常多的性能强悍的一些组件,而他们设计合理,也历经了考验,最起码开源出来的这些组件,都是他们已经实战过的产品,而且呢,他们的整个成套产品,给我们能带来非常丰富的一些可视化界面,包括配置中心、注册中心、包括我们的这个熔断控制平台等等等等,都有完善的可视化界面,给我们运维也带来了极大的方便。而且呢,他的搭建简单,学习曲线低,等等等等。
    基于以上的各种优点呢,我们在开发分布式应用的时候,我们大多数的组件,我们可以优先选择Spring Cloud Alibaba,对应的相关产品,那么,基于这些,我们最终的整合方案如下。
    首先呢,我们来看,在Spring Cloud Alibaba里边,他呢提供了非常多的组件,在这边, 包括呢,官方也有中文的,我们也可以打开看,那我们最终呢,是来选择这些的。

【https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md】
 
   首先,我们使用Spring Cloud Alibaba提供的Nacos系列,来作为我们的注册中心和配置中心,这个呢,就相当于替换以前Spring Cloud的Eureka,而我们声明式的远程调用以及负载均衡,我们可以使用Spring Cloud原生提供的Feign,以及Ribbon,那么这个Ribbon呢, 还是在Netflix里边的一个组件,而feign呢,由于Netflix把它原来的feign已经闭源了,所以Spring Cloud呢,开了一个OpenFeign,欸,他维护了一个OpenFeign,开源的这个Feign,我们使用这个来做远程调用,也没什么问题。
    然后呢,如果我们要做服务的熔断降级等等,那么在Spring Cloud里边,原来呢,是NetFlix里边的Hystrix,我们来找一下,Netflix里边,我们原来呢使用Hystrix,来做断路保护、服务的熔断、降级等等,那现在呢,我们可以使用Spring Cloud Alibaba,给我们带来的这个Sentinel,这个Sentinel,它不仅有熔断降级、还有流量控制、系统负载保护等等等,各种强大的功能,而且呢,他有完善的监控平台,我们用起来也非常方便。
    包括呢在API网关里边,我们呢,使用Spring Cloud为我们开放的最新版的API网关,叫Gateway,我们来找一下Spring Cloud Gateway,欸,在这,这个Gateway呢,拥有比以前Zuul更强大的性能,以及更灵活优秀的设计。
    那我们其他的组件,比如我们这个调用链监控,我们还是使用Spring Cloud为我们提供的Sleuth,我们来找一下,在这,我们使用它呢,来做我们的调用链监控,包括呢,来整合Zipkin,我们的这个组件, 比如分布式事务,使用Spring Cloud Alibaba,为我们提供的Seata,这是原来阿里巴巴Fescar框架,给我们开源升级过来的,我们现在起的新名叫Seata,她帮我们来解决分布式事务,那对于我们Spring Cloud阿里巴巴里边,欸,我们将会使用它,来做分布式事务。
    但,Spring Cloud Alibaba的全线产品,都在我们Spring Cloud官方网站,这一块有介绍,我们在Spring Cloud Alibaba里边,诶,她帮我们来介绍了阿里巴巴能帮我们来提供的这么多的功能,比如我们这个分布式的,咱们这个配置中心,包括呢,我们服务的注册发现,以及我们分布式事务等等等等。
    那么呢,最终我们在分布式系统里边,我们将会用到这些走向,Nacos的配置中心Ribbon和Feign,来做远程调用,以及Sentinel,我们服务熔断降级限流,包括我们GatWay来做网关,Sleuth调用链监控,和Seata我们来做分布式事务。但,后续的技术呢,我们一点一点进行学习,而,我们如何整合Spring Cloud Alibaba,进入我们的项目。
    首先呢,我们得面临一个版本选择的问题,包括在Spring Cloud,官方网站,在Spring Cloud Alibaba里。
【https://spring.io/projects/spring-cloud-alibaba】
【https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md】
    这块呢,都帮我们来说了,如果我们Spring Cloud版本,用的是这个,那并且Spring Boot版本对应的是这个,那我们就应该选择Spring Cloud Alibaba版本的这一块,而我们现在的微服务,都是Spring Boot2.1版本的。
    来可以看一下,比如来到,某一个服务里边【pom.xml】,我们看,我们现在依赖的是Spring Boot2.1版本的,包括呢,我们Spring Cloud也用的是Greenwich这个版本的,所以呢,我们在这,欸,对应的相当于是这个,我们最终呢,要导入Spring Cloud Alibaba的2.1点几的版本。
    而我们后来呢,每一个微服务,都可能会用到Spring Cloud Alibaba对应的某些组件。所以呢,我们将这些组件,可以直接导入到,我们之前创建的common这个工程里边。
    那Spring Cloud Alibaba,要怎么使用,我们先来,做第一步,在我们项目的common工程里边,来引入这些依赖就行了,包括呢,在Spring Cloud Alibaba官方文档里边也说了,如何使用,我们呢可以把这个依赖引进来,那我们现在呢,就用2.1.0版本的Spring Cloud Alibaba。
    我们把这个呢,复制过来,来到我们的common工程里面,我们common呢,在这写dependencyManagement,将这个进行,这个呢,是使用的依赖管理,相当呢,我们以后在dependencies里边,来引我们Spring Cloud Alibaba相关的依赖,就不用写版本号了,全被我们这个进行管理,那么在我们开发正式的功能之前,我们就后来先来学习一下我们Spring Cloud Alibaba里边,我们要用的一些基本组件。


【粘贴到gulimall-common的pom.xml文件里面,放在project最后面】
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
 

21、分布式组件-SpringCloud Alibaba-Nacos注册中心

【https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md】
    前面呢,我们给大家介绍了一下,Spring Cloud Alibaba,接下来呢,我们就先来看一下Spring Cloud Alibaba里边的第一个组件, Nacos,我们使用Nacos呢,后来作为我们的注册中心,以及配置中心,我们先来看Nacos的第一个功能,将它作为注册中心,那么以后呢,只要有微服务上线,就会再将它自己注册到,我们这个Nacos里边,我们使用Nacos来做注册中心。
    那该怎么使用呢,所有的Nacos的使用的这些例子,我们都可以在,我们官方文档里边,Spring Cloud Alibaba里边,在这有演示Demo里边,这有呢Nacos作为注册中心的例子,这个Nacos Config呢,是Nacos作为配置中心的例子,那如何将Nacos作为注册中心。
    好,我们先按照这个官方文档来看,那那要作为注册中心。
【https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md】

    我们呢,首先,根据文档,第一步,先导入一个Nacos Discovery Starter,它功能呢,就是将我们这个,微服务注册到我们注册中心中,包括呢,从注册中心中,发现其他微服务,那么,这个依赖,我们来复制来,由于每一个微服后来都需要注到注册中心,而且呢,我们将Nacos的整个依赖管理,我们放到了common里边,所以呢,我们将服务注册发现,共同的依赖呢,放到我们这个common里边,好,我们将它复制过来。

复制依赖到gulimall-common的pom.xml里面
<!-- 服务注册/发现 -->
 <dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
 </dependency>

    复制过来呢,其他的各个微服务,就相当于拥有了服务注册发现功能,我们也可以看一下,比如我们的这个,coupon,我们来,刷新一下【Maven】,它呢,依赖了我们这个common,common呢引入了nacos discov 。它呢,就可以来帮我们进行服务的注册发现,好,这我们第一步就做完了。
    那么,第二步呢,我们接下来继续来,看文档,引入了我们,服务注册发现的这个依赖以后呢,接下来我们需要给我们微服务的配置文件里边,配置我们Nacos服务器的地址,也就是注册中心的地址。
    然后呢,我们现在还没有Nacos服务器,这Nacos服务器呢,我们在下边,我们想要把我们服务注册到注册中心,我们先得有一个注册中心,那我们Nacos呢,是做了一个中间件,我们这个Nacos Server,我们呢,可以直接来将Nacos Server,先下载下来,好,我们来点击下载。下载呢,我们就来下1.1.3版本的,我们主要下载ZIP压缩包。

SpringCloudVersion、SpringCloudAlibabaVersion、SpringBootVersion版本选择:

https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明

nacos server下载:
https://github.com/alibaba/nacos/releases
要下载zip压缩包的

    好,我们稍等一下,这个注册中心呢,我们就下载完了,我们可以来直接打开,这个Nacos呢,我们可以装在我们的Linux上,但,我们现在呢,为了方便我们先来在Windows上运行,我呢,先把它整个解压到我们的桌面,好,立即解压。
    我们发现呢,桌面上呢,现在就有一个Nacos,这就是我们注册中心服务器,我们直接呢点进来,我们在bin里边,我们可以直接双击startup.cmd,那我们的Nacos注册中心,就启动了,好,我们会看到呢,这有一个地址,192,欸,相当于我们本机的8848端口。

【将下载下来的nacos-server解压到桌面——打开文件找到bin里面,打开startup.cmd】

    那相当于呢,我们要做第二步,哪一,每一个微服务,想给注册中心中配置,那就需要在配置文件中,指定注册中心的地址,那么,如何指定呢,我们在这一块,官方文档都已经说了,我们继续,欸,我们继续来看Macos注册中心的,这个试例。
    好,我们第二步呢,需要配一个nacos.discovery,服务器的地址,来指向我们本机的8848,因为我们在本机,刚启动了一个注册中心,好,那我们呢,就在这,来,修改一下,我们呢,叫nacos:discovery:server-addr,好,那就是它,它呢,我们来写我们本机地址127.0.0.1:8848,这是我们Nacos注册中心的地址,这是我们第二步,我们就配完了。

修改gulimall-coupon的application.yml文件:
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/gulimall_sms
    driver-class-name: com.mysql.jdbc.Driver
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848


    然后呢,接下来第三步,我们呢,接下来就可以将我们的,服务注册到我们的注册中心,我们只需要,使用这个注解,来开启服务的注册与发现功能就行了,好,我们将这个注解呢,复制过来,这注解其实是我们以前,用我们的eureka,也需要来写的这个注解,比如。

在gulimall-coupon的GulimallCouponApplication文件里加上注解

@EnableDiscoveryClient


    好,我们呢,写了一个这个注解。叫开启服务的注册发现的这个客户端,欸,开启我们的这个客户端,服务注册发现功能,然后呢,我们这个服务就能注册到注册中心了。
    那我们可以来启动测试一下,我呢直接来启动我们这个服务,当然要启动之前,由于他要把他自己注册到注册中心,我们的nacos注册中心,先得启动。
    那启动起来,我们怎么看,他注册到注册中心呢,我们可以在这来,既然我们是8848端口,那我们就访问,我们当前主机的8848端口,那8848端口呢,我们还需要访问一个路径,叫nacos。
【启动后访问127.0.0.1:8848/nacos/】

     好,这就是nacos注册中心的可视化界面。那登录的账号名密码,默认都叫nacos,好,先开发环境,直接用默认的登录进来。
    如果注册进来了,我们在这呢,看到Macos这个注册中心控制台,会有这么几处,第一个是配置管理,是他作为配置中心的功能,第二个是服务管理,作为注册中心的功能,当然naocs也可以做集群,然后呢,我们来看服务管理里边,服务列表,如果注册进来服务,那服务列表里边就会东西,发现呢,现在这一块呢,没有东西的没有东西的原因是什么,我们来可以看一下,我们现在呢,没有服务,用咱们这个nacos注册进来,每一个服务呢,想要注册,我们这个注解呢现在是开启了。
    其次,我们要每一个服务起上他自己的,应用的名字,application: name,这样呢,我们才能知道注册中心中注册了哪个服务,欸,这就是当前服务的名字,他呢以后再注册中心中就使用这个名字注册,我们现在来重新重启一下。
    相当于呢,我们只要启动了nacos注册中心,我们只需要配置两个,一个是注册中心地址,第二个呢是我们当前服务名,也就是我们的模块名,接下来呢,使用这个注解,开启,我们这个服务注册发现功能就行了。

gulimall-coupon的application.yml文件:

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/gulimall_sms
    driver-class-name: com.mysql.jdbc.Driver
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: gulimall-coupon

    然后呢,接下来我们进行测试,刷新,诶,我发现呢,这个gulimall-coupon,现在呢,就已经注册上来了,而且呢,健康实例数1,相当于呢,现在有一个可用的实例,包括点击详情,我们都可以看到,咱们本机7000端口,现在呢,有一个实例,欸,现在已经,正在运行,在我们服务列表里边,将会列出,所有的运行的实例,同样的,以后要有更多的服务想要注册到我们这个注册中心,我们先要做的事情,就是先要启动我们这个注册中心。
    我们刚才呢,已经启动了,接下来,比如,另外一个服务,还要注册进来,我们的member要注册进来,怎么注册呢,还是我们刚才的,那么两步。
    第一步来写配置,配置呢,主要配置上我们Nacos地址,nacos注册中心地址,Spring Cloud Nacos注册中心地址,这个地址呢,我们来指定是本机的点0.1点8848。
    第二步,来写上我们当前应用的名字,application: name,欸,是Spring下边的application: name,我们当前应用的名,是gulimall-member。 


将gulimall-member注册到注册中心:
修改application.yml文件
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/gulimall_sms
    driver-class-name: com.mysql.jdbc.Driver
#添加注册中心地址和当前应用的名字
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: gulimall-member

    然后呢,接下来,我们只需要用一个注解,开启服务的注册发现功能,好,一个注解叫@EnableDiscoveryClient。

在gulimall-member的启动文件里添加注解@EnableDiscoveryClient

    好,然后呢,我们接下来启动我们这个服务,我们服务呢,就会自动注册到注册中心,好,我们现在呢,就看到这服务呢,正在启动,好,这一块呢,启动完成以后呢,我们来刷新注册中心,发现呢,member服务现在也进来了,那某一个服务想要启动多个实例,这一块呢,就会有多个实例的显示。
【启动——访问127.0.0.1:8848/nacos/】

    这个呢,就是我们macis作为注册中心的功能,简单总结呢,就这么几步。
    首先呢,我们必须下载macos这个服务器,把这个服务器软件下载来以后呢,我们来启动nacos服务器,利用默认的nacos/nacos进行登录就行了。
    以后的微服想注册进来,首先呢,引入依赖,既然现在所有的依赖引入到common中了,那以后所有的服务,其实就可以不用引了,因为他们都依赖了common。然后呢,第二步配置上nacos注册中心的地址,然后,第三步,然后再来开启我们服务的注册发现功能。
    但,注意的细节就是,每一个服务都应该写上自己的名字,这样呢,才能注册到我们注册中心里边去,那想要注册更多的服务,都是这么1234步,那现在服务呢,都注册到注册中心了,我们下一节课呢,就可以测试我们这个远程调用,服务之间互相是否能调用。
 

    上节课呢,我们测试将会员服务以及优惠券服务注册到了,我们这个nacos注册中心中,那接下来呢,我们就来测试他们两个之间的远程调用,是否可以成功。
    比如我们以一个例子,我们会员呢,想要从优惠券服务中,获取到当前会员领取到的所有优惠券,那他要做的事呢,我们会员服务先去注册中心中,找一下,我们这个优惠卷服务都在哪些机器,比如优惠卷服务在多个机器都有,那么呢,注册中心给他返回,优惠券服务可能在这三台机器,我们会员服务呢,就必须挑一台机器,给他发送请求过去,这样呢,找优惠券服务要来我们的响应数据,那我们会员服务呢,就可以使用了,所以我们必须从注册中心中,获取到对方服务所在的这个机器位置。
    那我们就来测试一下我们这个流程是否可以走通,首先来说我们这个远程调用,使用的技术呢,还是Spring Cloud里边的Feign,这个Feign呢,他可以做声明式的远程调用,那如果大家用过,那就很方便,那如果没用过呢,按照我们的这个步骤,我们先来使用,在后边呢,我们再来说它的原理。
    这个Feign呢,他是一个声名式HTTP客户端,也就是,它给远程服务发的其实就是HTTP请求,而且呢,它的使用也非常简单。
    比如,我们的会员服务,想要调用优惠券服务,那我们呢,只需要给会员服务里边,引入我们这个openfeign,他呢,就具有了远程调用别的服务的能力。
    我们呢,来可以看一下,我们的这个微服务,我们的会员服务里边,有没有引入我们的openfeign,欸,我们之前在创建微服务的时候,我们就让大家引了web和openfeign。
    接下来呢,它想要调用,我们的优惠券服务,比如呢,我们在优惠券服务里边,写一个功能,就是获取某一个会员的所有优惠券,我们在controller里边,欸,比我们就在这些一个示例方法。
    好,我们还是public,返回R,欸,我们全系统的所有返回,都返回这个R,我们呢,就叫membercoupons。欸,我们所有,我们当前会员的所有优惠券,那,我们写了一个return R.ok(),我们将所有的优惠券呢,我就放在这个controller里边,好,我们,整一个list,Arrays.asList(),我们先写一个假的,给这边放一个假的优惠券就行了,欸Coupon实体类,好,假设呢,我们这个优惠券就是从数据库里边找到的。来,我们来创建一个优惠券,这个优惠券呢,我们给里边放上几个简单的东西,比如set我们这个优惠券的名字,比如,满100,100减10,好,现在呢,我们这有一个优惠券,我们就将呢,这个优惠券放到我们的这个集合里边,这块呢,还没有这个方法,对,我们先OK,返回一个成功的结果,给他里边put上我们的key value。
    好,我们呢,比如我们来发送一个请求,这个请求呢,是RequestMappering,欸,发一个呢我们这个coupon/member/list,好,我们这个优惠券,我们这个优惠券,会员的所有优惠券信息 ,欸,我们就让它返回,我们这个数据。

【gulimall-coupon——src/main/java/com/atguigu/gulimall/coupon/controller/CouponController】

    @RequestMapping("/member/list")
    public R membercoupons(){
        CouponEntity couponEntity = new CouponEntity();
        couponEntity.setCouponName("满1000减10");
        return R.ok().put("coupons",Arrays.asList(couponEntity));
    }


    那现在呢,我们远程服务写好了,我们就是这个coupon,它能帮我们来返回当前会员的所有优惠券。

    那我们会员服务想要调用,第一步,欸,我们来在这来记录一下,想要远程调用的步骤,诶,想要远程,想要咱们这个远程调用别的服务,那首先呢,我们做的第一步,就是要引入open-feign,引入咱们这个open-feign,这样呢,我们就具有远程调用别人的能力了。
    接下来第二个我们编写一个,因为open-feign是一个声明式的远程调用,所以我们编写一个接口,然后呢,这个接口就来告诉,编写一个接口,告诉Spring Cloud,诶,这个接口呢,需要调用远程服务,这个接口需要调用远程服务,那怎么编写呢,欸我们将,以后将所有的远程接口,我们都放在这个feign包下,那这样呢,一看就是远程接口,比如呢,我们现在呢,有一个接口,我来写上一个,咱们这个接口,就将CouponFeignService,好,我们这个接口,这个接口呢,我们现在想要,远程调用我们别的服务,如何远程调用,非常简单。

    首先呢,在这个接口上,来写第一个注解,叫@FeignClient,欸,告诉Spring Cloud,这个接口呢,是一个远程客户端,欸,它呢,要调用远程服务,调用远程哪个服务,我们member想要调用coupon刚才写的那个功能,所以呢,我们来看注册中心中,注册这个服务的时候,用的这个服务名,我们在这一写,欸,相当于我们呢,要调用这个远程服务,那这个远程服务呢,由于他有很多的功能,那我们到底要要用哪个功能,所以我们可以来到这个coupon里边,coupon里边,好,假设呢,刚才写的这个功能,我们想远程调用,那怎么办呢,我们只需要将这个方法的完整签名,我们来复制过来,给我们这个接口这,一放,放在这。
    然后呢,当然这一块的路径得写全,因为远程接口的整个地址,是我们的coupon/coupon/member/list,所以我们把这两个也复制过来,放在这,好,我们写上/,那这句话的意思就是,如果我们以后调用接口的这个方法,它就会去注册中心中,先找远程服务,gulimall-coupon所在的位置,然后呢,再去调用这个请求对应的方法。
    好,那这就是远程调用的流程,这是第一步。
    第二步编写一个接口,编写好接口以后呢,主要在接口里边声明,接口的每一个方法,每一个方法,都是调用,哪个远程服务的哪个请求,诶,这样呢,我们只需要把远程服务的这些请求方法,直接往这一复制就行了,这我们做的第二步。

在gulimall-member的com/atguigu/gulimall/member下新建一个包feign

在feign包里写一个接口CouponFeignService


/*
这是一个声名式的远程调用
 */
@FeignClient("gulimall-coupon")
public interface CouponFeignService {

    //想要远程调用哪个功能,就复制那个方法的完整签名
    //要把路径写全
    @RequestMapping("/coupon/coupon/member/list")
    public R membercoupons();

}

    那第三步,非常简单,我们必须呢,开启咱们这个远程调用功能,远程调用功能,那怎么开呢,我们要使用feign来调用,那需要一个注解,叫@EnableFeignClients,欸,我们开启FeignClients,开启我们这个Feign客户端的远程调用功能,那我们这个远程调用功能呢,在这里边主要有一个叫baseRackages,也就是我们的这种基础包,我们的所有的远程调用的这些接口,我们都放在了这个feign包下,所以我们把这个包,全,类名,咱们这个全包名给这一复制,这样呢,我们只要这个服务器一启动,就会自动扫描这个包下,所有标了FeignClient注解的这些接口,每一个接口呢,又说明了他是调用这个服务的这个请求。

在gulimall-member的启动文件里添加注解
@EnableFeignClients开启远程调用功能

@EnableFeignClients(basePackages = "com.atguigu.gulimall.member.feign")


    那所以呢,我们如果想在会员服务里边,比如我们在会员的controller,我们来找一个会员的controller,来写一个测试请求吧,好,就在这我想要获取到,我们在这呢,来写一个R test,好,来写一个RequestMapper,我们现在呢,都返回的是json数据,好,我们呢,比如就叫coupons,获取我们当前会员的所有优惠券,那首先呢,当前会员信息,我们可以先new一个member,假设啊,现在本应该都是从数据库里面查的,那假设了一个会员,欸,那就是这个会员,会员点,比如我们给它set一个会员的名字吧,好,Nickname,会员的这个昵称,比如叫张三,欸,它的所有优惠券它要远程获取,而远程接口呢,我们刚才写了一个,就叫这个CouponFeignServices, couponFeignServices,把这个远程接口呢,Alt+Enter,把它注入进来,好,我们来Autowired注入进来,然后呢,我们想要,调用它里边的方法,接口点我们这个方法名,欸,我们这有一个方法,它呢,直接帮我们返回R,这个数据,所以呢,我们可以将整个这个R先返回,我先来return,我们的这个R.ok,点,我们put上两个,第一个,我当前会员是什么,诶,我们当前会员呢,是我们的这个member,以及它的优惠券是什么,我们继续.进put,它的,我们获取到的,所有的优惠券,所有的优惠券,欸,我们从这个远程结果里边,远程结果里边,我们来获取一下,因为我们远程返回的这个东西,我们看我们远程接口,我们将所有的优惠券呢,都放在了R里边的这个集合里边,我们来看,欸我们给R里边是放了一个,叫coupons,而这个R,的这个put方法,它其实呢,就是给map里边放个key value,整个R呢,其实就是一个map,所以呢,我们从这个R里边,我们获取到刚才放的coupons,好,远程服务呢,现在会放一个这个,然后呢,那相当于我们最终的优惠券内容,那就是在这,诶,这样呢,我们会看到,我们最终响应的结果里边,第一个结果,这是我们本地查询到的,比如一个张三,第二个结果呢,这是调用远程服务查询到的,那我们就可以来测试一下这个是否成功。

在gulimall-member的src/main/java/com/atguigu/gulimall/member/controller的MemberController文件里写一个会员的请求

    @Autowired
    CouponFeignService couponFeignService;
    //获取我们当前会员的所有优惠券
    @RequestMapping("/coupons")
    public R test(){
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setNickname("张三");
        R membercoupons = couponFeignService.membercoupons();
        return  R.ok().put("member",memberEntity).put("coupons",membercoupons.get("coupons"));
    }

    好,我们现在呢,重新启动我们这两个服务,会员服务以及咱们优惠券服务。

    我们会员服务呢如果发送member/member/coupons请求,它呢,会调用一个接口的membercoupons方法,而这个方法呢,它是一个FeignCliet,它的意思就是这是一个,这是一个,声明式的远程调用,远程调用,所以呢,只要我们调用这个接口的这个方法,他就会找远程的gulimall-coupon服务,给他的这个请求来发咱们这个请求。然后呢,我们将响应到的结果重新解析出来,要我,要到我们自己的数据,比如我们想要远程的这个coupons内容,那最终整体返回。
    好,我们来测试一下,测试呢,我们给member发请求,好,member8000端口,我们发什么请求呢,我们发member/member/coupons,这个请求呢会远程的先来获取到我们的coupons,我们回车,看一下效果,欸,我们发现呢,success,已经成功了,我们的这个coupons,这是从远程获取到的,欸,满100减多少,我们当前的会员是张三,也都没问题。

访问
localhost:8000/member/member/coupons

    那么我们这个远程调用,我们就测试通过了,因为远程调用的整个过程,它的第一步,就是先要去我们的注册中心里边,得知道我们这个服务所在的位置。
    那假设如果我们这个服务没上线,那我们看一下这个远程调用能否成功,我们呢,将我们这个coupon,这个停掉,我们现在来看,coupon服务呢现在是上线的,假设呢,由于各种原因,coupon服务掉线,掉线了呢,我们,我们在注册中心中,我们刷新一下,吗稍等看一下,如果我们这个coupon服务呢,一掉线以后,我们再来远程获取,欸,我们看一下这个注册中心中,稍微慢一点,好,我们来刷新,欸,在这一块健康实例数已经没有了,那我们想要这次远程调用,来看一下结果,欸,我们在这儿呢,就会出现一个异常,叫connect timed out,我们连接超时,我们去来执行远程的这个coupon请求,member/list,已经超时了,因为我们这个服务掉线了,我们服务呢,只要重新上线,重新上线,首先呢,在注册中心中会有,只要在注册中心中有了,那我们这个远程调用才能成功,欸,我们稍等,刚才刷新的时候呢,那个掉线的服务已经被踢除了,等他上线,现在又会上来,我们稍等一下,欸,多刷几次,诶,现在呢,这个服务又上来了,我们重新在这,再一次调用测试,走,欸,这个测试呢,我们得稍等一下,他现在呢说,还没有可用的服务上线,欸,这个上来呢,还得有段缓冲时间,来稍等一下,好,我们现在呢刷新,欸,我们发现呢,这个服务又成功了,我们远程获取到的优惠券,在这满100减多少,当前的会员,是张三。
    欸,我们这个远程调用就成功了,远程调用呢,我们主要是使用Feign来进行调用,Feign的使用步骤呢,我刚才给大家也总结了。
    首先导入我们Feign的这个依赖包,然后呢,再来编写我们这个远程调用接口,你想要调哪个方法很简单,把远程接口的那个方法,完整的签名给我们接口这一复制粘贴,就行了,把这个路径写对就行了,包括他有参数,也是给这,把参数整个都复制粘贴过来,然后呢,我们接下来,只要开启我们远程调用的功能,欸,我们这个Spring Cloud Feign就会呢,扫描这些远程接口,只要呢,你调接口的这个方法,就会自动的给远程这个服务,来发送请求,但前提是,所有的服务都必须上线。


想要远程调用别的服务:
1)、引入open-feign
2)、编写一个接口,告诉Spring Cloud这个接口需要调用远程服务
    1、声名接口的每一个方法都是调用哪个远程服务的哪个请求
3)、开启远程调用功能


 

23、分布式组件-SpringCloud Alibaba-Nacos配置中心-简单示例

    上一节课,我们使用nacos呢,作为注册中心,并且测试了openfeign的远程调用功能,那么接下来呢,我们就测试,使用nacos作为我们的配置中心来,集中管理我们个个微服务的一些配置。
    但,这一块的所有操作,都可以参照我们Spring Cloud Alibaba的相关文档,欸,我们回头到Spring Cloud Alibaba。
【https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md】
    在,我们这个中文文档里边呢,也有,我们nacos作为配置中心的例子,我们往下翻,这个Example例子里边呢,有我们的Nacos Config Example,好,我们在这个里边,来看一下,它看如何作为配置中心。

如何作为配置中心使用
https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md

    那想要作为配置中心来管理配置呢,我们首先, 来做的第一步,先引入Nacos Config Starter,那这样的话呢,我们的这个微服务,才能跟Nacos建立连接, 然后呢,让Nacos来管理它的配置,好,我来复制一下,我们呢,同样,每一个服务,后来都可能需要配置中心的功能,我们都导入到common里边。
    上面呢,是我们nacos,来做注册中心完成服务端注册发现相关功能导入的依赖,好,我们可以在这注释一下,这是注册发现,服务的注册发现。
    然后呢,我们下边呢,再来导入我们刚才的这个配置管理,欸,我们连接,注册中心,连接我们的配置中心,配置中心,来,做咱们这个配置,管理的,咱们这个相关依赖,这个依赖呢,我们就按照官方文档,把这个复制来,这是我们第一步,导入依赖。

在gulimall-common的pom.xml文件导入依赖

        <!-- 配置中心来做配置管理 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>


    接下来第二步,假设呢,我们这个coupon,这个优惠券服务,需要呢, 配置中心帮我们来管理,这个服务里边的所有相关配置,那么呢,我们可以参照文档,来做第二步,第二步呢,需要在我们类路径下,src下,创建一个叫bootstrap.properties这个文件,这个文件呢,其实是Spring Boot里边规定的,如果我们项目里边,有这么一个文件,这个文件呢,会优先于application.properties来加载,它里边的配置呢,会先被读取。
    好,那么在这个配置文件里边呢,需要配置这么两个东西。
    第一个是我们当前应用的这个名字,当前的应用名字我们可以先来写一个spring.application.name,我们应用名呢,都是我们的,这个当前的模块的名字,欸,微服务的名字,这我们配的第一个,当前应用的名字。
    第二个,来指定Nacos配置中心的这个地址,以前呢这是discovery,服务注册发现的地址,现在呢是配置中心的地址, 而这个配置中心呢,其实就是我们这个启动的Nacos服务器,它兼顾了咱们这个服务注册发现,以及配置管理,也就是配置中心的功能,好,我们呢,接下来就来写配置中心,config.server-addr,那这个呢,也是我们本机的127.0.0.1:8848。


在gulimall-coupon的/src/main/resources下新建文件bootstrap.properties


 spring.application.name=gulimall-coupon

spring.cloud.nacos.config.server-addr=127.0.0.1:8848


    好,我们在这指定好了以后呢,接下来我们相当于,就配置好了配置中心的一些相关信息,那么接下来呢,我们来做一个测试,比如,我们来在这写一个controller。
    好,我们就在这个controller里边,来写一个请求,public,好,我们还是返回R,然后呢,我们就来写一个test,欸,RequestMapping来帮我们来发送请求,还是我们这个test请求。
    然后呢,它比如来获取两个我们配置中的值,比如我们以前给,这里边配置的一些值,我们比如配一个,比如user.name吧,我们随便配一个,叫张三,比如user.age等于18,我们可以将任何配置呢,都抽取到配置文件中。

在gulimall-coupon的application.properties文件添加name和age。

user.name=zhangsan
user.age=18


    我们想要获取呢,以前是这样子做的,比如我们在这来,写上两个变量,一个String的name,一个是Integer的age,而这两个变量呢,我们在配置文件中都配过,所以我们直接可以用Spring的@Value注解来获取到配置文件的值,直接${},只要在application.properties里边配的东西,我们直接可以在这来取,user.name,欸,就是这样,那么这个呢,也一样,@Value${user.age}。
    好,比如呢,我们发一个test请求,我们将这两个呢,返回一下,欸,我们return R.ok(),欸,它帮我们返回一个ok,ok里边呢帮我们来put一个东西,它的名字叫什么,名字呢,就是我们从配置文件中获取的,并且呢,再来放一个,他的年龄是多少,也是我们从配置文件中获取的,只不过呢目前,我们是先把它配置到配置文件中,我们虽然呢配置了配置中心的相关地址,当然我们现在可以来启动看一下。

在gulimall-coupon的src/main/com/atguigu/gulimall/coupon/controller的CouponController文件写一个test

    @Value("${user.name}")
    private String name;
    @Value("${user.age}")
    private Integer age;

    @RequestMapping("/test")
    public R test(){
        return R.ok().put("name",name).put("age",age);
    }


    我们在来启动我们这个coupon服务的时候呢,我们来发送我们这个coupon/coupon/test请求,我们看他能不能先获取到基本的一些值,好,这个优惠券呢,它是在7000端口,稍等一下, 好,我们来点击7000端口,我们先来测试一下,coupon/coupon/test。

启动,访问http://localhost:7000/coupon/coupon/test

    欸,我们发现呢,这个name,age,都有值,name,lfy,age,18,不过这个name呢,这个不是我们当时配的值,来看一下,当时配的这个呢,是从配置文件中取出user.name,而user.name呢,这其实是一个系统变量,所以呢,他取出的是我们这个java环境,系统里边的这个名字。就是我们当前计算机的这个名字。
    所以呢,这个为了区分开,比如我们就叫coupon.user.name,好,我们来,写上我们自己的前缀,coupon.user.age。

修改gulimall-coupon的application.properties文件

coupon.user.name=zhangsan
coupon.user.age=18

    包括我们在这取的时候呢,我们也加上自己的,当前应用的这个前缀, 欸,我们配置的时候呢,给它多加一个前缀。

修改gulimall-coupon的src/main/com/atguigu/gulimall/coupon/controller的CouponController文件


    @Value("${coupon.user.name}")
    private String name;
    @Value("${coupon.user.age}")
    private Integer age;

    @RequestMapping("/test")
    public R test(){
        return R.ok().put("name",name).put("age",age);
    }


    好我们现在呢,重新来启动我们这个优惠券服务,那么呢,这个就是正常的从配置文件中获取值,它是能获取到的,来测试一下,好,稍等让它启动,来刷新,好,现在呢name,age,都能正确的获取到值。
【启动,访问http://localhost:7000/coupon/coupon/test】

    但是呢,假设我们现在有这么一个需求,我呢想要把这个年龄和名字都要修改,修改了以后呢,那我们还要实时的看到结果,那我们以前是这样子的,假如我们这个应用已经上线了,想要修改,那我们需要修改源代码,配置文件中,比如我们把name改成张三2,然后呢,18改成20,我们把这个应用的配置改好了以后呢,重新将应用打包,又发布上去,又来重新启动,启动了以后呢,你再来发请求才能看到,所以这样呢,会非常麻烦,包括我们当前应用如果在十台机器都同时部署了,那我们把这个应用呢,相当于,配置相当于修改以后重新打包要给十台服务器重新再来部署一遍,这样就,非常麻烦。
    那我们希望做的是什么,我们将我们的这些配置,可以交给配置中心,配置中心呢我们刚才,指定了地址叫8848,如果配置中心有了这些配置,我们在配置中心一改,让他动态全改。
    那怎么做这个事呢,其实在我们这个,服务在一启动的时候,我们能看到这么一个日志,这个日志呢,叫,加载,欸,我们这个定位,定位呢,我们这个数据源,我们的属性的来源,从哪定位呢,他可以从nacos中,来获取一个叫gulimall-coupon.properties这个东西,相当于呢,我们配置中心中如果有这么一个配置,那么它里面的配置呢,也会被获取来,那好,这个配置的名字呢,一般默认现在是我们当前应用名,加上她的properties,好,我们现在呢,就把它复制来。
    我们来到配置中心nacos,在这儿有一个配置列表,我们在这呢,可以点一个加号,来,我们创建一个配置,配置呢这有一个Data ID,相当于我们这个数据的ID,配置的ID, 这个ID呢就是我们这个配置文件的名字,我们叫gulimall-coupon.properties,欸,就在我们这1块来写着的。好,我们先给这一复制,然后呢,配置的信息,由于他是一个Properties,把我们以前的这个配置呢,我们可以拿过来。我们原来是给这配了两个东西,但每次要改这太麻烦了,我们把它搬家到配置中心,好,我们放在这儿,然后呢,我点一个发布,好,发布了以后呢,接下来我们来看最终的效果。

修改配置文件的name和age
coupon.user.name=zhangsan2
coupon.user.age=20


来到配置中心配置列表http://127.0.0.1:8848/nacos/#/configurationManagement?dataId=&group=&appName=&namespace=&pageSize=&pageNo=

点击加号创建一个配置,
Data ID:gulimall-coupon.properties
配置格式:Properties
配置内容:
    coupon.user.name=zhangsan2
    coupon.user.age=20
发布


    比如呢,我们把这个coupon现在重启一下,因为以前呢,还没有加载到这个properties,如果我们现在加载到了properties,我们先来重启一下。
【启动,访问http://localhost:7000/coupon/coupon/test】

    我们来看一下,我如果来刷新, 先看能不能正确的获取到值,欸,能获取到张三,20。
    但如果我们现在想要修改怎么办呢,当前应用正在上线中,不能像以前,改了配置把应用重新打包,这样太麻烦了,我们可以来到配置中心,好,我们比如这有一个配置列表,我们看到有这个gulimall-coupon.properties,我们在这呢,可以点击编辑,我们把这个配置呢,20我们可以改成22,我们点一个发布,我们希望呢,在这,把这个改成22,你再次来请求,这块呢动态的变成22,我们发现呢,这没动态变成动22。
    想要动态变呢,非常简单,只需要结合一个注解,比如我们来到controller里边,欸我们用一个注解叫@RefreshScope,欸,我们来刷新,然后呢,我们让他刷新配置,这样的话呢,每一次,我们这个配置呢,他都会从配置中心动态的来获取到。

给gulimall-coupon的controller/CouponController这个类加一个注解
@RefreshScope

    我们现在来重新再来测试一下。
【启动,访问http://localhost:7000/coupon/coupon/test】

    那么整个步骤呢,其实非常简单,只要们导了这个配置中心相关的依赖,然后呢,在这配置一下配置中心的地址,将所有的配置搬家到配置中心,并标注一个,这个配置刷新的注解,我们以后就能动态获取到,来看一下,我们现在呢,先来刷新,目前呢这是22,是从配置中心获取的,我们现在呢,改成一个24,好,我们改成张3,我们点一个发布,我们直接在配置中心,把我们这个配置一发布,然后呢,我们在这重新测试,刷新,欸,我们发现呢张三24,这就已经动态改了,我们不需要重新来,为这个微服务打包,重新发布到我们这个服务器中。
    那我们基本的,把它的用法总结一下。我们来到我们这个主程序中,欸,我们在这呢,总结一下,配置中心是怎么使用,如何使用拿nacos作为配置中心统一管理配置。
   当然,这个步骤呢,首先要做的第一步就是引入我们这个依赖,这个依赖呢,是我们之前说的nacos作为配置中心的这个依赖,叫nacos config,这个starter,好,我们直接把这个复制过来,这我们做的第一步,引入依赖。
    然后呢,我们要做的第二步,第二步,我们呢,需要创建一个, 创建一个,一个,这个文件,叫bootsstrap.properties这个名是固定的,这是Spring Boot的规定,我们只要给这个配置文件中,配上关键的两项,第一项是我们当前应用的名字,第二项,是配置中心服务器的这个地址,但这个配置中心的前提,就是我们得启动nacos服务器。
    好,在这呢,配置上这两项,然后呢,接下来第三步,第三步我们需要呢,需要给配置中心默认添加一个叫,叫什么呢,我们来看一下,在配置中心中,默认添加一个叫当前应用名点properties,这个我们称为叫Data ID数据集,添加一个我们叫数据集,我们这个,叫数据集,也就是Data ID,然后呢这个Data ID呢,默认的名,必须叫这个,这个规则呢,就是默认,默认规则,默认规则就是应用名点properties。
    然后呢,我们给配置中,加一个这个,然后呢,给这个里边再来添上所以的配置,添加任何配置,我们把这个任何配置呢,都可以添到这个properties里边。
    那我们想要动态获取配置,怎么办,动态获取配置,非常简单,结合两个注解。
    第一个注解呢,叫RefreshScope,我们叫动态刷新配置,这个呢,其实是在使用咱们这个SpringCloud,原来,默认的这些配置中心也需要写的这个注解, 这是第一个注解。
    结合第二个注解,叫@Value,获取某个配置的值,好,这块呢,就可以,它的作用可以动态刷新配置,动态获取并刷新配置,然后呢,我们这个@Value,我们在这呢,写成${},我们这个配置项的名,这呢,比如,我们写了一个coupon user点name,它呢就能获取到,我们这个配置。
    而且呢,我们刚才看到一个效果就是,当我们application.properties中配了一个,,而且呢,同名的,我们还配在我们这个配置中心里边,那优先用的谁呢,看,配置中心是张三,24,application.properties里边,是张三,20,我们在这呢,通过测试,发现呢用的是张三,24。
    也就是,配置中心有的,优先使用配置中心,如果,配置中心和当前应用,当前应用的配置文件中,都配置了相同的项,都配置了相同的项,那么呢,优先使用配置中心的配置,这样呢,我们就可以,以后在配置中心改一个配置,让当前的这个微服务所有的东西呢都动态的进行修改。

/*
1、如何使用Nacos作为配置中心统一管理配置

    1)、引入依赖,
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
    2)、创建一个bootstrap.properties
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
    3)、需要给配置中心默认添加一个叫数据集(Data Id)gulimall-coupon.properties。默认规则,应用名.properties
    4)、给 应用名.properties添加任何配置
    5)、动态获取配置。
        @RefreshScope  :动态获取并刷新配置
        @Value("${配置项的名}")    :获取到配置。
        如果配置中心和当前应用名的配置文件中都配置了相同的项,优先使用配置中心的配置。
 */

24、分布式组件-SpringCloud Alibaba-Nacos配置中心-命名空间与配置分组

    好,前面呢,我们简单演示了,使用nacos作为配置中心来统一管理配置。那么接下来呢,我们来说一下nacos为配置中心的一些更多细节。
    好,在这个细节里面呢,我们首先来理解上这么几个核心概念。第一个概念。首先呢,是我们说的这个命名空间。还有呢,我们的配置集。以及我们的配置集ID。还有我们的配置分组。
    了解清楚这么几个概念,我们就可以对配置中心运用自如,首先我们来说,命名空间,命名空间呢,它其实,说白了一句话,是来做配置隔离的,这个隔离呢,我们可以在nacos的控制台看到,欸,这一块呢,有一个叫命名空间,命名空间呢,我来说一下,首先默认是public,欸,这是一个保留空间,这个默认的命名空间是public,它作用是什么呢?我们可以看到,在我们配置列表里边,所有呢,我们新添的这些配置,我们都属于默认的这个public名称空间,也就是说,我们默认新增的所有咱们这个配置,都在咱们这个public空间下。
    而我们说这个命名空间,它的核心是想用来做配置隔离的,所以说呢,我们举上这么几个例子,比如第一个例子,我们呢,开发有一堆的配置,测试呢,也有一堆的配置,在线上环境,我们的生产环境,也有一堆的配置,配置呢,可能不一样,那我们呢就可以,在第一种情况,我们可以创建,很多的命名空间。
    比如呢,我们来新建一个命名空间,比如我们这个命名空间呢,我们就叫dev,这是我们这个开发环境。然后呢,我们还可以创建更多的这个名称空间,好我们再来创建,比如我们的测试环境,这是我们测试环境。然后呢,当然我们还可以来创建我们的生产环境。要说呢,我们可以先创建这么几个命名空间。
【 
在nacos命名空间创建三个新的命名空间
命名空间名:dev
描述:开发环境

命名空间名:test
描述:测试环境

命名空间名:prop
描述:生产环境

    那他们的作用是什么呢?比如我们看我们配置列表,我们之前呢,给这添了一个叫gulimall-coupon.properties这个配置,只不过呢,他在默认的这个名称空间public下。
    比如我们现在呢,我们有一个生产环境,好我们在生产环境里边,我们再来创建,还是我们这这个gulimall-coupon.properties,然后呢,我们将那一堆的配置我们重新写在这,比如我们之前有个coupon.user.name。点user点name,欸,比如呢,我们等于李四,和,coupon.user.age,等于30,好我们点一个发布。

在nacos配置列表的生产环境(prop)新建一个配置
Data ID:gulimall-coupon.properties
Group:DEFAULT_GROUP
配置格式:Properties
配置内容:
    coupon.user.name=lisi
    coupon.user.age=30

    相当于呢,我们能看到,在我们这两个名称空间,第一个是public下,有gulimall-coupon.properties,和prop下,也有gulimall,properties,并且呢,他们都拥有相同的两个配置,一个叫user.name和user.age,我们的这个public下也有这个user.name,和user.age。
    而如果我们此时,来启动我们的这个coupon优惠券服务。这个优惠券呢,我之前配过。我们只要它配置了这个配置中心的地址,我们说,它默认会找到当前应用名点properties文件,而它默认呢,会在哪个命名空间下找,我们来可以看一下。
【重启gulimall-coupon,访问http://localhost:7000/coupon/coupon/test】

   好,我们来等他启动,启动呢我们来直接进行测试,来发送请求。欸,我们发现呢,它获取到的是张三,24,因为呢,它是使用默认的这个命名空间public,将他获取到了这个里边的配置。
    而如果我们某一天我们这个应用上线了,我们想要让它动态的从prop里面,来获取线上的一些配置,那怎么办呢?我们只需要改善一处,我们在bootstrap这一块呢,来修改一个叫config。这呢,有一个叫namespace,我们来写上咱们这个命名空间,我们要哪个命名空间呢? 注意这个namespace呢,我们必须写成,欸,我现在想让它切换到这个环境下,欸,我们用这一块的配置,那我们就得切到prop,这个命名空间,这命名空间呢,这有一串uuid一样的东西,我们把它复制来,必须写它,好,当我把这个一配上以后呢,我再来重启coupon,相当于呢,我们就给他切到了另外一个名称空间,他还是来获取我们的gulimall-coupon.properties,只不过呢,获取到另外一个名称空间下的。

复制nacos的prop命名空间的唯一ID:9de62e44-cd2a-da82-bf5c-95878bd5e871

修改gulimall-coupon的resources下的bootstrap.properties文件

添加
spring.cloud.nacos.config.namespace=9de62e44-cd2a-da82-bf5c-95878bd5e871


    欸,我们来可以看到日志,还是获取他,然后呢,我们来重新来刷新。欸,我发现他拿到的就是李四,30。
    那这就是我们第一种场景,我们可以利用命名空间来做我们这个环境隔离。
    利用,利用咱们这个命名空间,来做环境隔离。那么,这一块呢需要注意的一点就是,我们呢,需要在咱们这个bootstrap.properties里边来配置上,我们呢,需要使用哪个命名空间下的配置。所以呢,我们必须额外加上这句话,而且这个namespace这呢,一定要写,我们这个命名空间的这个,唯一ID,不能写这个命名空间的名字,比如叫什么prop、dev不能写这个,这就是我们说的第一个场景。

    第二个场景呢,其实我们也可以,来这样做,比如我们现在微服务众多,每一个微服务里面也有超级多的配置文件,如果我们呢,就只有这么三个命名空间,这样的话呢,在每一个命名空间下,有超多的这个配置文件,非常混乱,那么我们可以呢,基于我们每一个微服务,每一个微服务之间,互相隔离,互相隔离配置。怎么互相隔离配置呢?我们可以每一个微服务都创建一个自己的命名空间,每一个微服务,都创建自己的命名空间,那么这样只加载,只加载自己命名空间下的所有配置。欸,这样呢我们也可以这么来做。
    比如举一个例子,我们呢,以前是这么,欸,开发测试这几个命名空间,那现在呢,我们不想用这种模式,我们可以来,再来建一些命名空间,我们啊,为每一个微服务都建上,但这块呢,比如我们叫,第一个叫,gulimall-coupon,好,我们为优惠券,来创建一个专门优惠券的这个命名空间,欸,我们是优惠系统,优惠系统,啊,咱们这个命名空间。欸,比如呢,我们可以给优惠系统,自己来创一个命名空间,当然我们也可以,给我们的其他各个微服务,我们就来创建两个,给它测试一下就行了,好我们可以给我们这个会员系统也创建自己的命名空间。

nacos新建命名空间

命名空间名:coupon
描述:优惠系统

命名空间名:member
描述:会员系统

    这样呢,以后啊,所有的和优惠券有关的,比如,和优惠系统有关的所有配置,我们全放在这个优惠系统下,让它启动的时候呢,只来读它,自己命名空间下的东西,比如,我们重新呢,给咱们这个coupon,这个命名空间下创建出我们这个gulimall-couon.properties,但,我每次呢想给这复制一个,太麻烦,我们可以选中这个,我们在这呢,专门有一个克隆配置,我们点一个克隆,我们呢把这个所有的配置内容,我们放到coupon命名空间下,然后呢,点一个开始克隆。

在nacos配置中心克隆一个gulimall-coupon.properties到coupon命名空间

选中——克隆——目标空间:coupon——开始克隆

    这样呢coupon下就有一个这个配置,而我们这个,以后啊,咱们这个coupon,这个微服务,他呢,都只获取自己命名空间下的所有配置。
    好我们自己命名空间,我们把这一块【coupon唯一ID】复制来。我们可以基于环境进行隔离,也可以基于微服务之间互相隔离,好,我们来重启一下。

将nacos的coupon命名空间的唯一ID复制粘贴到gulimall-coupon的bootstrap.properties。

spring.cloud.nacos.config.namespace=coupon命名空间的唯一ID

重启

    这样呢,我们以后啊,就可以将,我们这个coupon,这个微服务下的所有配置,可能有这个配置,可能有更多其他配置,每一个呢,我们都创建到这。把它都放到它自个的命名空间下,好,我们可以来测试一下,比如呢,我们coupon,这个服务下的命名空间下的这些修改,我们来修改一下,比如我们就叫zhangsan-coupon。好,然后呢,这个age呢,我们就叫29,我们来发布一下,看是不是能用到最新的。欸,当然这是一个properties类型的,来发布一下。

修改coupon命名空间的gulimall-coupon.properties配置

配置格式:Properties
配置内容:
    coupon.user.name=zhangsan-coupon
    coupon.user.age=29

    好,我们在这儿呢刷新一下,欸,现在是zhangsan-coupon,29,欸,已经用到了他自己命名空间下的这些配置,这是我们说的第一个核心概念,叫命名空间,它的这个使用场景,命名空间,说白了呢,就是用来配置隔离的,我们可以基于环境进行隔离,也可以基于微服务进行隔离等等,但隔离方式有很多,大家可以按照自己的业务的特性,来进行不同的隔离。


    接下来第二个叫配置集,什么叫配置集呢,也就是我们一组相关或者不相关配置项的集合就是配置集,那说白了,我们这个配置文件里面有超多的配置,它们合起来就是一个配置集,也就是呢,这个只是一个概念,我们知道一下,欸,所有的配置的集合,欸,我们就叫配置集。
    而接下来呢还有一个重要的叫配置集ID。也就是说呢,我们配置所有的配置集合,我们以前呢是放在这个配置文件中,这个文件名叫application.yml,那这个配置集ID呢,就类似于配置文件名。
    而他在nacos中,是这个东西来看一下,我们在这呢点一个新增,这会有一个叫Data ID:,这个就是我们的配置集ID,那其实就是我们以前的这个配置文件名,欸,类似我们这个配置文件名。
    那我们以后呢,想要给我们这里边加什么配置文件,那这块呢,就相当于它的配置文件名等等等等,那我们这儿呢就有一个配置文件,gulimall-coupon.properties等等,好,这是我们的配置集的ID。
    接下来还有一个核心概念叫配置分组,这个很重要,我们看到,在这个Data ID,也就是这个配置文件,它所属于这一组,叫DEFAULT_GROUP,我们说一下,默认所有的配置集,都属于,配置集都属于,属于哪一组呢?属于我们这个DEFAULT_GROUP。我们这些组啊,其实都是可以基于业务来随意定制的,比如我双11的时候,欸,用这一组【1111】,我们组名呢就叫双11,欸,我们这个618的时候呢,用这一组配置【618】,比如我们这个双十二的时候呢,用这一组配置【1212】等等等等,我们呢,可以随意来定义我们这些组名。
    咱们在创建配置的时候,比如我们在这,点一个新增,在这创建配置的时候呢,这就让我们输入组,这个组呢,大家自己来输就行了,比如我们这个,又有一个叫gulimall-coupon好,点properties,而他呢属于双11的,双11呢,如果是双11情况下那就这样用,比如user name就叫haha,比如我们的这个年龄。user.age。age等于18,好,我们呢把这个一发布。

在nacos的coupon命名空间新建一个配置

Data ID:gulimall-coupon.properties
Group:1111
配置格式:Properties
配置内容:
    coupon.user.name=haha
    coupon.user.age=18
发布


    我们可以看到。在这一块呢,同样的配置,在我这个coupon命名空间下,这呢有gulimall-coupon.properties,欸,这两个呢是同样一个配置集,但是他们所属于不同分组,那这样呢,我比如想,过节了双11了,我想让他用这一组的配置,那怎么办呢?我们只需要来bootstrap.properties里边,config在指定了namespace以后,config呢,当然还能指定我们的group。欸,这呢有一个group,group呢如果不写就是用默认组的,如果我们写上,好,我现在呢想让他用双11的这个配置,好,我们来重新启动coupon。

修改gulimall-coupon的bootstrap.properties文件

添加
spring.cloud.nacos.config.group=1111

    好,我们来进行来测试,如果是双11的话呢,它获取到的应该是haha,18,我们在这来刷新一下。好,我们看到呢,确实拿到的是haha,18。
【重启,访问http://localhost:7000/coupon/coupon/test】
    这就是呢,我们说的这个配置分组,而最终呢,在我们这个项目里边,对他们的使用是这样子的,首先呢,每个微服务,每个微服务。创建自己的命名空间。就像我们刚才这样一样,欸,coupon这个微服务,有他自己的这个命名空间。接下来呢,我们使用这个配置分组,来区分它的这个环境,我们再来使用,这个配置分组,分组,区分环境。比如,我们区分dev环境和test环境和咱们这个prop环境。
    还是呢,由我们这个gulimall-coupon为例,我们来修改一下我们的这个配置,首先呢,我们这个命名空间自己微服务呢,拥有自己的命名空间,接下来呢,我们将每一个properties改成我们不同的这个分组,好,由于这一块呢,我们点击编辑的时候,这个分组已经定了不能改了,那我们就将之前的这个配置,我可以先删除掉。

删除nacos的coupon命名空间下在DEFAULT_GROUP分组的gulimall-coupon.properties】


    我来创建上这么几个分组,我现在把里边的配置复制出来,然后我来创建我们的gulimall。gulimall和coupon.properties,首先呢,第一个组,是dev组,dev组里边的配置是这样子的,我们就叫dev,好18,然后呢,我点一个发布。同样的呢,我再来发布一个gulimall-coupon.properties,而此时呢,让他属于咱们这个prod组。好,我们来测试一下,还是我们这个gulimall-coupon.properties。好,我们呢,让他属于prod组,好,我们就呢,整上两组,给大家测试一下prod,比如说呢,我们是20,prod组,好,这样呢,我们就会看到我们这有两个配置文件,两个一模一样的配置文件,只不过呢,他是那所属于不同的分组,我们将这个呢,删除掉,这样如果我们在开发环境下,那我们以后呢,就来修改bootstrap.properties,我们呢,就让它来读取开发环境这一组的相关的配置,好,我们来启动。


在nacos的coupon命名空间新建配置

Data ID:gulimall-coupon.properties
Group:dev
配置格式:Properties
配置内容:
    coupon.user.name=dev
    coupon.user.age=18


Data ID:gulimall-coupon.properties
Group:prod
配置格式:Properties
配置内容:
    coupon.user.name=prod
    coupon.user.age=20

删除coupon命名空间下1111组的gulimall-coupon.properties配置


修改gulimall-coupon的bootstrap.properties文件

spring.cloud.nacos.config.group=dev

    命名空间呢,每一个微服务还是读取自己命名空间下的配置,而呢,我们现在是开发环境,我们让它读取dev组下的相关配置。我们可以来进行测试。刷新。我们现在呢,看到的是dev,18。
    等切换到线上环境了,我们只需要把这个分组呢,改成prod。让他,让他默认来读取我们这个prod组里,组的配置。

修改修改gulimall-coupon的bootstrap.properties文件

spring.cloud.nacos.config.group=prod

来看一下,如果是prod呢,我们这一块,返回的就应该是prod,我们prod组的,这个配置的内容是prod,20,来测试一下。
    好,我发现呢,他已经切换到prod,20,那以后呢,我们的微服务就这么来使用,每一个微服务呢,创建自己的这个命运空间,然后呢,他来使用咱们这个配置分组来区分不同的环境。


2.细节
 1)、命名空间:配置隔离:
    默认:public(保留空间);默认新增的所有配置都在public空间。
    1、开发,测试,生产:利用命名空间来做环境隔离。
      注意:在bootstrap.properties;配置上,需要使用哪个命名空间下的配置。
      spring.cloud.nacos.config.namespace=9de62e44-cd2a-da82-bf5c-95878bd5e871
    2、每一个微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置

 2)、配置集:所有的配置的集合

 3)、配置集ID:类似文件名。
    Data ID:类似文件名

 4)、配置分组:
    默认所有的配置集都属于:DEFAULT_GROUP;
    1111,618,1212

每个微服务创建自己的命名空间,使用配置分组区分环境,dev,test,prod


25、分布式组件-SpringCloud Alibaba-Nacos配置中心-加载多配置集

    接下来呢,我们来继续测试,从配置中心中,我们同时加载多个配置集。
    我们先来设想一个场景,随着我们业务呢不断的壮大,我们这个微服务,可能有非常非常多的配置,我们呢,不会将这些所有的配置全部都写在这么一个配置文件中,这样这个配置文件中的内容又多又乱,不好维护。
    那我们一般的做法呢,都是来拆分出不同的配置文件,比如,跟数据源有关的配置,我们写在某一个配置文件里边,datasource,properties,和我们这个框架有关的一些配置,比如我们写在mybatis点properties里边,和我们这个微服务等等其他有关的配置,我们都会拆分成,不同的配置文件。
    而,我们这个nacos配置中心呢,也支持我们这种操作。比如呢,我们想要将这个配置里边所有内容,都让nacos配置中心来管理。我们以前呢,可以将所有内容全部放到一个配置文件中。现在可以这么来做。
    好,我一个一个来抽取,我呢,先把跟数据源有关的datasource点,欸,我们现在呢是一个yml,好,我们写一个yml,我们还是呢,放在开发组dev组,好yml,那将跟数据源有关的内容呢,我复制过来我放到这。放到这,那我将跟数据源有关的内容呢,我们就放到了datasource的这个配置里边,‎同样的,我们将跟三大框架,比如这个mybatis有关的内容,我们又放到mybatis的配置里边。由我们再来创建一个。 mybatis.yml,同样我们还是dev,这个组,好,我们把这个yml呢,我们给这里复制,这事跟mybatis有关的这些配置。然后呢,包括我们将其他的一些配置,比如这是,呃,我们nacos注册中心的,包括我们服务的端口号,欸,比如我们再来添加一个配置,欸,我们就叫other吧,其他的一些配置。好,我们也叫dev组,这个yml呢,我们来给这一复制,我直接一复制。把我们以前提取出来的呢,我就可以先删掉了。只留下,欸,我们这个有用的,好,这数据源呢,已经提取出来。

在nacos的coupon命名空间新建配置
 
Data ID:datasource.yml
Group:dev
配置格式:YAML
配置内容:
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/gulimall_sms
    driver-class-name: com.mysql.cj.jdbc.Driver


Data ID:mybatis.yml
Group:dev
配置格斯:YAML
配置内容:
mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml
  global-config:
    db-config:
      id-type: auto


Data ID:other.yml
Group:dev
配置格式:YAML
配置内容:
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: gulimall-coupon

server:
  port: 7000


    好,我点一个发布。那么呢,我们就会发现,其实呢,我们将我们整个微服务的所有配置,我们拆分成了这么几个文件,只有这几个文件全部合起来,才能构成我们微服务的整个配置,那我们需要让我们这个微服务一启动的时候,同时来加载多个配置文件,怎么同时加载呢?欸,我呢就可以把这一块我们可以先来注掉,我们想要加载的话我们可以这么来加载。
    首先还是这个namespace我们打开,我们这个微服务呢,只加载当前自己名称空间下的东西,我们可以来写一个这个,叫spring cloud,这有一个config。config里面呢有一个extended,ext-config,我们扩展的配置,而且这个ext-config呢,我们点过来发现这是一个List,我们可以来写多个,那既然能写多个,我们在这就写0,欸,第一个配置,点一个,这有data-id,group以及refresh三个选项,那data-id,指的就是我们来加载配置中心中的哪个配置集,那,我们这有一个配置集的id,叫datasource.yml,好,我们写,加载它,同样呢,我们还是第0个配置。继续来配,也就是呢,datasource.yml,他呢是属于哪个分组,比datasource它有不同的分组,有dev组,prod组不同的分组,不同的配置,但是呢,我们现在只写了一个组叫dev,相当于呢,我只加载dev组的datasource.yml,呢,我们这个要不要动态刷新,欸,这还有一个功能叫refresh,要不要动态刷新,这动态刷新呢默认是false的,而不具有动态刷新功能,也就是我们在配置文件中,如果改了这个东西,在配置中心中改了,那我们的这个微服务不会刷新,那如果我们想要刷新,我可以把这一块呢写成true,由于它默认是false的,这一块呢,就相当于加载了一个配置文件,那其他的配置文件,继续一一到此里往下添加,好,把这三个呢来复制一下,我们不只要加载datasource。欸,接下里呢,这是第二个,第三个配置。我们不止呢,要加载datasource.yml,我们同时还要加载mybatis.yml。好,我们同时呢,还要加载我们的other.yml。other.yml,那相当于呢,我呢就将application.yml里面的所有内容,我们都放到了配置中心,行,我可以把它注掉,我来看我们配置中心的东西能不能被用到。

修改gulimall-coupon的bootstrap.properties文件。

spring.application.name=gulimall-coupon

spring.cloud.nacos.config.server-addr=127.0.0.1:8848
#选择哪一个命名空间
spring.cloud.nacos.config.namespace=09fc37f9-37c4-4aad-8d91-d996d2836f28
#选择哪一个分组,不写就是默认分组
#spring.cloud.nacos.config.group=prod

spring.cloud.nacos.config.prefix=datasource.yml
spring.cloud.nacos.config.group=dev
spring.cloud.nacos.config.refresh-enabled=true

spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml
spring.cloud.nacos.config.ext-config[1].group=dev
spring.cloud.nacos.config.ext-config[1].refresh=true

spring.cloud.nacos.config.ext-config[2].data-id=other.yml
spring.cloud.nacos.config.ext-config[2].group=dev
spring.cloud.nacos.config.ext-config[2].refresh=true

注释gulimall-coupon的application.yml文件里面的所有内容

    我们在这呢就配置好了,让要从配置中心中再来读这三个文件,来重启一下我们这个,coupon这个服务。好,coupon,来重启一下我们这个服务。来看一下他现在的这个效果。
【重启】

    首先呢,我们在启动的时候观察日志,它读取了哪些配置,在日志里边都会有。好,我们现在看一下,他呢相当于读取了这几个,加载nacos的这个数据,读取了datasource.yml,读取了mybatis.yml,也读取了other.yml,同时呢,还读取了他默认要用的gulimall-coupon.properties,欸,因为我们知道即使在不配这些情况下,我们这个微服务呢一启动都会读取到他的这个当前,服务名.properties这个文件,好相当于它会读取这么四个1234,那我们来进行一个测试。
    我们首先呢,测试,我们来刷新,欸,测试呢,这一块用户名和年龄获取的是张三2,20,因为呢,我们在nacos中,我们来看一下这个配置,欸,详情,我们这个呢叫dev,18,我们的这个prod,我们来看一下,这个呢,叫prod,20,并不是我们的这个张三2,20,为什么呢?相当于我们在这来加载我们的gulimall-coupon的时候,来看一下,它加载的呢,是默认分组的,欸,它加载的是默认分组的,而我们呢,这个gulimall-coupon,现在呢有一个dev组和prod组,相当于呢,没有那个默认DEFAULT分组的,那没有默认呢,它会读取什么,它会读取配置文件中的,是张三2,20,也就是配置中心中没有的,就用配置文件的,配置中心有的,用配置中心的,好,我们在这呢还是回到它原样,我们让他呢加载默认配置文件的时候,是加载prod下边的。

取消gulimall-coupon的bootstrap.properties文件的注释
spring.cloud.nacos.config.group=prod

    来测试一下。即使是默认的配置文件也是加载prod下边的,prod下边的应该返回的是prod,20,来测试一下刷新,唉,我们发现呢,读取到的是prod,20,这块呢是没问题的。
    那数据源相关的配置对不对呢?只要这一块呢没报错,那看起来是对的,那我们也可以来发一个请求来测一下,我们让他们查一下数据库,看一下他对不对。比如呢,我们这个coupon/coupon下的我们的这个。我们这个list请求,他呢就会调用我们service来查数据库,欸,我们发一下这个请求就行了,coupon/coupon/list,来测一下。好,在这儿呢来测试list。
【启动,访问localhost:7000/coupon/coupon/list】

    欸,他呢,查数据库查到的,咱们这个总记录数什么都没有,但是呢,它已经连上数据库没有报错,这说明是没问题的。那这样呢,我们最终对配置中心的使用来总结一下。
    那以后呢,我们每一个微服务,我们微服务啊,微服务,微服务,任何配置信息,任何配置信息,或者呢,任何配置文件,任何配置文件,都可以,都可以放在配置中心中,配置中心中。然后呢,接下来,我们只需要, 只需要在我们这个bootstrap.properties中来说明加载配置中心中,配置,配置中心中哪些配置文件,文件,即可。这样呢,我们只要读取到我们指定的这些配置文件以及默认的这些配置文件,我想要获取配置文件的这些值,那我们自己想要获取,可以用@Value,欸我们之前测过,或者呢Spring Boot以前所有获取配置文件值的注解都能用,比如ConfigurationProperties,欸找一下,ConfigurationProperties,比如这个注解,也可以来获取,比如呢,以前Spring Boot任何方式来从配置文件中。等等等等,以前,SpringBoot,任何方式,从配置文件中。配置文件中,获取值,都能使用,他呢都能从配置中心中获取,而且默认的规则是配置中心,有的优先使用配置中心中的,中的值。

3.同时加载多个配置集
1)、微服务任何配置信息,任何配置文件都可以放在配置中心中。
2)、只需要在bootstrap.properties说明加载配置中心中哪些配置文件即可
3)、@Value,@ConfigurationProperties  。。。
以前SpringBoot任何方法从配置文件中获取值,都能使用。
配置中心中有的优先使用配置中心中的。


    那这呢就是我们以后配置中心的使用方法,大家可以看到application.yml的所有内容全搬家了,包括这里边的内容【application.properties】,我们之前也搬家放过去了,所以呢,最终我们的这个微服务啊,其实只需要保留一个biitstrao.properties,让他呢一启动,自己来配置中心中获取内容即可,我们呢,可以将所有的配置都写在配置中心中,但,现在开发期间,为了方便我们还是写在yml上,等线上,一上线以后呢,我们先将所有的yml可以配在配置中心中。
    关于nacos更多的信息呢,大家都可以百度nacos,来到他的官方文档,欸,这可以切换成中文的文档,这里面呢有包括nacos跟Spring Boot,Spring Cloud等各种整合,包括docker上的各种部署,包括他的其他各种详细的细节信息,以及它的一些参数配置等等等等,那么我们到时候呢,需要有什么修改设置,我们都是可以参照这个文档的。
【https://nacos.io/zh-cn/docs/what-is-nacos.html】

26、分布式组件-SpringCloud-Gateway网关核心概念&原理
 

    前面,我们介绍使用了注册中心和配置中心,那在分布式开发中呢,我们还需要一个API网关,它扮演着至关重要的作用。
    举一个例子,我们后台管理系统呢,要经常给商品服务等各个服务来发送请求,我们现在想要做一个商品的增删改查,那我们发请求呢,就需要知道我们商品服务所在的地址。
    假设我们写了一个一号机器的10000端口,那一号机器掉线了以后呢,难道我们要在前端系统里边,又把它改成二号机器的10000端口。关键我们这个商品服务,可能十几台机器同时上线,某一个用不了,还要动态的,能切换到一个能用的状态。我们不可能天天去我们的后台管理系统,代码里边来改,我们各个服务所在的端口,这样编写呢,太麻烦了。
    那我们需要呢,后台管理系统,以后给任何服务发送的请求,都先经过网关,网关帮我们动态的路由到各个服,而且网关呢,也能从注册中心中,实时的感知某一个服务,上线还是下线,总是能帮我们把请求正确的路由到指定位置,这是我们说的第一种需求。
    那第二种需求,我们每一个请求过来呢,可能后期,我们要给他加上权限,我们要鉴权,包括呢,我们要监控等等,那我们去每一个服务都要做这事,如果我们把这些功能写在各个服务上,那,这样就出现了很多重复开发,那我们呢,就可以让我们的这个客户端,不去来直接请求各个服务,让各个服务来做这些事情,比如鉴权、限流、日志输出。
    那我们让客户端呢,比如我们的后台管理系统浏览器,先来请求我们的API网关。由我们的网关呢,代转给其他服务,那我们可以在网关层,将这些统一的功能进行处理。
    那我们呢,就使用Spring Cloud为我们提供的GateWay组件,来做网关功能,那网关呢,是所有请求流量的一个入口,在我们网关呢,我们经常会做一些路由的转发、权限校验、限流控制,等等各种功能,而且我们这个Spring Cloud GateWay这个网关,是我们Spring Cloud官方推出的,相当于第二代网关框架。
    我们以前呢,大家可能使用过spring cloud的这个zuul网关,这个zuul网关呢,还是Netflix公司为我们提供的,但是呢,由于种种原因zuul的2.0版本,还没有被应用到Spring Cloud里边,Spring Cloud官方呢,也自己来做了一个网关叫Gateway,而且它也拥有非常优秀的设计以及强悍的性能。
    比如呢,网上就有一个简单的这个测试,在spring cloud Gateway,他每秒呢,大概能处理三万多的请求,而zuul网关,这一块测试的应该是zuul的第一代产品,zuul的第二代产品也是性能很高的。但是在zuul的第一代产品呢,只有两万多的请求,包括呢,非常流行的Linkerd这个网关,他也只有28000的每秒请求处理速率。
    那学习我们Spring Cloud Gateway呢,大家全部以我们官方文档为准,我们搜索Spring Cloud Gateway,可以来到他官方,我们在这Learn里边,来,主要找到他的这个稳定发布版,我们点到他的文档进行学习,而我们以前zuul网关组件,都是Spring Cloud Netflix,旗下的,大家可以去NetFlix旗下学习zuul相关的东西。
【https://spring.io/projects/spring-cloud-gateway#learn】
    那我们现在呢,主要来说Gateway,官方文档这一块呢,也对他作了简要介绍,我们这个Spring Cloud Gateway,他是来构建一个API网关的。
    他呢拥有非常多的特性,比如呢,它是使用Spring Framework 5 框架,构建的,支持我们Spring Framework 5最新的,响应式编程,包括能无缝整合Spring Boot2.0,我们SpringCloudGateway呢,他还支持我们使用任何的请求属性,来进行路由匹配,也就是功能强大呗,然后呢,每一种路由还会有自己独特这种断言规则,以及过滤器等等支持。
    但这东西我们用了才能知道,包括他能无缝整合和Hystrix来做熔融,包括整合我们服务注册发现,要做负载均衡,以及完成路径重写,请求速率限制,等等功能,包括我们呢,即使去来编写Spring Cloud Gateway里边的,这些断言以及过滤器也会非常简单。
    但,还是那句话,他有这么多优秀的功能特性,我们只有在用完以后才能体会到,这一块呢还有官方的一大段快速识别代码,那我们就来详细的来,看官方文档,到底该怎么使用Spring Cloud Gateway。
    好,我们点击Single HTML,那要使用Spring Cloud Gateway呢,我们首先得了解一下,他的几个基本概念,在Glossary章节,首先我们看这么三大概念。
    第一个叫Route,就是我们说的路由。那路由呢,顾名思义就是呢,发一个请求,给网关,那我们网关呢,要将这个请求路由到指定的我们这些服务,或者指定的地址,那这个路由呢,就包含几个重要的东西,首先呢,有一个标识性的ID,也就是每一种路由跟路由之间,是用这个ID来进行区分,还有一个目的地的URI,也就是我们当次请求到底要路由去哪,我们得有一个指定的地址。还有 collection,这就是集合,还有我们这个断言的集合。断言是什么意思,还有我们这个过滤器的集合。过滤器是什么意思,那我们下面呢,都有说,那简而言之就是一句话,我们这个路由啊,只要匹配了这个断言,我们这个断言为真,我们这个路由就匹配了,就能到达指定位置。也就是说我们请求发给API网关,到底要不要路由到某一个地方,我们得有一个条件判断。就叫断言。
    那断言又是什么呢,我们可以来看一下,他呢其实是我们Java 8里边的这个断言函数,在我们网关里边的这些断言呢,就是,允许我们这些开发人员,去来匹配当次请求的任何信息,比如,我们请求头或者请求参数,唉,那简单来说,可能是这样子的,我请求发过来,发给网关,我网关呢,可能会根据你的请求,参数,请求头等各种信息的不同,我来判断你到底要路由到哪个服务,那我们这个判断呢,就叫断言。只要我们这个判断成功了,比如按照你的请求路径判断成功了,我去这,那我们断言成功,我们就路由到指定位置。
    但,想要路由到这个指定位置,我们这还多了一个叫Filter,这个概念。这个呢,就是我们说的过滤器,那过滤器呢,就是我们,这块说的Spring框架里边提供的这个,网关过滤器,这些组件,那过滤器的功能,那跟我们以前理解的过滤器肯定都是一样啦,请求过来,我们先要过滤。欸,那到达以后呢,请求再要抵达回来,那还要过滤,就像官方文档说的,欸,在我们这个过滤器里面呢,我们这些请求或者,这些响应啊,都可以被修改。在我们请求抵达目标之前,或者呢,在我们请求到达,完成这个响应之后,这都能进行处理,那整个他的工作流程呢,其实是这样的。
    我们,有一个客户端,想要呢,发请求给我们目标服务,那我们中间呢加了一层API网关,我们这个网关呢,就是拿这个Gateway做的。那它的流程呢,是客户端添加请求发给我们API网关,也就是我们的Spring Cloud Gateway,那这个Gateway呢,通过它里面的Handler Mapping,相当于我们这些映射信息,来看一下,我们当前请求能否被路由或者被处理,如果能被处理的话呢,它就会交给这些Handler处理器,那处理器呢要处理这些请求,就会经过一系列的Filter,那当我们这个处理器处理结束了以后呢,我们就会把这个请求路由给指定的服务,我们这一系列的处理结束以后就路由给指定服务,那指定服务处理完了,还是这一系列Filter再返回过来,最终再返回给,我们客户端,这是这么一个流程。
    这个流程呢,结合这三个概念,其实总结起来就是一句话,当我们请求到达网关,网关先利用断言,来判定我们这次请求是否,是不是符合某个路由规则,如果符合了,就按这个路由规则把它路由到指定地方,但要去这些指定地方,就要经过一系列的Filter进行过滤。
    大家掌握这个核心流程,那我们Spring Cloud Gateway这个网关用起来就非常简单了。
    那么其实它最终的所有难点都集中在,我们该如何定义一些路由规则,包括这些断言是怎么判定成功失败,我们该怎么配置或者怎么写,包括,我们要使用哪些Filter,我们得自己心里清楚。
    而且呢,其实我们Spring Cloud Gateway里边,到底能怎么用断言,有多少种断言规则,包括有多少种Filter,官方文档也写的非常清楚,我可以一直往上翻,看目录这一块。这里呢,就给我们说明了,我们这个路由的,这个断言工厂,也就是说,它有这么多种断言,断言的作用呢,就是只要满足了,我们指定的这个条件,那我们就给你去路由到指定的位置,这是断言,包括能有多少种Filter,在这一块呢,也写得非常清楚,其实呢,听这些名字我们可能大概,就有点感觉,比如这有一个Filter叫AddRequestHeader,Filter,那它的作用呢,就是添加请求头的,那也就是,可能是当我们请求一过来,来到网关的时候,在抵达目标服务之前,网关给他添加一个我们指定的请求头,那来到我们目标服务,我们目标服务就能获取到我们网关刚添的这些请求头了,包括还有各种其他的Filter。
    那我们来编写网关相关的代码之前呢,我们可以先看一个非常简单的配置示例,比如呢,我来点进来。我们网关呢,最终你可以写在配置文件里面,配置各种网关的规则,其实呢,就这么几大块配置。
    第一个,我们会看到Spring CLoud Gateway,那这就是配置Spring Cloud网关的,网关里边呢,有一个东西叫routes,欸,一听加了个s,这叫路由规则,所有的路由规则呢,都能写在这,所以说呢,我们在yml中配置,先是一个杠,杠呢,右边这一堆,那其实是一个完整的对象,这都是yml的语法,那到底有多少种路由规则,我们都可以在这写,那路由规则呢,就是一个数组,这呢只有一个示例,我们可以继续往下写,继续往下写,那我们就来看一下这个示例,每一种路由规则呢,首先都得有一个ID,就是呢,当前路由规则的一个名字,不跟别人重复就行了,那这个uri的意思就是我们想要去哪个地方,我们看到呢,这又有一个叫predicates,这叫断言。杠这种写法,又是一个数组,也就是我们可以满足很多的断言,断言的意思,就是只有我们下边的东西,条件判断成功了,我们才给你路由到指定的地方。那我们这个示例是什么意思呢?我们能看到这是一个叫After Route Prodicate Faotory,这是一个叫什么之后的这个断言工程,它的作用是什么?官方文档都说的非常清楚,说,这个工程,他需要一个参数,这个参数呢,是一个时间,然后呢,这个断言就是用来匹配,当前请求,是不是在我们指定的这个时间之后,每发一个请求呢,都有一个时间,你在我指定的时间之后发的,那相当于满足了我这个判断,我才给你去这个地方,这其实呢,就是一个简单的配置示例。
    那我们想要看更多的这些示例,每一种断言规则的这些配置,样例在官方文档都有,包括我们过滤规则,我们都可以看。
    我们往下翻,比如呢,我们就看刚才的AddRequestHeader,来看他是怎么用的,还是这段配置,Spring Cloud Gateway,我们要配置路由规则,我们现在呢只配了第一种路由规则,给他呢随便起了一个名字,但是这一块呢,没有写断言,那就是任何请求,一上来都给你路由到这个地方。那路由到这个地方呢,要经过这些filter,要经过哪些filter,我们看到filters下面呢,写了一个杠,又是一堆数组,经过哪个filter呢,这是我们当前的filter的名字,相当于他把filter的名字给这一写,要经过这个filter,然后呢,这就写了这两个参数,什么意思,文档也说得非常清楚,这两个参数呢,是一个name value,名值对,这个名值对的作用,举一个例子,我们写了一个X-Request-Foo,Bar,他呢,将会添加这么一个请求头,那请求头的名就是他,值就是它,这个呢,就是我们Spring Cloud Gateway的一些最基本的简单用法,那我们下一节课呢,就来创建这个网关,我们来测试一下。
 

27、分布式组件-SpringCloud-Gateway-创建&测试API网关

【https://spring.io/projects/spring-cloud-gateway#learn】

    接下来,我们创建一个项目,作为我们的API网关,好,我先来右键new一个Module,我们还是使用spring的初始化向导。来选择下一步。我们的包名呢是com.atguigu,那我们的模块呢,是我们gulimall的gateway,我们的网关,好,我把下边呢,改一下,这个是我们的API网关。
    下一步,来,首先要选中我们的网关,我们来搜索gateway,好,直接来选中网关,在这一块呢,我们这个网关就选中了。我们选择下一步。 Finish。

在gulimall项目右键,新建项目——new——Module——Spring Initializr——Defult——Next

Group:com.atguigu.gulimall
Artifact:gulimall-gateway
Description:API网关
Package:com.atguigu.gulimall.gateway

Dependecies直接搜索gateway选中。
Spring Cloud Routing:Gateway

    同样,我们网关呢,还是要来依赖我们的common工程。我们在这来编写,我们dependencies,我们依赖gulimall-common。这个common里面呢,引入了我们的服务的注册发现以及配置中心,而且呢,我们网关也需要把自己注册到注册中心中去,他呢,同时也要发现其他服务所在的位置,这样,我们请求一过来,我们的网关就可以找到,我们的目标服务都在哪些机器里边,可以帮我们把请求路由到指定位置。
    同时呢,我们来修改一下我们网关的Spring Boot以及Spring Cloud对应的版本,那我们之前创建项目呢,使用的都是Spring Boot2.1.8,好,我们把boot版本呢改为2.1.8,包括我们使用的是Spring Cloud的这个Greenwich.SR3版本,好,把它改成Greenwich。好,把他呢复制过来。


修改pom.xml文件
添加依赖
<dependency>
    <groupId>com.atguigu.gulimall</groupId>
    <artifactId>gulimall-common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

复制其他项目的Spring Boot和Spring Cloud的版本依赖到gulimall-gateway的pom.xml文件

    接下来我们配置和测试一下网关,首先呢,我们来打开网关的整个main方法。我们要使用网关呢,首先我们要使用第一个功能,我们让网关,开启服务的注册发现。开启服务注册发现,这样我们网关想要将请求路由到其他服务,他就知道其他服务在哪了,我们要使用@EnableDiscoveryClient。

在gulimall-gateway的启动类GulimallGatewayApplication里面添加注解@EnableDiscoveryClient

    那要使用服务的注册发现,由于我们网关引入的是我们common里面的nacos,那我们nacos呢,就先得启动,我们这个nacos呢启动起来了,同时呢,我们要使用nacos,得配置nacos的相关地址,所以在服务的注册发现里边,我们主要配置nacos。的,咱们这注册中心地址。好,我们在application. properties里边,我们来配置nacos,discovery的address,欸,找一下server.addr。我们是本机的127.0.0.1:8848 。
    同时呢,配置我们当前应用的名字spring.application.name,我们当前用的名字呢,就是我们的网关。

修改gulimall-gateway的application.properties文件

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.application.name=gulimall-gateway

    当然我们还引入了配置中心,我们以后网关的所有配置,都可以放到配置中心中,那配置中心的配置文件呢,我们也来加上是bootstrap.properties。在这一块呢,主要让加上我们配置中心的地址,nacos的config,欸config.server.addr,是127.0.0.1:8848。
    然后按照我们以前的约定,每一个项目呢都有它自己的名称空间,欸,我们nacos,我们config.namespace,来找到,我们当前这个项目的名称空间,我们在nacos中,为我们,我们在nacos中,为我们的gateway项目创建一个名称空间,我们在这名称空间里边,新建名称空间,以后每一个项目呢,都有自己的名称空间,好,我们就叫gateway,这个网关。网关的这个名称空间。网关所有的配置呢,我们都放到这个名称空间下。
    来到配置列表,那我们网关的这个名称空间gateway,在这,那我们希望呢,就以后网关的配置,比如我们在这添一个Data ID,我们就叫gulimall-gateway点,欸,那我们以后呢,网关整个用yml配置比较合适,我们后来呢再说,我们先写一个yml,我们先配上最简单的,比如当前应用的名字,spring:application。冒号下面的name,好把这个名字配上就叫gulimall-gateway。来发布一下。
    好,我们网关的这个配置呢,我们先添上了,那我们在这呢,namespace就来指定上gateway的,名称空间的这个唯一ID,来复制过来,复制过来。
    如果我们有多个配置文件,还可以像我们以前的这种写法一样,在这同时加载多个配置文件,这样来写,但我们现在呢,目前只有一个配置文件,而且分组还是默认分组,那我们这一块呢,就可以先不写他的分组配置信息,但我们项目一启动,连接配置中心也要得知道项目的名字,所以我们将项目名字,同时在这儿配置一下,好,我们来复制过来,那接下来呢,我们就来启动咱们这个网关,来启动我们的网关来测试一下,他现在能否正常启动。

在gulimall-gateway的/resources目录下创建bootstrap.properties文件

spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=命名空间唯一ID

在nacos给gateway创建一个命名空间
命名空间名:gateway
描述:网关名称空间

在网关的命名空间,新建一个yml配置
Data ID:gulimall-gateway.yml
Group:DEFAULT_GROUP
配置格式:YAML
配置内容:
spring:
    application:
        name:gulimall-gateway
发布

    好,我们Run起来。我们发现了这一块的,单元测试有些不对,这是因为我们之前创建Gateway项目的时候,Spring Boot用的是高版本,高版本呢不是这样子的,好,我们把它切换为低版本以后,让他重新导入单元测试,唉,这就行了,我们呢,让他重新运行。启动起来。来看网关项目的启动。欸,我们发现呢网关项目在这儿出现了问题,说我们这个启动的时候呢,他在报,数据库相关的没有放在类路径下,也就是跟数据库的url地址没有配置,那为什么呢?这是由于我们在引入common的时候,我们同时呢,引入了我们MyBbatis相关的操作,那引入了Mybatis相关的操作,就有了数据源相关的自动配置,所以我们网关呢暂时没有用到什么数据源,那我们就可以在网关引入我们common的时候排除Mybatis Plus相关的配置,或者用最简单的方式,我在这呢,让他排除掉,跟数据库有关的自动配置,我来写一个exclude,exclude什么呢,我们就叫DataSourceAutoConfiguration,好,我们排除都跟数据源有关的配置。

修改gulimall-gateway的启动类GulimallGatewayApplication,修改一个注解

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

    好,我们来重新运行起来。那我们这个网关呢,就在8080端口启动了,我们呢以后给他编排一下,网关所使用的端口呢,我们来写一个server.port,网关的端口就是88。以后所有请求呢, 都发给我们项目的88端口,有网关路由的其他服务,我们重新启动。

在gulimall-gateway的application.properties文件,添加

server.port=88

启动

    好,现在呢网关启动成功,而且我们整个 网关呢,它不是使用Tomcat做的,它是使用Netty来做的呢,Netty呢,具有非常高的网络性能,我们来直接访问网关,localhost我们现在网关是88项目,那现在呢,由于我们网关想要做的功能是将我们请求转给其他服务,那么就来测试一个。
    测试一个什么请求呢,我希望来发送hello的时候,能带一个url地址,如果我带的是baidu。那就给我们转到www.baidu.com,如果我带的是qq,他就给我们转到qq,www.qq.com,想要做这个功能呢,我们需要对网关做一个配置,所有的配置呢都要参照网关的官方文档。
    那我们配置呢,还是写在yml里边好,我们将我们的配置写在yml里边,后来上线我们都可以搬到配置中心,我们先写在这application.yml,那我们的配置怎么写呢,先来看我们的第一个。 Spring Cloud Gateway,首先routes,就是多种路由规则,那我们就先来写上spring.cloud.gateway,gateway,我们先来配置routes这是路由规则,由于它里边呢是一个数组,所以我们需要配一个数组,那数组在yml里面的配法呢,是-,那数组里面是一个对象,接下来就在这来写对象的相关信息。
    首先第一个信息我们说,每一个路由都得有一个唯一ID。欸,我们就,随便叫一个,比如叫test_rour,我们来测试我们网关的路由功能。
    接下来我们说网关的工作原理是,满足某种断言,给你去哪个地方。
    好,我们来看一下,我们要去的地址,好,我先来写一下uri,比如我们要去的地址呢,是三,https://www.baidu.com,什么时候要去百度呢 ?我们就得满足某种断言规则,我们就可以在这配置我们的断言,这个配置呢,也可以参照官方文档后。我们来到,唉,我们是按照参数的,这有一个叫Query Route Predicate Factory,我们的这个参数的路由的这个断言工厂,在这一块呢,我们写个predicates,这是所有的断言规则,断言规则里面呢,其中有一个规则叫Qoery,因为断言规则里边也是一个数组,有多个规则,我们可以看一下,欸,他还是一个list数组,那写数组呢,我们来写,第一个断言,杠,好第一个断言呢,我们用的是Query,这种断言方式,所以这块呢,固定写了先写一个Query,意思我们用这种断言,这断言呢是什么,我们是希望有一个参数叫url,如果它等于百度就去那,那我们就写一个叫url,那接下来怎么做呢,来看这一块。
    我们第一种写法Query等于什么,那就是如果我们有这个参数我们就去这,但是我们还要参数等于指定值,那么接下来就是这个,Query=foo逗号ba点。那他的意思呢就是,如果我们包含了这个参数,而且呢这个参数的值,匹配这个正则表达式,也就是后边的这个值还可以是正则表达式,那么现在是精确率,那我们就直接来写baidu,欸,如果呢,你带了baidu我们就去这同样的,我们继续来写,如果带了qq,我们就去qq,好,ID,接下来是路由到qq的地方,来写个route,同样,uri,我们路由给qq。 qq.com,然后呢,我们的规则是什么,来写上,我们是按照参数的方式。走,参数呢,现在url等于qq,欸,那我们就路由到qq服务。

在gulimall-gateway新建application.yml文件

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: https://www.baidu.com
          predicates:
            - Query=url,baidu

        - id: qq_route
          uri: https://www.qq.com
          predicates:
            - Query=url,qq



    好,我们现在来启动我们这个网关。测试一下我们现在是否能发送我们想象的这些请求,来到达我们指定的位置。来看一下,好,网关呢,现在正在启动过程中。好,网关已经在88端口启动,我们先来访问qq,我们来访问hello带一个qq,回车,唉,我们发现呢,现在确实是跳到qq,只是呢,什么页面不存在,那我们再来访问baidu,如果我们带了百度,回车,然后呢,那就访问到百度,为什么不存在,是因为我们转发请求的时候,我们跳到qq的hello地址,也就是说我们网关会跳给qq的hello,所以我们最终相当于访问的是www.qq.com。欸,因为我们的访问路径他也会转过去,欸,访问的是这个,我们叫hello,所以qq会说不存在,最终呢,就出现的是qq之前的那个404页面。

访问:
localhost:88/hello?url=qq
localhost:88/hello?url=baidu

    好,那网关的更多配置呢,我们在项目里面用的时候,直接参照文档进行配置就行了,我们在这先做一个简单实例。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汤永红

一分也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值