Loading

SpringCloud Alibaba

一 微服务

image-20220805144754792

1 注册中心

在分布式开发中,如果有各个微服务,那么每一个微服务上线都应该将其注册到注册中心,这样做的好处就是:如果订单服务想要调用商品服务,那么订单服务就可以先去注册中心查看哪几个商品服务注册进来了——1号机器有一个商品服务,2号机器也有一个商品服务,那么订单服务就可以随便挑选一个商品服务来进行远程调用。

2 配置中心

各个微服务的配置众多,比如商品服务现在在10台机器上,我们想要修改商品服务的某个配置,那么这10台机器都要改,挺麻烦的。那么就需要一个配置中心来集中管理配置,然后各个商品服务都从配置中心获取配置,那么想要修改配置的时候就只需要修改配置中心的配置就可以实时地修改每一台机器上的商品服务的配置了。

3 网关

所有前端的请求都会经过网关,网关对所有的请求进行统一的鉴权、过滤、路由等等,由网关来抵达其他的服务。

二 SpringCloud Alibaba

1 简介

Spring Cloud Alibaba致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过Spring Cloud编程模型轻松使用这些组件来开发分布式应用服务。

依托Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将Spring Cloud应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

SpringCloud的几大痛点:

  • SpringCloud部分组件停止维护和更新,给开发带来不便;
  • SpringCloud部分环境搭建复杂,没有完善的可视化界面,我们需要大量的二次开发和定制
  • SpringCloud配置复杂,难以上手,部分配置差别难以区分和合理应用

SpringCloud Alibaba的优势:

  • 阿里使用过的组件经历了考验,性能强悍,设计合理,现在开源出来大家用
  • 成套的产品搭配完善的可视化界面给开发运维带来极大的便利
  • 搭建简单,学习曲线低。

结合SpringCloud Alibaba我们最终的技术搭配方案:

  • SpringCloud Alibaba-Nacos: 注册中心(服务发现/注册)
  • SpringCloud Alibaba-Nacos: 配置中心(动态配置管理)
  • SpringCloud-Ribbon: 负载均衡
  • SpringCloud-Feign: 声明式HTTP客户端(调用远程服务)
  • SpringCloud Alibaba: Sentinel:服务容错(限流、降级、熔断)
  • SpringCloud-Gateway: API网关(webflux编程模式)
  • SpringCloud-Sleuth: 调用链监控
  • SpringCloud Alibaba-Seata: 原Fescar,即分布式事务解决方案

2 如何使用

在gulimall-common中引入依赖:

国内镜像仓库:https://gitee.com/mirrors/Spring-Cloud-Alibaba

<!--# 下面是依赖管理,相当于以后再dependencies里引spring cloud alibaba就不用写版本号,全用dependencyManagement进行管理-->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

3 Nacos注册中心

  1. 首先,修改 pom.xml 文件,引入 Nacos Discovery Starter。由于上面做了依赖管理,所以这里不需要再引入依赖。
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  1. 下载nacos到本地,并启动起来(窗口要一直开着)

image-20220805161742613

下载地址:https://wwm.lanzouv.com/iA1Lg091v2kj

  1. 在应用的 /src/main/resources/application.yaml 配置文件中配置 Nacos Server 地址
spring:
  cloud:
    nacos:
      discovery:
      	# nacos的地址
        server-addr: 127.0.0.1:8848
  application:
	# 该服务在注册中心的名字
    name: gulimall-product
  1. 使用 @EnableDiscoveryClient 注解开启服务注册与发现功能
@SpringBootApplication
// 注册到注册中心
@EnableDiscoveryClient
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }

    @RestController
    class EchoController {
        @GetMapping(value = "/echo/{string}")
        public String echo(@PathVariable String string) {
            return string;
        }
    }
}
  1. 启动服务,启动成功后访问nacos:http://192.168.121.1:8848/nacos/index.html(默认账号密码是:nacos/nacos)

注:需要先启动nacos,再启动服务

image-20220805162029524

4 OpenFeign测试远程调用

OpenFeign不是SpringCloud Alibaba的,是SpringCloud的。

如何使用

  1. 引入依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在一开始建各个微服务的时候,我们已经引入过了。

  1. 编写一个接口,告诉SpringCloud这个接口需要调用远程服务。我们创建一个单独的包,专门用于远程调用。
