Spring cloud Gateway网关简介及使用

Spring cloud Gateway网关简介及使用

1、API网关

介绍:

网关的角色是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。
API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制
和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。因此,隐藏在
API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。

在这里插入图片描述
作用:
在这里插入图片描述
在这里插入图片描述

2、Gateway

官方介绍https://spring.io/projects/spring-cloud-gateway
官方文档https://docs.spring.io/spring-cloud-gateway/docs/2.2.7.RELEASE/reference/html/
gateway特性

1、基于SpringFramework5,ProjectReactor和SpringBoot2.0进行构建
2、能够匹配任何任何请求属性
3、可以对路由指定Predicates和Filters
4、集成断路器
5、集成Spring Cloud服务发现
6、易于编写的Predicates和Filters
7、支持请求限流
8、支持路径重写

工作方式:
在这里插入图片描述

客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到
网关Web处理程序。该处理程序通过特定于请求的过滤器链来运行请求。筛选器由虚线分隔的原因是,
筛选器可以在发送代理请求之前和之后都运行逻辑。所有“前置”过滤器逻辑均被执行。然后发出代理请 求。发出代理请求后,将运行“后”过滤器逻辑。

三个概念:

路由:路由是构建网关的基本模块,它由ID,目标URI,一系列的断言Predicates和过滤器Filters组成,
如果断言为true,则匹配该路由。
断言:参考Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容,例如请求
头或请求参数,如果请求与断言相匹配则进行路由。
过滤:Spring框架中GatewayFilter的实例,使用过滤器,可以载请求被路由前或者后对请求进行修改。

路由断言工厂

Spring Cloud Gateway将路由作为Spring WebFlux HandlerMapping 基础架构的一部分进行匹
配。Spring Cloud Gateway包括许多内置的路由断言工厂。所有这些断言都与HTTP请求的不同属性匹
配。您可以将多个路由断言工厂与逻辑 and 语句结合使用。
路由断言工厂RoutePredicateFactory包含的主要实现类如图所示,包含Datetime、Cookie、
Header、Host、Method、Path、Query、RemoteAddr、Weight等类型的路由断言。

在这里插入图片描述
Gateway过滤器工厂介绍

过滤器 有 20 多个 实现 类, 包括 头部 过滤器、 路径 类 过滤器、 Hystrix 过滤器 和 变更 请求 URL 的 过滤器,
还有 参数 和 状态 码 等 其他 类型 的 过滤器。 内置的过滤器工厂有22个实现类,包括 头部过滤器、路径过滤器、Hystrix 过滤器
、请求URL 变更过滤 器,还有参数和状态码等其他类型的过滤器。根据过滤器工厂的用途来划分,可以分为以下几种:
Header、Parameter、Path、Body、Status、Session、Redirect、Retry、RateLimiter和Hystrix

在这里插入图片描述
gateway全局过滤器 GlobalFilter

全局过滤器不需要在配置文件中配置,作用在所有的路由上。我们可以用它来实现很多统一化处理的业
务需求,比如负载均衡,统一过滤,路径转发,监控,日志等等。
全局过滤器加上网关过滤器组成过滤器链,该过滤器链的执行顺序是根据@Order注解指定的数字大 小,从小到大进行排序,数字越小,优先级越高。

在这里插入图片描述
自定义过滤器

Spring Cloud Gateway提供了过滤器的扩展功能,开发者可以根据实际业务需求来自定义
GatewayFilter网关过滤器或者GlobalFilter全局过滤器。

令牌桶算法

RequestRateLimiter底层实现是令牌桶算法; 令牌桶内存储令牌,令牌桶需要设置令牌容量,也就是系统最大的并发大;
以一定的速率生成令牌(具体速率根据系统性能设置),放到令牌桶,如果桶慢了,则丢弃;
客户端来一个请求,则先去令牌桶获取令牌,拿到令牌,则处理请求,否则 丢弃或者返回失败;

令牌桶算法的优点:

通过恒定的速率生成令牌桶,能够让请求处理更均匀,不会出现短时间大量的请求处理; 比较友好的控制高并发;

在这里插入图片描述

gateway快速入门

