首页 > 其他分享 >SpringCloud GateWay网关(入门)

SpringCloud GateWay网关(入门)

时间:2023-01-17 21:33:36浏览次数:79  
标签:网关 断言 SpringCloud Gateway GateWay cloud id payment 路由

1、介绍

强烈推荐,看官网文档

Spring Cloud Gateway

①简介

Cloud全家桶里有个重要组件:网关

SpringCloud Gateway基于WebFlux框架

WebFlux底层使用高性能的Reactor模式(异步非阻塞)通信框架Netty

image-20230116230015522

②选择原因

  • 1.x版本采用Zuul网关

    但是在2.x版本中,zuul升级经常跳票,所以SpringCloud研发了SpringCloud Gateway代替1.x版本

    SpringCloud Gateway作为SpringCloud生态的网关,目标是替代Zuul,在SpringCloud2.0以上,没有对Zuul2.0以上进行集成,仍然使用Zuul1.x非Reactor模式的老版本。

  • SpringCloud Gateway属于Spring家族,整合更方便

  • 动态路由:能够匹配任何请求属性

  • 可以对路由指定Predicate(断言)和Filter(过滤器)

  • Zuul1.基于Servlet2.5使用阻塞架构,不支持任何长连接。Zuul2,SpringCloud没有整合。SpringCloud Gateway吸收Zuul2特点,使用非阻塞架构,支持长连接

③Zuul与Spring Cloud Gateway模型

一.Zuul模型(阻塞式)

使用Servlet2.5

image-20230116230735827

当请求进入Container,会为其绑定一个线程,在并发不高的情况下模型还Ok。但是高并发情况下,线程数会飙升,而线程的资源代价很高贵(线程的上下文切换,内存消耗很大...)严重影响请求处理时间。

二.SpringCloud Gateway模型

在Servlet3.1之后有了异步非阻塞的支持

2、 三大概念

image-20230116235343703

①路由

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

②断言

参考Predicate

开发人员通过匹配HTTP请求中的内容(如请求头,请求参数),如果请求和断言匹配,进行路由

③过滤

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

3、SpringCloud Gateway工作流程

在这里插入图片描述

客户端向SpringCloud Gateway发请求,然后Gateway Handler Mapping中找到匹配的路由,将其发送到Gateway Web Handler中。

Handler再通过指定的过滤器链来将请求发送到我们的实际服务执行业务逻辑,然后返回。

过滤器之间用虚线分开,是因为过滤器可能会在发送请求之前(pre)和之后(post)执行逻辑

4、搭建

1.新建模块cloud-gateway-gateway9527

image-20230117001146236

2.pom.xml:

<dependencies>
    <!--gateway-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!-- 引用自己定义的api通用包,可以使用Payment支付Entity -->
    <dependency>
        <groupId>cn.zko0.cloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <!--eureka client(通过微服务名实现动态路由)-->
    <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>

3.yml:

将GetWay注册到Eureka上:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      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:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

4.启动类:

@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {
    public static void main(String[] args) {
        SpringApplication.run(GatewayMain9527.class, args);
    }
}

5.启动7001(注册中心),8001(Provider)与9527(Gatway)三个工程

image-20230117002123653

image-20230117002219961

6.服务调用测试:

8001调用测试:

image-20230117002305169

9527调用测试:

image-20230117002327721

5、两种配置方式

①配置文件

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          uri: http://localhost:8001
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由

        - id: payment_route2
          uri: http://localhost:8001
          predicates:
            - Path=/payment/lb/** #断言,路径相匹配的进行路由

②代码注入RouteLocator的Bean

自拟一个需求:

通过Gateway路由到百度贴吧:

这里路由到百度知道存在错误,目前还没有找到原因,由于Gateway一般用于内网的转发,所以没有细究,主要学习Gateway的配置方式

@Configuration
public class GatwayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        /*routes.route("path_route_angenin",  //id
                r -> r.path("/zhidao")  //访问 http://localhost:9527/zhidao
                        .uri("https://zhidao.baidu.com/"));  //就会转发到*/

        routes.route("path_route_angenin2",  //id
                r -> r.path("/tieba")  //访问 http://localhost:9527/tieba
                        .uri("https://tieba.baidu.com/index.html"));  //就会转发到
        return routes.build();
    }
}

6、动态路由

①产生原因

在前面我们的配置都是写死了uri

8001和8002都是payment,如果后面我们对paymen服务进行扩容,出现了8003,8004等,那么这种方式就没有办法进行动态的调整了

image-20230117133802338

②配置

通过微服务名实现动态路由

  1. 开启从注册中心动态创建路由的功能,利用微服务名称进行路由(默认false)

  2. 把写死的uri替换为服务名

    lb:是指路由的一种通信协议,它实现了负载均衡通信功能

总配置文件:

image-20230117140746031

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名称进行路由(默认false)
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由

#        - id: payment_route2
#          uri: lb://cloud-payment-service
#          predicates:
#            - Path=/payment/xxxx #断言,路径相匹配的进行路由

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

启动测试:

启动eureka注册中心,payment8001和8002,9827gateway

image-20230117140924968

接口调用测试:成功

image-20230117141506971

7、路由断言

之前我们的断言仅仅使用了uri的匹配

