分布式微服务 - 3.服务网关 - 4.Gateway

分布式微服务 - 3.服务网关 - 4.Gateway

项目示例:

  • 项目示例 - 3.服务网关 - 3.Gateway

内容提要:

  • 基本使用:配置方式、代码方式
  • 内置断言、自定义断言
  • 内置局部过滤器、自定义内置和全局过滤器

文档:

基本使用

配置方式

  1. 引入依赖:使用gateway依赖时,不能同时引入spring-boot-starter-web依赖。gateway配合nacos使用别名进行路由,需要使用负载均衡(而nacos依赖不包含),因此要单独引入loadbalancer依赖
xml 复制代码
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
  1. application.yml配置
yml 复制代码
spring:
  cloud:
    gateway:
      discovery:
        locator:
          # 从服务注册中心根据别名来进行路由
          enabled: true
      routes:
        # 路由Id,自定义,唯一即可
        - id: nacos-provider-test
          # 成功匹配后,要转换成的路由地址(配合服务注册中心使用别名),需要负载均衡依赖
          uri: lb://nacos-provider
          # 成功匹配后,要转换成的路由地址(不配合服务注册中心)
          #uri: http://localhost:8001
          # 断言
          predicates:
            # 路径匹配的进行路由
            - Path=/**

代码方式

java 复制代码
@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator myRouteLocator(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route("nacos-provider-test", r -> r.path("/**").uri("lb://nacos-provider"));
        return routes.build();
    }

}

路由配置

路由是由ID、URI、一系列的断言和过滤器组成的。断言可以匹配请求中的所有内容,如果请求与断言相匹配则进行路由。URI是进行路由时,要转换成的路由地址。在满足断言之后,过滤器可以修改向URI发送的请求和返回的响应。

断言

gateway本身内置许多断言(RoutePredicateFactory接口的实现类),多个断言可以组合使用。

当一个请求可以满足多个路由的断言时,会按定义的顺序找第一个满足断言的路由。

内置断言

内置断言中用到的时间格式可以用代码ZonedDateTime.now() 获取,也可以指定时间区域ZonedDateTime.now(ZoneId.of("Asia/Shanghai"))

常用内置断言

  • Path
    • 请求满足路径正则表达式则匹配
    • 如:Path=/product-serv/segment,/server-b/**
  • Method
    • 请求满足指定请求方式则匹配
    • 如:Method=GET,POST
  • Cookie
    • 请求cookie中存在指定key且value满足正则表达式则匹配
    • 如:Cookie=key, valueReg
  • Header
    • 请求头中存在指定key且value满足正则表达式则匹配
    • 如:Header=X-Request-Id, \d+
  • Query
    • 请求带有指定参数且value满足正则表达式则匹配
    • 如:Query=name, fly
  • RemoteAddr
    • 请求的ip在指定ip/mask内则匹配
    • 如:RemoteAddr=192.168.1.0/24
  • Host
    • 请求的host满足正则表达式则匹配
    • 如:Host=localhost:8080,localhost:8081
  • After
    • 请求时间在指定时间之后则匹配,可用于在未来指定时间上线服务
    • 如:After=2024-01-01T23:59:59.123+08:00[Asia/Shanghai]
  • Before
    • 请求时间在指定时间之前则匹配,可用于服务在指定时间内可访问
    • 如:Before=2024-01-01T23:59:59.123+08:00[Asia/Shanghai]
  • Between
    • 请求时间在指定时间之间则匹配,可用于服务在指定时间内可访问
    • 如:Between=2024-01-01T23:59:59.123+08:00[Asia/Shanghai], 2024-01-02T23:59:59.123+08:00[Asia/Shanghai]
自定义断言
  1. 创建类并@Component注入:类名要求是XxxRoutePredicateFactory(配置文件中使用断言时,断言名为Xxx)
java 复制代码
@Component
public class CustomRoutePredicateFactory
  1. 创建静态内部类:用于接收参数,因此要有属性值和对应的getter和setter
java 复制代码
    @Getter
    @Setter
    public static class Config {
        private String key;
        private String value;
    }
  1. 继承抽象类:继承断言工厂类AbstractRoutePredicateFactory并确定泛型为内部类
java 复制代码
@Component
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomRoutePredicateFactory.Config>
  1. 构造方法
java 复制代码
    public CustomRoutePredicateFactory() {
        super(Config.class);
    }
  1. 重写读配置文件方法:方法读取配置文件的参数值,赋值到内部类中的属性上(顺序必须与yml文件中的配置顺序对应)
java 复制代码
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("key", "value");
    }
  1. 重写apply方法:返回true路由成功,返回false返回404(serverWebExchange可以获取很多内容)
java 复制代码
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return new Predicate<ServerWebExchange>() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                List<String> strings = serverWebExchange.getRequest().getHeaders().get(config.key);
                if (strings==null || strings.isEmpty())
                    return false;
                return config.value.equals(strings.get(0));
            }
        };
    }
  1. yml文件中配置断言
yml 复制代码
Custom=test, a

过滤器

过滤器分为局部过滤器和全局过滤器,局部过滤器仅在配置的路由上起效,而全局过滤器对所有的路由都起效。

内置局部过滤器

常用内置过滤器

  • StripPrefix

    • 转换成路由之前,去掉URL中前面几节
    • 如:StripPrefix=1
  • PrefixPath

    • 给请求路径path添加前缀
    • 如:PrefixPath=/nacos
  • AddRequestParameter

    • 添加请求参数
    • 如:AddRequestParameter=name,test
  • RemoveRequestParameter

    • 删除请求参数
    • 如:RemoveRequestParameter=name
  • AddRequestHeader

    • 在请求头上添加参数
    • 如:AddRequestHeader=key,value
  • SetRequestHeader

    • 修改请求头上指定参数的值,参数不存在时创建
    • 如:SetRequestHeader=myHeader, test
  • RemoveRequestHeader

    • 删除请求头上的指定参数
    • 如:RemoveRequestHeader=MyHeader
  • AddResponseHeader

    • 在响应头上添加参数
    • 如:AddRequestHeader=key,value
  • SetResponseHeader

    • 修改响应头上指定参数的值,参数不存在时创建
    • 如:SetResponseHeader=addHeader, test
  • RewriteResponseHeader

    • 修改响应头上指定参数的值,第一个参数是key,第二个参数是正则表达式匹配修改前的值,第三个参数是修改后的值
    • 如:RewriteResponseHeader=addHeader,test1,test
  • RemoveResponseHeader

    • 删除响应头上的指定参数
    • 如:RemoveResponseHeader=addHeader
  • SetStatus

    • 设置返回的响应码
    • 如:SetStatus=500
  • RedirectTo

    • 重定向,两个参数分别是重定向300系列状态码和URL
    • 如:RedirectTo=302, https://www.baidu.com
  • RewritePath

    • 重写请求路径
    • 如:RewritePath=/test1/?(?.*), /nacos/${segment}
自定义局部过滤器
  1. 创建类并@Component注入:类名要求是XxxGatewayFilterFactory(配置文件中使用过滤器时,过滤器名为Xxx)
java 复制代码
@Component
public class CustomGatewayFilterFactory
  1. 创建静态内部类:用于接收参数,因此要有属性值和对应的getter和setter
java 复制代码
    @Getter
    @Setter
    public static class Config {
        private String key;
        private String value;
    }
  1. 继承抽象类:继承过滤器工厂类AbstractGatewayFilterFactory并确定泛型为内部类
java 复制代码
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config>
  1. 构造方法
java 复制代码
    public CustomRoutePredicateFactory() {
        super(Config.class);
    }
  1. 重写读配置文件方法:方法读取配置文件的参数值,赋值到内部类中的属性上(顺序必须与yml文件中的配置顺序对应)
java 复制代码
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("key", "value");
    }
  1. 重写apply方法:可以在chain.filter(exchange).then之前操作request,之后操作response(serverWebExchange可以获取很多内容)
java 复制代码
    @Override
    public GatewayFilter apply(Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                // pre操作
                return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                    // 异步post操作
                }));
            }
        };
    }
  1. yml文件中配置断言
yml 复制代码
Custom=test, a
自定义全局过滤器
  1. 创建GlobalFilter、Ordered接口实现类并@Component注入
java 复制代码
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered
  1. 重写getOrder方法:方法返回的值越小,过滤器的优先级越高
java 复制代码
    @Override
    public int getOrder() {
        return 0;
    }
  1. 重写filter方法
java 复制代码
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // pre操作
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 异步post操作
        }));
    }
相关推荐
荆州克莱10 分钟前
mysql中局部变量_MySQL中变量的总结
spring boot·spring·spring cloud·css3·技术
zquwei24 分钟前
SpringCloudGateway+Nacos注册与转发Netty+WebSocket
java·网络·分布式·后端·websocket·网络协议·spring
dessler1 小时前
Docker-run命令详细讲解
linux·运维·后端·docker
Q_19284999061 小时前
基于Spring Boot的九州美食城商户一体化系统
java·spring boot·后端
ZSYP-S2 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
Yuan_o_2 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
程序员一诺3 小时前
【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】
后端·python
DT辰白3 小时前
如何解决基于 Redis 的网关鉴权导致的 RESTful API 拦截问题?
后端·微服务·架构
thatway19894 小时前
AI-SoC入门:15NPU介绍
后端