0
点赞
收藏
分享

微信扫一扫

Gateway的基本使用

自由的美人鱼 2022-04-17 阅读 50
gateway

搭建基本框架

项目结构

image-20220412085504882

创建父项目

作用

创建一个父项目(Maven项目,可以把src文件夹删除掉),其作用是用于管理依赖的版本号以及子项目模块

创建过程

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ledao</groupId>
    <artifactId>GatewayDemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>order</module>
        <module>stock</module>
        <module>gateway</module>
        <module>common</module>
    </modules>
    <packaging>pom</packaging>

    <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>Hoxton.SR9</spring-cloud.version>
        <springboot.version>2.3.2.RELEASE</springboot.version>
        <springcloudalibaba.version>2.2.6.RELEASE</springcloudalibaba.version>
        <common.version>1.0-SNAPSHOT</common.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>
            <dependency>
                <groupId>com.ledao</groupId>
                <artifactId>common</artifactId>
                <version>${common.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

创建公共项目

作用

创建一个公共项目(Maven项目),用于管理公共依赖、工具类以及实体类等

创建过程

<?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>GatewayDemo</artifactId>
        <groupId>com.ledao</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>common</artifactId>

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

创建订单项目

作用

创建一个订单项目模块,模拟真实业务,用于测试

创建过程

<?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>GatewayDemo</artifactId>
        <groupId>com.ledao</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.ledao</groupId>
            <artifactId>common</artifactId>
        </dependency>
    </dependencies>
</project>
server:
  port: 8081
  servlet:
    context-path: /
  tomcat:
    uri-encoding: utf-8

spring:
  application:
    name: order
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
package com.ledao;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author LeDao
 * @company
 * @create 2022-04-11 23:19
 */
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}
package com.ledao.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author LeDao
 * @company
 * @create 2022-04-11 23:17
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @RequestMapping("/test")
    public Map<String, Object> test() {
        Map<String, Object> resultMap = new HashMap<>(16);
        resultMap.put("模块名称", "订单模块");
        resultMap.put("请求时间", new Date());
        return resultMap;
    }
}

创建库存项目

作用

创建一个库存项目模块,模拟真实业务,用于测试

创建过程

<?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>GatewayDemo</artifactId>
        <groupId>com.ledao</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>stock</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.ledao</groupId>
            <artifactId>common</artifactId>
        </dependency>
    </dependencies>
</project>
server:
  port: 8082
  servlet:
    context-path: /
  tomcat:
    uri-encoding: utf-8

spring:
  application:
    name: stock
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
package com.ledao;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author LeDao
 * @company
 * @create 2022-04-11 23:22
 */
@SpringBootApplication
public class StockApplication {

    public static void main(String[] args) {
        SpringApplication.run(StockApplication.class, args);
    }
}
package com.ledao.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author LeDao
 * @company
 * @create 2022-04-11 23:23
 */
@RestController
@RequestMapping("/stock")
public class StockController {

    @RequestMapping("/test")
    public Map<String, Object> test() {
        Map<String, Object> resultMap = new HashMap<>(16);
        resultMap.put("模块名称", "库存模块");
        resultMap.put("请求时间", new Date());
        return resultMap;
    }
}

测试

启动订单项目和库存项目

通过http://localhost:8081/order/test访问,返回:

{"模块名称":"订单模块","请求时间":"2022-04-14 11:25:51"}

通过http://localhost:8082/stock/test访问,返回:

{"模块名称":"库存模块","请求时间":"2022-04-14 11:25:49"}

出现上面结果说明搭建成功

开始使用Gateway

实现访问其它项目接口

<?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>GatewayDemo</artifactId>
        <groupId>com.ledao</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>
</project>

id:路由id,设置为被访问项目的名称

uri:路由地址,设置为被访问项目的端口

predicates:断言规则,设置为被访问项目的请求路径

server:
  port: 8080
  servlet:
    context-path: /
  tomcat:
    uri-encoding: utf-8

spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**

        - id: stock
          uri: http://localhost:8082/
          predicates:
            - Path=/stock/**
package com.ledao;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author LeDao
 * @company
 * @create 2022-04-11 23:35
 */
@SpringBootApplication
public class GatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

启动Gateway网关项目

通过http://localhost:8080/order/test访问,返回:

{"模块名称":"订单模块","请求时间":"2022-04-14 11:25:51"}

通过http://localhost:8080/stock/test访问,返回:

{"模块名称":"库存模块","请求时间":"2022-04-14 11:25:49"}

出现上面结果说明已经成功,其中8080为Gateway网关项目的端口

路由匹配规则

spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
            - After=2022-04-14T13:12:12+08:00[Asia/Shanghai]
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
            - Before=2022-04-14T11:12:00+08:00[Asia/Shanghai]
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
            - Between=2022-04-14T13:12:00+08:00[Asia/Shanghai],2022-04-14T14:12:00+08:00[Asia/Shanghai]
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
            - Cookie=token, \d+
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
            - Header=X-Request-Id, \d+
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
            - Host=**.mytest.com,**.mytest2.com
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
            - Method=GET

一些匹配示例说明如下:

  1. /order/**:以/order/开头的请求路径
  2. /order/my/{aa}/order/my/test可以通过,/order/test/order/my/ss/test不可以通过
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
            - Query=name

内置过滤器

AddRequestParameter

spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
          filters:
            - AddRequestParameter=name,ledao

RewritePath

spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/gateway/**
          filters:
            - RewritePath=/gateway(?<segment>/?.*), $\{segment}

SetStatus

spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
          filters:
            - SetStatus=404

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QCa33qN3-1650180001231)(C:\Users\LeDao\AppData\Roaming\Typora\typora-user-images\image-20220417122637663.png)]

AddResponseHeader

spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
          filters:
            - AddResponseHeader=X-Response-Author,LeDao

image-20220417124138292

更多

查看:Spring Cloud Gateway

自定义GatewayFilter

package com.ledao.filter;

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author LeDao
 * @company
 * @create 2022-04-17 13:01
 */
public class MyGatewayFilter implements GatewayFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("我的自定义网关过滤器");
        //获取请求的参数name的值
        System.out.println(exchange.getRequest().getQueryParams().get("name"));
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        //越小优先级越高
        return -1;
    }
}
package com.ledao.config;

import com.ledao.filter.MyGatewayFilter;
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;

/**
 * @author LeDao
 * @company
 * @create 2022-04-17 13:05
 */
@Configuration
public class MyGatewayFilterConfig {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        return builder.routes().route(r -> r
                .path("/order/**")
                .uri("http://localhost:8081/")
                .filter(new MyGatewayFilter())
                .id("myGatewayFilter")
        ).build();
    }
}

自定义GlobalFilter

package com.ledao.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author LeDao
 * @company
 * @create 2022-04-17 13:50
 */
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("我的自定义全局过滤器");
        return chain.filter(exchange);
    }

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

限流

限流算法

Gateway默认给我们实现了限流实现,也就是网关拦截器RequestRateLimiter,RequestRateLimiter的底层实现是令牌桶限流算法,需要引入Redis

image-20220417145409837

URL限流

<!-- 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>
package com.ledao.config;

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;

/**
 * @author LeDao
 * @company
 * @create 2022-04-17 14:36
 */
@Configuration
public class KeyResolverConfig {

    @Bean
    public KeyResolver pathKeyResolver() {
        /*return new KeyResolver() {
            @Override
            public Mono<String> resolve(ServerWebExchange exchange) {
                return Mono.just(exchange.getRequest().getURI().getPath());
            }
        };*/
        //URL限流,上面注释代码的lambda写法
        return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
    }
}
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充速率
                redis-rate-limiter.burstCapacity: 2 #令牌桶总容量
                redis-rate-limiter.requestedTokens: 1 # 每次请求消耗1个
                key-resolver: "#{@pathKeyResolver}"

参数限流

package com.ledao.config;

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;

import java.util.Objects;

/**
 * @author LeDao
 * @company
 * @create 2022-04-17 14:36
 */
@Configuration
public class KeyResolverConfig {

    /**
     * 参数限流
     *
     * @return
     */
    @Bean
    public KeyResolver parameterKeyResolver() {
        return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getQueryParams().getFirst("token")));
    }
}
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充速率
                redis-rate-limiter.burstCapacity: 2 #令牌桶总容量
                redis-rate-limiter.requestedTokens: 1 # 每次请求消耗1个
                key-resolver: "#{@parameterKeyResolver}"

IP限流

package com.ledao.config;

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;

import java.util.Objects;

/**
 * @author LeDao
 * @company
 * @create 2022-04-17 14:36
 */
@Configuration
public class KeyResolverConfig {

    /**
     * IP限流
     *
     * @return
     */
    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getHostName());
    }
}
spring:
  application:
    name: gateway
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  cloud:
    gateway:
      routes:
        - id: order
          uri: http://localhost:8081/
          predicates:
            - Path=/order/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充速率
                redis-rate-limiter.burstCapacity: 2 #令牌桶总容量
                redis-rate-limiter.requestedTokens: 1 # 每次请求消耗1个
                key-resolver: "#{@ipKeyResolver}"

PS.

官方文档地址:[Spring Cloud Gateway](

举报

相关推荐

0 条评论