Springcloud Gateway还提供了很多其他断言判断条件:

SpringCloud断言文档

①The After Route Predicate Factory

时间级别还有:

  • The Before Route Predicate Factory
  • The Between Route Predicate Factory

配置:

测试类,获取当前的时间:

public class Test {
    public static void main(String[] args) {
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println(now);
    }
}

image-20230117142728272

通过上图我们能获得当前的时间

设置after断言判断,让当前时间在设置事件后,该路由才能生效

image-20230117142954121

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名称进行路由(默认false)
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由
            - After=2023-01-17T15:23:19.987+08:00[Asia/Shanghai]

重启测试:

由于时间未到after之后,所以路由未生效

image-20230117143228735

下面的介绍来自官网,看官网就OK了

cookie 路由断言工厂采用两个参数,即 cookie 名称和正则表达式。 此谓词匹配具有给定名称且其值与正则表达式匹配的 Cookie。 以下示例配置 cookie 路由断言工厂:

image-20230117143634315

配置:

image-20230117143844472

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名称进行路由(默认false)
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由
            #- After=2023-01-17T15:23:19.987+08:00[Asia/Shanghai]
            - Cookie=username,fuckU

重启测试:

带Cookie调用,成功:

image-20230117144234179

不带Cookie调用,或者Cookie错误,失败:

image-20230117144301806

③The Header Route Predicate Factory

标头路由断言工厂采用两个参数,即标头名称和正则表达式。 此断言与具有给定名称的标头匹配,该标头的值与正则表达式匹配。 以下示例配置标头路由断言:

image-20230117193711995

配置测试:

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名称进行路由(默认false)
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由
            - Header=X-Request-Id, \d+
            #- After=2023-01-17T15:23:19.987+08:00[Asia/Shanghai]
            #- Cookie=username,fuckU

测试:

当Header中X-Request-Id的value为正整数,路由才能生效

image-20230117194732434

④还有很多:略

参考Spring官网提供的文档即可:

SpringCloud断言文档

8、Gateway Filter

路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由过滤器只能指定路由使用

①生命周期

  1. pre(前
  2. post(后

②种类

一.单一的Gateway Filter

用的比较少,略

二.全局过滤器

自定义全局GlobalFilter

新建config包,自定义全局过滤器:该过滤器能够通过检验请求参数是否包含username,来设置是否过滤请求:

@Slf4j
@Component
public class MyLogGateWayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("**************come in MyLogGatewayFilter{}",new Date());
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if (uname==null){
            log.info("*****用户名为null,非法");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    //数字越小Filter的优先级越高
    public int getOrder() {
        return 0;
    }
}

重启,测试:

请求附带参数,uname=1,成功

image-20230117205722794

请求不附带参数,失败:

image-20230117205753827

标签:网关,断言,SpringCloud,Gateway,GateWay,cloud,id,payment,路由
From: https://www.cnblogs.com/zko0/p/17058723.html

相关文章

  • Kong网关安装自定义插件
    安装自定义插件需要注意kong网关的版本要求!! 下面以安装Skywalking插件为例,要求Kong网关是2.2及以上版本,https://github.com/apache/skywalking-kong一、下载Skywalking......
  • Spring Cloud——微服务网关介绍
    API网关的作用如果服务将所有API接口对外直接暴露给用户端,用户可能越权访问不属于它应该访问的功能(如管理员的高级功能)。后台服务可能采用不同的通信方式,如服务A采......
  • API 网关的功能用途及实现方式
    1.API网关诞生背景前言API经济生态链已经在全球范围覆盖,绝大多数企业都已经走在数字化转型的道路上,API成为企业连接业务的核心载体,并产生巨大的盈利空间。快速增长......
  • API 网关的功能用途及实现方式
    1.API网关诞生背景前言API经济生态链已经在全球范围覆盖,绝大多数企业都已经走在数字化转型的道路上,API成为企业连接业务的核心载体,并产生巨大的盈利空间。快速增长......
  • SpringCloud学习(1)
    今天学习谷粒商城的openfeign远程调用的时候,启动项目后报错nestedexceptionisjava.lang.IllegalStateException:NoFeignClientforloadBalancingdefined.Didyou......
  • 分布式请求链路跟踪(SpringCloud Sleuth + zipkin)
    前言在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果,每一个前段请求都会形成一条复杂的分布式服务调用链路,链路......
  • 处理分布式事务(SpringCloud Alibaba Seata)
    前言一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的......
  • Gateway开发教程之配置uri的三种方式
    Gateway路由一共有三种uri的配置方式,下面我们会逐一介绍一下。http方式http方式,自然指的是可以转发任意http链接,比如可以配置以下这样:routes:-id:demo_router#......
  • Gateway过滤器工厂
    Gateway过滤器工厂文章目录​​Gateway过滤器工厂​​​​概述​​​​GatewayFilters​​​​1.AddRequestHeader​​​​2.AddRequestParameter​​​​3.AddResponse......
  • 如何通过物联网网关感知工业设备故障,优化设备维护体验?
    传统的工业生产中,设备维护一直存在效率低下的问题。传感的设备管理模式无法实时感知设备运行状态,往往在设备故障停机之后才联系工程师进行维护,严重影响生产效益和订单交付;对......