1、创建一个父级maven空项目gatewaydemo并导入依赖:

 <modules>
        <module>product-demo</module>
        <module>order-demo</module>
        <module>gateway-server</module>
    </modules>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring-cloud.version>2020.0.4</spring-cloud.version>
        <springboot.version>2.5.5</springboot.version>
        <springcloudalibaba.version>2.2.5.RELEASE</springcloudalibaba.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${springcloudalibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2、创建新模块子级maven空项目product-demo(商品)、order-demo(订单)并导入依赖:

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

product-demo/order-demo的application.yml配置文件:

server:
  port: 8080
  servlet:
    context-path: /
spring:
  application:
    name: product-demo/order-demo

product-demo:实体层Product类

public class Product {
    private Integer id;
    private String name;
    private Integer number;
    private Double price;
    }
 public Product(Integer id, String name, Integer number, Double price) {
        this.id = id;
        this.name = name;
        this.number = number;
        this.price = price;
    }

product-demo:controller层ProductController 类

@RestController
@RequestMapping("/product")
public class ProductController {
    @GetMapping("/{id}")
    public Product detail(@PathVariable("id")Integer id){
        System.out.println(1);
        return new Product(id,"xxx商品"+id,2,100.00);
    }
}

order-demo:实体层order类

public class Order{
    private Integer id;
    private String orderNo;
    private Double totalPrice;
    private String userInfo;
    private String productInfo;
    public Order(Integer id, String orderNo, Double totalPrice, String userInfo, String productInfo) {
        this.id = id;
        this.orderNo = orderNo;
        this.totalPrice = totalPrice;
        this.userInfo = userInfo;
        this.productInfo = productInfo;
    }
    }

order-demo:controller层OrderController 类

@RestController
@RequestMapping("/order")
public class OrderController {
    @GetMapping("/{id}")
    public com.bdqn.pojo.Order detail(@PathVariable("id")Integer id,String info){
        System.out.println(info);
        return new Order(id,"1212",21.12,"用户信息"+id,"商品信息"+id);
    }
}

3、创建新模块子级maven空项目gateway-server并导入依赖:

 <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- spring boot redis 缓存引入 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- lettuce pool 缓存连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
    </dependencies>

配置application.yml:

server:
  port: 80
  servlet:
    context-path: /
spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes: # 路由规则定义
      - id: product-service # 路由ID
        uri: http://localhost:8080/ # 路由地址
        predicates: # 断言规则
        - Path=/product/**
      - id: order-service # 路由ID
        uri: http://localhost:8081/ # 路由地址
        predicates: # 断言规则
        - Path=/order/**    

匹配指定日期时间之后的请求 After:

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: after_route
          uri: http://localhost:8080/
          predicates:
            - After=2021-04-20T06:06:06+08:00[Asia/Shanghai]

匹配指定日期时间之前的请求 Before

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: before_route
          uri: http://localhost:8080/
          predicates:
            - Before=2021-12-20T06:06:06+08:00[Asia/Shanghai]

匹配指定日期时间之间的请求 Between

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
      - id: betwwen_route
        uri: http://localhost:8080/
        predicates:
        - Between=2021-01-20T06:06:06+08:00[Asia/Shanghai],2021-04-
  20T06:06:06+08:00[Asia/Shanghai]

Cookie路由匹配规则

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: cookie_route
          uri: http://localhost:8080/
          predicates:
          - Cookie=token, \d+

Host路由匹配规则

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: host_route
          uri: http://localhost:8080/
          predicates:
  - Host=**.somehost.org,**.anotherhost.org

Header路由匹配规则

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: header_route
          uri: http://localhost:8080/
          predicates:
          - Header=X-Request-Id, \d+

Method路由匹配规则

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: method_route
          uri: http://localhost:8080/
          predicates:
          - Method=GET,POST

Path路由匹配规则

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://localhost:8080/
          predicates:
          - Path=/product/{segment}

Query路由匹配规则

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
       - id: query_route
        uri: http://localhost:8080/
        predicates:
        - Query=green

Gateway过滤器

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: add_request_parameter_route
          uri: http://localhost:8080/
          predicates:
          - Path=/product/** ,  /api-gateway/**
          filters:
          - AddRequestParameter=info, hehe  #添加请求参数(属于前置过滤网关)
          - RewritePath=/api-gateway(?<segment>/?.*), $\{segment} #将/api-gateway/product/请求重写成/product/请求(属于前置过滤网关)
          - SetStatus=456 #无论哪种情况,响应的HTTP状态都设置为456(属于后置过滤网关)
          - AddResponseHeader=X-Response-Author, java1234 #返回信息,添加header头信息(属于后置过滤网关)

4、编写代码:
gateway-server:config层:KeyResolverConfiguration

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
@Configuration
public class KeyResolverConfiguration {
    @Bean
    public KeyResolver ipKeyResolver(){
// return exchange -> Mono.just(exchange.getRequest().getURI().getPath());//URI限流
//Mono.just(exchange.getRequest().getQueryParams().getFirst("token")); // 参数限流
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());//IP限流
    }
}

filter层MyCustomerGatewayFilter 类

public class MyCustomerGatewayFilter implements GatewayFilter, Ordered {
    @Override
    public int getOrder() {
        return -1;
    }
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("自定义网关过滤器");
        return chain.filter(exchange);
    }
}

filter层:MyCustomerGlobalFilter 类

public class MyCustomerGlobalFilter  implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain
            chain) {
        System.out.println("自定义全局过滤器");
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        return -2;
    }
}

5、运行结果:(redis可视化工具中也有记录报错)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值