• SpringCloud 学习笔记总结 (五)


    1. zuul 与 Gateway


    netflix公司研发出了zuul。

    zuul现在已经停止更新,之前要出zuul2,zuul2的研发也一直延迟。

    zuul一直做网关的效果。

    Gateway是SpringCloud公司自研发的第二代微服务网关,代替了zuul。

    2. Gateway 之 简介


    Gateway的位置:
    在这里插入图片描述


    SpringCloud Gateway网关底层用了netty通讯框架:
    在这里插入图片描述


    webflux是什么?

    • WebFlux 模块的名称是spring-webflux,名称中的Flux 来源Reactor中的类Flux。Spring webflux 有一个全新的非堵塞的函数式 Reactive Web 框架,可以用来构建异步的、非堵塞的、事件驱动的服务,在伸缩性方面表现非常好。

    项目架构图:

    • 请求一般想通过nginx负载均衡,之后进入网关集群中。
      在这里插入图片描述

    3. Gateway 之 核心概念 + 架构流程


    网关gateway的三个核心概念:在这里插入图片描述

    Gateway网关架构图:

    • 核心逻辑就是:路由转发 + 执行过滤器链
      在这里插入图片描述

    官方架构图:
    在这里插入图片描述

    4. Gateway 之 搭建Gateway服务器 + 测试


    第一步:创建项目,配置依赖。

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-gatewayartifactId>
    dependency>
    
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    第二步:修改application.yml文件,添加路由ID,路由地址,断言。

    server:
      port: 9527
    
    spring:
      application:
        name: cloud-gateway
      cloud:
        gateway:
          routes:
            - id: payment_routh # 路由ID。 没有固定规则但要求唯一,建议配合服务名。
              uri: http://localhost:8001 # 路由地址。 匹配后提供服务的路由地址。
              predicates:
                - Path=/payment/get/** # 断言。 路径相匹配的进行路由。
    
            - id: payment_routh2 # 路由ID。 没有固定规则但要求唯一,建议配合服务名。
              uri: http://localhost:8001 # 路由地址。 匹配后提供服务的路由地址。
              predicates:
                - Path=/payment/lb/** # 断言。 路径相匹配的进行路由。
    
    
    eureka:
      instance:
        hostname: cloud-gateway-service
      client:
        service-url:
          # 表示是否将自己注册进EurekaServer默认为true
          register-with-eureka: true
          # 是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
          fetch-registry: true
          # 入驻地址是哪个
          defaultZone: http://eureka7001.com:7001/eureka # 单机
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    注意事项:

    • Gateway网关不要引入springboot web 和 actuator依赖。

    第三步:启动项目,进行测试。
    在这里插入图片描述

    5. Gateway 之 路由的两种配置方式


    第一种:就是上面演示的,在配置文件yml里面配置。

    spring:
      application:
        name: cloud-gateway
      cloud:
        gateway:
          routes:
            - id: payment_routh # 路由ID。 没有固定规则但要求唯一,建议配合服务名。
              uri: http://localhost:8001 # 路由地址。 匹配后提供服务的路由地址。
              predicates:
                - Path=/payment/get/** # 断言。 路径相匹配的进行路由。
    
            - id: payment_routh2 # 路由ID。 没有固定规则但要求唯一,建议配合服务名。
              uri: http://localhost:8001 # 路由地址。 匹配后提供服务的路由地址。
              predicates:
                - Path=/payment/lb/** # 断言。 路径相匹配的进行路由。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    第二种:代码注入routeLocator的bean。

    • 案例访问百度的地址。
    package com.itholmes.springcloud.config;
    
    import org.springframework.cloud.gateway.route.RouteLocator;
    import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class GateWayConfig {
    
        //使用注入bean的方式来修改网关的路由
        @Bean
        public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
            RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
    
            // 这里映射百度的地址 , 目录为https://news.baidu.com/guonei
            //这样访问http://localhost:9527/guonei 就会 访问到 https://news.baidu.com/guonei的信息
            routes.route("path_route_itholmes",
                    r -> r.path("/guonei")
                    .uri("https://news.baidu.com/guonei"));
    
            return routes.build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    6. Gateway 之 配置动态路由


    以上我们配置的路由都是写死的,默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。

    • 先开启从注册中心动态创建路由的功能,利用微服务名进行路由。
    • uri 配置成注册中心对应的微服务名称。
    server:
      port: 9527
    
    spring:
      application:
        name: cloud-gateway
      cloud:
        gateway:
          discovery:
            locator:
              # 开启从注册中心动态创建路由的功能,利用微服务名进行路由。
              enabled: true
          routes:
            - id: payment_routh # 路由ID。 没有固定规则但要求唯一,建议配合服务名。
              # uri: http://localhost:8001 # 路由地址。 匹配后提供服务的路由地址。
              uri: lb://CLOUD-PAYMENT-SERVICE
              predicates:
                - Path=/payment/get/** # 断言。 路径相匹配的进行路由。
    
            - id: payment_routh2 # 路由ID。 没有固定规则但要求唯一,建议配合服务名。
              # uri: http://localhost:8001 # 路由地址。 匹配后提供服务的路由地址。
              uri: lb://CLOUD-PAYMENT-SERVICE
              predicates:
                - Path=/payment/lb/** # 断言。 路径相匹配的进行路由。
    
    
    eureka:
      instance:
        hostname: cloud-gateway-service
      client:
        service-url:
          # 表示是否将自己注册进EurekaServer默认为true
          register-with-eureka: true
          # 是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
          fetch-registry: true
          # 入驻地址是哪个
          defaultZone: http://eureka7001.com:7001/eureka # 单机
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    7. Gateway 之 Predicate分类


    Predicate断言有多种,就像加了where条件一样,来判断该路由是否符合条件:
    在这里插入图片描述


    对于三个时间范围的route predicate,时间范围内符合的路由请求:

    spring:
      application:
        name: cloud-gateway
      cloud:
        gateway:
          discovery:
            locator:
              # 开启从注册中心动态创建路由的功能,利用微服务名进行路由。
              enabled: true
          routes:
            - id: payment_routh2 # 路由ID。 没有固定规则但要求唯一,建议配合服务名。
              # uri: http://localhost:8001 # 路由地址。 匹配后提供服务的路由地址。
              uri: lb://CLOUD-PAYMENT-SERVICE
              predicates:
                - Path=/payment/lb/** # 断言。 路径相匹配的进行路由。
                - After=2022-07-01T09:42:44.070+08:00[Asia/Shanghai] # 在这个时间之后的请求,才能正常通过路由。
                - before=2022-07-01T09:42:44.070+08:00[Asia/Shanghai] # 在这个时间之前的请求,才能正常通过路由。
                - Between=2022-07-01T09:42:44.070+08:00[Asia/Shanghai],2022-07-01T09:42:44.070+08:00[Asia/Shanghai] # 在这个时间之间,才能正常通过路由。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Cookie Route Predicate参数:

    predicates:
      - Path=/payment/lb/** # 断言。 路径相匹配的进行路由。
      - Cookie=username,zzyy # cookie,key是username,value是zzyy
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    通过curl可以测试有cookie请求和没有cookie请求的效果:
    在这里插入图片描述


    Header Route Predicate参数:

    • 下图意思:请求中要有一个X-Request-Id的请求头,值必须符合\d+(正则,数字)。
      在这里插入图片描述

    同上:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


    Query Route Predicate:
    在这里插入图片描述

    8. Gateway 之 Filter(GatewayFilter)


    这里指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

    Spring Cloud Gateway的filter的生命周期:

    • pre 和 post。前置,后置。

    Spring Cloud Gateway的filter的种类:

    • 两种:GatewayFilter 和 GlobalFilter 两种。

    对于GatewayFilter 和 GlobalFilter的过滤器有很多种不同的类型。


    自定义全局GatewayFilter过滤器:

    • 两个主要接口:GloalFilter , Ordered。
    • ordered就是决定优先级顺序,那个过滤器先被执行。
    • 通过exchange获取,request和response,修改一系列的操作。
    package com.itholmes.springcloud.filter;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    import java.util.Date;
    
    @Component
    @Slf4j
    public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
            log.info("*******come in MyLogGateWayFilter: "+new Date());
            //exchange.getRequest()
            String uname = exchange.getRequest().getQueryParams().getFirst("uname");
    
            if (uname == null){
                log.info("*********用户名为null,非法用户!");
                //exchange.getResponse() , HttpStatus.NOT_ACCEPTABLE是不可用请求。
                exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
                Mono<Void> voidMono = exchange.getResponse().setComplete();
                return voidMono;
            }
            //放行,去下一个过滤链
            return chain.filter(exchange);
        }
    
        @Override
        public int getOrder() {
            //order就是顺序,一般是数字越小,优先级越高。
            return 0;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    9. SpringCloud Config 之 分布式配置中心(介绍)


    在这里插入图片描述

    多个微服务之间都需要进行必要的配置信息才能运行,所以要有一套集中式的,动态的配置管理设施是必不可少的(意思就是可以统一的配置application.yml)。


    官方解释:
    在这里插入图片描述

    SpringCloud Config 分为 服务端 和 客户端两部分。

    在这里插入图片描述


    Spring cloud config的几个作用:
    在这里插入图片描述


    SpringCloud Config默认使用Git来存储配置文件(也有其他方式SVN,本地文件),推荐还是使用Git。

    10. SpringCloud Config 之 配置总控中心搭建(服务端)


    也就是搭建下面服务器:
    在这里插入图片描述


    第一步:在Github上新建一个名为springcloud-config的新Repository仓库。获取git地址。并且将仓库clone克隆下来。

    在这里插入图片描述

    第二步:创建项目,添加依赖。

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-config-serverartifactId>
    dependency>
    
    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    第三步:修改application.yml文件。

    • 配置config 的 git相关操作。
    server:
      port: 3344
    spring:
      application:
        name: cloud-config-center # 微服务名称
      cloud:
        config:
          server:
            git:
              uri: https://gitee.com/lixiaogou/sprincloud-config.git #GitHub上面的git仓库名字
              search-paths: #搜索目录
                - springcloud-config
          label: master #读取分支
    
    # 服务注册到eureka地址
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    第四步:添加启动类,添加@EnableConfigServer //开启config服务。

    package com.itholmes.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.config.server.EnableConfigServer;
    
    @SpringBootApplication
    @EnableConfigServer //开启config服务
    public class ConfigCenterMain3344 {
        public static void main(String[] args) {
            SpringApplication.run(ConfigCenterMain3344.class,args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    对应公式如下:
    在这里插入图片描述
    官方公式:

    • 建议使用第三个。
      在这里插入图片描述

    11. SpringCloud Config 之 配置总控中心配置与测试(客户端)


    SpringCloud Config有客户端和服务端。

    第一步:创建项目,添加SpringCloud Config客户端依赖。

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-configartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    第二步:创建bootstrap.yml配置文件。

    • 什么是bootstrap.yml配置文件?
      在这里插入图片描述
    server:
      port: 3355
    
    spring:
      application:
        name: config-client
      cloud:
        # SpringCloud Config 客户端配置
        config:
          label: master # 分支名称
          name: config # 配置文件名称
          profile: dev # 读取后缀名称
          # 上述三个综合: master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
          uri: http://localhost:3344 # 配置中心地址
    
    # 服务注册到eureka地址
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 其实config客户端就是先去找config服务端,对应的信息如下:
      在这里插入图片描述

    第三步:测试接口,http://localhost:3355/configInfo。

    package com.itholmes.springcloud.controller;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class ConfigClientController {
    
        @Value("${config.info}")
        private String configInfo;
    
        @GetMapping("/configInfo")
        public String getConfigInfo(){
            return configInfo;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    最大的问题就是分布式配置的动态刷新问题:

    • 意思就是当我们修改git上面的信息后,config服务端会立刻响应对应修改的数据,config客户端却没有任何响应(除非将客户端系统重新启动)!

    12. SpringCloud Config 之 配置中心 如何解决动态刷新的问题?


    第一步:添加actuator监控依赖。

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    第二步:暴露监控端点。

    server:
      port: 3355
    
    spring:
      application:
        name: config-client
      cloud:
        # SpringCloud Config 客户端配置
        config:
          label: master # 分支名称
          name: config # 配置文件名称
          profile: dev # 读取后缀名称
          # 上述三个综合: master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
          uri: http://localhost:3344 # 配置中心地址
    
    # 服务注册到eureka地址
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
    
    # 暴露监控端点
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    第三步:controller层添加@RefreshScope注解。

    • 添加了这个注解就具备了刷新的能力。
    package com.itholmes.springcloud.controller;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RefreshScope
    public class ConfigClientController {
    
        @Value("${config.info}")
        private String configInfo;
    
        @GetMapping("/configInfo")
        public String getConfigInfo(){
            return configInfo;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    注意:配置上以上内容,并不能动态刷新,还必须由运维人员发送Post请求刷新3355才行!

    第四步:由运维人员发送Post请求刷新3355。

    • 执行 curl -X POST “http://localhost:3355/actuator/refresh” 命令进行刷新。

    这样的配置是优缺点:

    • 多个服务器需要台台发送请求,很麻烦。
    • 再个就是100台机器,我想要其中的几台变更,这样也是没法实现很麻烦。
  • 相关阅读:
    智慧工地施工如何应用室内定位uwb技术
    【Dockerfile镜像实战】构建LNMP环境并运行Wordpress网站平台
    多聚焦图像融合算法
    linux软连接与硬连接
    C/C++书籍信息系统
    特殊类的设计
    Python基础入门篇【36】-python初识异常及常见的异常类型
    uni-app 之 去掉顶部导航
    React学习3(React组件)
    514. 自由之路
  • 原文地址:https://blog.csdn.net/IT_Holmes/article/details/125537099