// 存放各种远程调用方法的包
package com.example.gulimall.member.feign;

// 需要填写要调用的远程服务在nacos中的名称
@FeignClient("gulimall-coupon")
public interface CouponFeignService {
    // 需要写方法在服务中的完整路径
    @RequestMapping("/coupon/coupon/member/list")
    public R memberCoupons();
}
  1. 开启远程调用功能
@SpringBootApplication
@EnableDiscoveryClient
// 开启远程调用功能
@EnableFeignClients(basePackages = "com.example.gulimall.member.feign")
@MapperScan("com.example.gulimall.member.dao")
public class GulimallMemberApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallMemberApplication.class, args);
    }

}

这时,只要该服务启动,就会自动扫描 basePackages 所指定的包下所有加了 @FeignClient 注解的接口,每个接口又说明了调用哪个服务的哪个接口。

我在启动过程中,由Feign导致了报错:No Feign Client for loadBalancing defined.....

解决方案:https://blog.csdn.net/weixin_45942124/article/details/112170311

测试远程调用

image-20220805171433830

image-20220805171846247

image-20220805171457413

这是一个声明式的远程调用

如果别调用的那个服务没有上线,那么这个远程调用就会失败。

5 Nacos配置中心

测试读取本地配置

  1. 新建一个配置文件 application.properties

image-20220806154552936

  1. 测试是否能够读取

image-20220806154743578

测试读取Nacos配置中心配置

  1. 首先,修改 pom.xml 文件(common模块 ),引入 Nacos Config Starter。
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
  1. 在应用的 /src/main/resources/bootstrap.properties(也可以使用yaml) 配置文件中配置 Nacos Config 元数据。
spring.application.name=nacos-config-example
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
  1. springboot2.4及以上版本需要添加spring-cloud-starter-bootstrap依赖,否则boostrap配置文件无法生效
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
    <version>3.1.3</version>
</dependency>
  1. 在nacos配置中心发布配置

image-20220806162536200

image-20220806162506791

  1. 删除刚才本地测试的配置文件(不删也行,配置中心的配置比当前应用中的配置文件优先级更高

image-20220806162245147

image-20220806162712093

  1. 测试,成功从配置中心读取配置

image-20220806162843032

动态地获取配置

这时候,如果我们在配置中心更改配置,再次调用接口,返回的数据并没有动态的改变,还是之前的配置。

若想要实时地获取配置中心的数据,只需要加一个注解 @RefreshScope

// 配置刷新
@RefreshScope
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
    ...
}

加了该注解后,每次调用都会到配置中心动态地获取配置。

总结

  1. 引入依赖

  2. 创建一个bootstrap.properties

  3. 需要给配置中心默认添加一个叫 数据集(Data Id)gulimall-coupon.properties。默认规则:应用名.properties

    如果是yaml的话,需要在bootstrap.properties说明配置中心的文件后缀file-extension(要完全一致):

    spring:
      application:
        name: gulimall-product
      cloud:
        nacos:
          config:
            server-addr: 127.0.0.1:8848
            namespace: 209d5c7c-b4cc-4003-98eb-42b11bd03125
            file-extension: yml
    
  4. 应用名.properties 添加任何配置。

  5. 动态获取配置:@RefreshScope动态获取并刷新配置,@Value("${配置项的名}")获取到配置

配置中心的配置比当前应用中的配置文件优先级更高。

进阶

命名空间

核心:配置隔离。

默认:public(保留空间);默认新增的所有配置都在public空间。

开发、测试、生产:利用命名空间来做环境隔离。

  1. 在nacos上新建命名空间 test(测试环境)

image-20220807164900674

image-20220807164826430

test测试环境是我提前新建的一个命名空间。public是默认的命名空间。

image-20220807164634778

  1. 在bootstrap.properties中指定读取某个命名空间的配置
spring:
  application:
    name: gulimall-coupon
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        # 指定命名空间,后面这串是命名空间的ID,在nacos上查询
        namespace: 31be343f-3f40-4daa-935b-57686488ea0c

命名空间的ID可以自己设置。

image-20220807165638683

  1. 测试是否能够读取到test命名空间的配置

