SpringCloud 服务网关

2022-03-17 17:41:13 浏览数 (1)

博客学习参考视频

GateWay 新网关

① 概述简介

1.官网
  • 上一代网关 zuul 1.X:https://github.com/Netflix/zuul/wiki
  • 当 前 网 关 gateway :https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/
2.是什么

概述:

一句话:

  1. SpringCloud Getaway 使用的 Webflux 中的 reactor-netty 响应式编程组件,底层使用的 Netty 通讯框架
  2. 源码框架
3.能干嘛
  1. 反向代理
  2. 鉴权
  3. 浏览控制
  4. 熔断
  5. 日志监控

….

4.微服务架构中网关在哪里
5.有了 Zuul 了怎么又出来了 gateway

我们为什么选择 Gatway?

  1. neflix 不太靠谱, zuul2.0 一直跳票,迟迟不发布
  1. SpringCloud Gateway 具有如下特性
  1. SpringCloud Gateway 与 Zuul 的区别

Zuul1.x 模型

GateWay 模型

  1. WebFlux 是什么

② 三大核心概念

1.Route(路由)

​ 路由的构建网关的基本模块,它由 ID ,目标 URI , 一系列的断言和过滤器组成,如果断言为 true 则匹配该路由

2. Predicate(断言)

​ 参考的是 java8 的 java.util.function.Predicate 开发人员可以匹配 HTTP 请求中的所有内容(例如请求头或请求参数),如果请求域断言相匹配则进行路由。

3. Filter(过滤)

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

4. 总体

③ Gateway 工作流程

1.官网总结
2.核心逻辑

​ 路由转发 执行过滤器链

④ 入门配置

新建 Module: cloud-gateway-gateway9527

POM

代码语言:javascript复制
<?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>
        <artifactId>clould</artifactId>
        <groupId>com.oy</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-gateway-gateway9527</artifactId>

    <dependencies>
        <!--新增 gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.oy</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

YML

代码语言:javascript复制
server:
  port: 9527
spring:
  application:
    name: cloud-gateway
eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表中
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

业务类 (无)

主启动类

代码语言:javascript复制
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
     public static void main(String[] args) {
           SpringApplication.run(GateWayMain9527.class, args);
      }
}

**9527 网关如何做路由映射那? ? ? **

  • cloud-provider-payment8001 看看 controller 的访问地址
    • get
    • lb
  • 我们目前不想暴露 8001 端口,希望在 8001 外面套一层 9527

YML 新增网关配置

代码语言:javascript复制
server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称j进行路由
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          uri: http://localhost:8001
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由
        - id: payment_route2
          uri: http://localhost:8001
          predicates: Path=/payment/lb/** #断言,路径相匹配的进行路由
eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表中
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

测试

  • 启动 7001
  • 启动 8001: cloud-provider-payment8001
  • 启动 8001: cloud-provider-payment8001

访问说明

  • 添加网关前: http://localhost:8001/payment/get/1
  • 添加网关后: http://localhost:9527/payment/get/1

YML 配置说明

Gateway 网关路由有两种配置方式

  1. 在配置文件 yml 中配置 (见前面步骤)
  2. 代码中注入 RouteLocator 的 Bean

官网案例

自己写一个: 业 务 需 求 : 通 过 9527 网 关 访 问 到 外 网 的 百 度 新 闻 网 址 http://news.baidu.com/guoji

代码语言:javascript复制
/**
 * 配置网关
 * @Author OY
 * @Date 2020/10/18
 */
@Configuration
public class GateWayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_rote_oy", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();

        return routes.build();
    }

    @Bean
    public RouteLocator customRouteLocator2(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_rote_oy2", r -> r.path("/guoji").uri("http://news.baidu.com/guoji")).build();

        return routes.build();
    }
}

测试

⑤ 通过服务名实现动态

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

启动: 一个 eureka7001 两个服务提供者 8001/8002

POM

YML: uri: lb//cloud-payment-service

