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服务器 + 测试


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

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

<!--添加eureka-client客户端-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

第二步:修改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 # 单机

注意事项:

  • 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/** # 断言。 路径相匹配的进行路由。

第二种:代码注入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();
    }
}

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 # 单机

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] # 在这个时间之间,才能正常通过路由。

Cookie Route Predicate参数:

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

在这里插入图片描述
通过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;
    }
}

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


在这里插入图片描述

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


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

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

在这里插入图片描述


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


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

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


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


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

在这里插入图片描述

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

<!--springcloud config配置中心的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

<!--添加eureka-client客户端-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

第三步:修改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

第四步:添加启动类,添加@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);
    }
}

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

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

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


SpringCloud Config有客户端和服务端。

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

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

第二步:创建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
  • 其实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;
    }

}

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

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

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


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

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

第二步:暴露监控端点。

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: "*"

第三步: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;
    }

}

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

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

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

这样的配置是优缺点:

  • 多个服务器需要台台发送请求,很麻烦。
  • 再个就是100台机器,我想要其中的几台变更,这样也是没法实现很麻烦。

猜你喜欢

转载自blog.csdn.net/IT_Holmes/article/details/125537099