image-20220807170832121

如果只有开发环境、测试环境、生产环境这么三个命名空间的话,那么每一个命名空间下就都会有超多的配置文件,会非常混乱,所以我们可以每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置。

配置集

核心:一组相关或者不相关的配置的集合称为配置集。比如application.properties

配置集ID

类似文件名。Nacos中的配置的 Data ID

配置分组

默认所有的配置集都属于:DEFAULT_GROUP

  1. 在nacos上新建配置,并指定分组(随便填,不需要提前创建组)

image-20220807172713089

image-20220807172757254

  1. 在bootstrap.properties中指定配置组
spring:
  application:
    name: gulimall-coupon
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        # 指定命名空间
        namespace: 31be343f-3f40-4daa-935b-57686488ea0c
        # 指定配置组
        group: 1111
  1. 测试是否能够读取到1111配置组的配置

image-20220807173002464

有了命名空间和配置分组,我们就可以使用这两个概念来区分微服务和环境了。

每个微服务创建属于自己的命名空间, 然后配置不同的分gulimall-coupon.yaml组来区分环境

image-20220807180304399

image-20220807180602509

微服务的任何配置信息、配置文件都可以放在配置中心中。只要在bootstrap.properties说明加载配置中心中哪些配置文件即可。

image-20220807183458755

6 GateWay

简介

网关作为流量的入口,常用功能包括路由转发、权限校验、限流控制等。

官方中文文档:Spring Cloud Greenwich 中文文档 参考手册 中文版

用一个例子来了解网关的作用:后台管理要经常给商品服务等多个服务发送请求,我们发请求就需要知道商品服务的地址,假设我们写了一个1号机器的10000端口,那如果1号机器掉线了之后呢,难道我们要在前端项目里改成2号机器的10000端口?而且有可能这个商品服务是十几台机器同时上线,某一个用不了还要动态地切换到能用的服务,不可能经常去前端项目里改各个服务所在的端口,这样太麻烦了。所以需要一个网关来接收所有的请求,动态地路由到各个服务,而且网关能够从注册中心中实时地感知哪个服务是上线的、哪个服务是下线的,总是能帮助我们把请求路由到正确位置。而且网关还能帮我们做统一的权限管理,而不需要把权限管理重复地写到各个服务当中。

image-20220807185935120

image-20220807212307006

核心流程

请求到达网关,网关利用断言(Predicate)判断此次请求是不是符合路由规则(Route),如果符合,就按照路由规则路由到指定地方。但要到达指定地方,中间得经过一系列的过滤器(Filter)进行过滤。

创建&测试API网关

  1. 创建网关模块

image-20220807214350435

image-20220807214539650

image-20220807214611669

  1. 在网关模块引入 common 的依赖。
<dependency>
    <groupId>com.example.gulimall</groupId>
    <artifactId>gulimall-common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

需要nacos的依赖。网关也需要把自己注册到注册中心去,同时也要发现到其他服务所在的位置。这样,请求一过来,网关就能找到目标服务的所在位置。

  1. 在nacos为网关新建命名空间和配置

image-20220807221722156

image-20220807223403039

这时候启动报了个错,需要一个依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>

而且引入了gateway的依赖,会导致和common模块中的 spring-boot-starter-web 冲突,所以还要在gateway服务内排除掉common的这个依赖:

<dependency>
    <groupId>com.example.gulimall</groupId>
    <artifactId>gulimall-common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  1. 开启网关的服务注册、服务发现;配置nacos注册中心地址;网关的规则
server:
  port: 88
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      # 路由数组
      routes:
        # id:唯一标识,uri:跳转地址,predicates:断言数组
        # 这里两个断言的意思是:请求地址中有含有名为url的参数,参数的值为baidu/qq
        - id: baidu_route
          uri: https://www.baidu.com
          predicates:
            - Query=url, baidu
        - id: qq_route
          uri: https://www.qq.com
          predicates:
            - Query=url, qq
  application:
    name: gulimall-gateway
  1. 请求 http://localhost:88/?url=baidu,会跳转到 https://www.baidu.com

image-20220807231150840

posted @ 2022-08-07 23:16  KledKled  阅读(11)  评论(0编辑  收藏  举报