代码语言:javascript复制
server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称j进行路由
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          #uri: http://localhost:8001
          uri: lb//cloud-payment-service
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由
        - id: payment_route2
          #uri: http://localhost:8001
          uri: lb//cloud-payment-service
          predicates: Path=/payment/lb/** #断言,路径相匹配的进行路由
eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表中
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

需要注意的是uri 的协议为 lb ,表示启用 Gateway 负载均衡功能。

lb ://serviceName 是 spring cloud gateway 在微服务中自动为我们创建负载均衡 uri。

测试:

​ http://localhost:9527/payment/lb: 8001/8002 两个端口切换

⑥ Predicate 的使用

1.是什么

启动我们的 gateway9527

2.Route Predicate Factories 是什么?
3.常用的 Route Predicate

After Route Predicate

问题一:上述这个 After 好懂,这个时间时间串串,有点不能理解。使用以下方式即可解开谜团。

代码语言:javascript复制
@Test
public void test1(){
    ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
    System.out.println(zbj); // 2020-10-18T10:35:52.127 08:00[Asia/Shanghai]

    ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/Denver"));// 用指定时区获取当前时间
    System.out.println(zny); // 2020-10-17T20:38:37.693-06:00[America/Denver]
}

YML

代码语言:javascript复制
- After=2020-10-18T10:38:37.692 08:00[Asia/Shanghai]

Before Route Predicate

YML

代码语言:javascript复制
- After=2020-10-18T10:38:37.692 08:00[Asia/Shanghai]
- Before=2020-10-18T10:38:37.692 08:00[Asia/Shanghai]

Between Route Predicate

YML

代码语言:javascript复制
- Between=2020-10-18T10:38:37.692 08:00[Asia/Shanghai],2020-10-19T10:38:37.692 08:00[Asia/Shanghai]

Cookie Route Predicate

1) 不带 cookies 访问

2) 带上 cookies 访问

加 入 curl 返 回 中 文 乱 码 :https://blog.csdn.net/leedee/article/details/82685636

代码语言:javascript复制
curl http://localhost:9527/payment/lb --cookie "username=oy"

3)YML

代码语言:javascript复制
- Cookie=username,oy #并且Cookie是username=oy才能访问

Header Route Predicate

YML

代码语言:javascript复制
- Header=X-Request-Id, d  #请求头中要有X-Request-Id属性并且值为整数的正则表达式

Host Route Predicate

YML

代码语言:javascript复制
- Host=**.somehost.org,**.anotherhost.org

Method Route Predicate

YML

代码语言:javascript复制
- Method=GET,POST

Path Route Predicate

YML

代码语言:javascript复制
- Path=/red/{segment},/blue/{segment}

Query Route Predicate

YML

代码语言:javascript复制
- Query=username, d  #要有参数名称并且是正整数才能路由

测试: http://localhost:9527/payment/lb?username=1

小总结

All

说白了,Predicate就是为了实现一组匹配规则, 让请求过来找到对应的Route进行处理

⑦ Filter 的使用

1.是什么
2.Spring Cloud Gateway 的 Filter
  • 生命周期, Only Two
    • Pre : 在业务逻辑之前
    • Post: 在业务逻辑之后
  • 种类: Only Two
    • GatewayFilter: 单一
    • GlobalFilter: 全局
3.常用的 GatewayFilter

AddRequestParameter

YML

4.自定义过滤器

自定义全局 GlobalFilter

  1. 两个主要接口介绍
代码语言:javascript复制
impiemerts GlobalFilter , Ordered
  1. 能干嘛
  • 全局日志记录
  • 统一网关鉴权
  • ……
  1. 案例代码
代码语言:javascript复制
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("*********come in MyLogGateWayFilter: " new Date());
        String username = exchange.getRequest().getQueryParams().getFirst("username");
        if(username == null){
            log.info("*****用户名为 NUll 非法用户.(┬_┬)");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);// 给人家一个回应
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

测试

启动

  • 正确: http://localhost:9527/payment/lb?username=1
  • 错误 : http://localhost:9527/payment/lb?usernameaa=1

0 人点赞