微服务统一入口——Gateway

目录

一、网关的概念

[二、Spring Cloud 中的网关](#二、Spring Cloud 中的网关)

[1. Zuul(已逐渐被替代)](#1. Zuul(已逐渐被替代))

[2. Spring Cloud Gateway(推荐使用)](#2. Spring Cloud Gateway(推荐使用))

三、快速上手

1.创建网关服务启动类

2.引入依赖

3.添加配置

4.测试

四、路由断言工厂

1.核心原理

2.内置网关过滤工厂

3.自定义路由断言工厂

五、网关过滤工厂

1.GatewayFilter

2.GlobalFilter

[3.Default Filters](#3.Default Filters)

4.自定义网关过滤工厂

六、过滤器的执行顺序


在之前的朱皮皮呀-CSDN博客中,我们通过Eureka,Nacos解决了服务注册,服务发现的问题,使用Spring Cloud LoadBalance解决了负载均衡的问题,使用OpenFeign解决了远程调用的问题,接下来则是使用Gateway解决API网关问题。

一、网关的概念

网关是位于客户端与后端服务之间,充当 "入口" 角色。它统一接收客户端请求,再根据配置的规则将请求转发到对应的后端服务,同时提供路由、过滤、安全等附加功能。

例子:外部人员去一家公司办理业务,这个公司里分为多个部门,每个部门办理业务之前都要进行身份校验,重复校验降低了班是效率,因此该公司成立一个前台来统一进行身份校验,校验成功后其他部门就无需校验了,这个"前台"就类似于"API网关"

网关的核心功能

权限控制:微服务的入口,对用户进行权限校验,如果校验失败则进行拦截。

路由转发:将请求按照规则转发到目标微服务。

负载均衡:将请求分配给不同的服务实例,提高可用性。

安全防护:防止恶意攻击、限制请求频率、过滤无效请求,有限流的功能。

日志与监控:记录请求日志,便于追踪和问题排查。

协议适配:支持 HTTP、WebSocket 等多种协议转发。

二、Spring Cloud 中的网关

1. Zuul(已逐渐被替代)

Zuul 是 Netflix 开源的网关组件,早期在 Spring Cloud 中广泛使用,基于 Servlet 技术栈实现。

特点:

基于同步阻塞 IO 模型(Servlet 2.5),性能较低。

集成 Spring Cloud 生态(如与 Eureka、Ribbon 配合实现服务发现和负载均衡)。

支持过滤器机制,可自定义请求处理逻辑。

缺点:

阻塞 IO 导致高并发场景下性能瓶颈明显。

扩展性较差,过滤器链执行效率低。

目前 Zuul 1.x 已停止更新,Zuul 2.x 虽改为非阻塞模型,但与 Spring Cloud 集成不够紧密,应用较少。

2. Spring Cloud Gateway(推荐使用)

Spring Cloud Gateway 是 Spring 官方推出的网关组件,旨在替代 Zuul,基于 Spring 5、Spring Boot 2 和 Project Reactor 开发,采用非阻塞响应式编程模型,性能远优于 Zuul。

核心优势:

非阻塞 IO:基于 Netty 实现,支持高并发,吞吐量是 Zuul 的数倍。

动态路由:支持通过配置中心(如 Nacos、Config)动态修改路由规则,无需重启服务。

强大的断言(Predicate)和过滤器(Filter):可灵活匹配请求、修改请求 / 响应。

原生集成 Spring 生态:无缝对接 Spring Security(认证授权)、Spring Cloud Circuit Breaker(熔断)等。

支持 WebSocket:适合实时通信场景(如聊天、消息推送)

三、快速上手

下面为gateway核心内容,前置代码配置请参考告别 RestTemplate,OpenFeign 才是微服务通信的正确姿势-CSDN博客

1.创建网关服务启动类

java 复制代码
@SpringBootApplication
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class,args);
    }
}

2.引入依赖

XML 复制代码
<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>

3.添加配置

java 复制代码
server:
  port: 10030 #⽹关端⼝
spring:
  application:
    name: gateway #服务名称
  cloud:
    nacos:
      discovery:
        server-addr: 110.41.51.65:10020
    gateway:
      routes: #⽹关路由配置
        - id: product-service       #路由ID,⾃定义,唯⼀即可
          uri: lb://product-service #⽬标服务地址
          predicates: #路由条件
            - Path=/product/**
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/order/**

核心概念

id:自定义路由标识,保持唯一。

uri:目标服务地址,⽀持普通URI 及 lb://应用注册服务名称,lb表示负载均衡,使用 lb:// 方

式表示从注册中心获取服务地址。

predicates:匹配条件,根据匹配结果决定是否执行该请求路由,上述代码中,我们把符合Path规则的⼀切请求,都代理到uri参数指定的地址。

4.测试

启动API网关服务

访问:http://127.0.0.1:10030/product/1001,路由转发到http://product-service/product/1001

访问:http://127.0.0.1:10030/order/1,路由转发到http://order-service/product/1

四、路由断言工厂

路由断言工厂(Route Predicate Factory)的作用是创建 Predicate(断言),用于判断请求是否符合某个路由的匹配条件。当请求到达网关时,网关会通过这些断言工厂生成的 Predicate,筛选出最合适的路由进行转发。

1.核心原理

过滤器分为局部过滤器 (仅对当前路由生效)和全局过滤器(对所有路由生效),这里的 "过滤工厂" 特指局部过滤器的工厂。

命名规则:工厂类名以GatewayFilterFactory结尾(如AddRequestHeaderGatewayFilterFactory),配置时使用前缀(如AddRequestHeader)。

执行时机:分为 "前置过滤"(请求转发前执行,如权限校验)和 "后置过滤"(服务响应后执行,如日志记录)。

2.内置网关过滤工厂

Spring Cloud Gateway 内置了 很多种过滤工厂,覆盖请求修改、路径处理、限流、熔断等场景。以下是最常用的几种:

配置示例:

java 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/product/**             # 路径匹配:/user/开头的请求
            - Method=GET                   # 方法匹配:只接受GET请求
            - Query=token                  # 参数匹配:必须包含token参数
            - Header=X-Request-Source,app  # 头匹配:X-Request-Source必须为app

3.自定义路由断言工厂

  1. 定义工厂类 :继承AbstractRoutePredicateFactory,泛型为配置类(存储断言参数)。

  2. 实现方法 :重写apply方法(生成 Predicate)和shortcutFieldOrder方法(指定参数顺序)。

  3. 注册为 Bean :通过@Component注解注册。

代码示例:自定义 "请求 IP 在白名单中" 的断言工厂

java 复制代码
// 配置类:存储白名单参数
@Data
public class IpWhiteListConfig {
    private List<String> allowedIps; // 允许的IP列表
}
​
// 自定义断言工厂
@Component
public class IpWhiteListRoutePredicateFactory 
    extends AbstractRoutePredicateFactory<IpWhiteListConfig> {
​
    // 构造方法:指定配置类
    public IpWhiteListRoutePredicateFactory() {
        super(IpWhiteListConfig.class);
    }
​
    // 生成Predicate:判断请求IP是否在白名单中
    @Override
    public Predicate<ServerWebExchange> apply(IpWhiteListConfig config) {
        return exchange -> {
            // 获取客户端IP
            String clientIp = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
            // 检查是否在白名单中
            return config.getAllowedIps().contains(clientIp);
        };
    }
​
    // 指定配置参数的顺序(用于简化配置)
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("allowedIps");
    }
}

配置示例:

java 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: admin-service
          uri: lb://admin-service
          predicates:
            - Path=/admin/**
            - name: IpWhiteList  # 自定义断言的前缀(类名去掉RoutePredicateFactory)
              args:
                allowedIps: 192.168.1.100,127.0.0.1  # 允许的IP列表

五、网关过滤工厂

网关过滤工厂(Gateway Filter Factory)的作用是创建过滤器,用于在请求转发到目标服务前后修改请求或响应,实现横切功能(如添加头信息、路径处理、限流等)。

Filter分为两种类型:Pre类型和Post类型。

Pre类型过滤器: 路由处理之前执行(请求转发到后端服务之前执行),在Pre 类型过滤器中可以做鉴权,限流等。

Post类型过滤器:请求执行完成后, 将结果返回给客户端之前执行。

Spring Cloud Gateway 中内置了很多Filter,用于拦截和链式处理web请求,比如权限校验,访问超时等设定,Spring Cloud Gateway从作⽤范围上, 把Filter可分为GatewayFilter和GlobalFilter。

GatewayFilter:应用到单个路由或者⼀个分组的路由上。

GlobalFilter:应用到所有的路由上,也就是对所有的请求生效。

1.GatewayFilter

内置网关过滤工厂

Spring Cloud Gateway 内置了多种过滤工厂,覆盖请求修改、路径处理、限流、熔断等场景。以下是最常用的几种:

配置示例:

java 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/order/**
          filters:
            - StripPrefix=1  # 去除1层前缀(/order/1 → /1)
            - AddRequestHeader=X-From-Gateway, true  # 添加请求头
            - AddResponseHeader=X-Cache-Time, 60  # 添加响应头
            # 限流配置
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 5  # 每秒允许5个请求
                redis-rate-limiter.burstCapacity: 10  # 突发允许10个请求
                key-resolver: "#{@ipKeyResolver}"  # 基于IP限流(需自定义Bean)

2.GlobalFilter

GlobalFilter是Spring Cloud Gateway中的全局过滤器,它和GatewayFilter的作用是相同的,GlobalFilter会应用到所有的路由请求上,全局过滤器通常用于实现与安全性,性能监控和日志记录等相关的全局功能。

Spring Cloud Gateway 内置的全局过滤器也有很多,比如:

Gateway Metrics Filter:网关指标, 提供监控指标

Forward Routing Filter:用于本地forword, 请求不转发到下游服务器

LoadBalancer Client Filter:针对下游服务, 实现负载均衡

快速上手

1.添加依赖

XML 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2.代码示例

java 复制代码
@Component  // 注册成 Spring Bean,Gateway 自动识别
public class LogGlobalFilter implements GlobalFilter, Ordered {
​
    private static final Logger log = LoggerFactory.getLogger(LogGlobalFilter.class);
​
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 前置逻辑
        log.info("请求路径:{}", exchange.getRequest().getURI());
​
        // 继续执行下一个过滤器
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 后置逻辑
            log.info("响应状态码:{}", exchange.getResponse().getStatusCode());
        }));
    }
​
    @Override
    public int getOrder() {
        return -1; //数字越小优先级越高,Ordered.HIGHEST_PRECEDENCE = Integer.MIN_VALUE
    }
}

3.配置示例

java 复制代码
spring:
  cloud:
    gateway:
      metrics:
        enabled: true   # 启用 Gateway 的监控指标(Metrics)
management:
  endpoints:
    web:
      exposure:
        include: "*"    # 暴露所有 Actuator 端点
  endpoint:
    health:
      show-details: always   # 健康检查时总是显示详细信息(
    shutdown:
      enabled: true          # 开启优雅关闭(/actuator/shutdown 接口),生产环境一般建议关闭

4.测试

访问http://127.0.0.1:10030/actuator, 显⽰所有监控的信息链接

3.Default Filters

前面的filter添加在指定路由下,所以只对当前路由生效,若需要对全部路由生效,可以使用spring.cloud.gateway.default-filters 这个属性需要⼀个filter的列表。

示例:

java 复制代码
spring:
  cloud:
    gateway:
      default-filters:
        # 给所有响应都加一个响应头
        - AddResponseHeader=X-Response-Default-Red, Default-Blue
        # 给所有请求的路径都自动加上前缀
        - PrefixPath=/httpbin

4.自定义网关过滤工厂

自定义过滤工厂用于实现业务特定的过滤逻辑(如自定义签名校验、日志记录等)。步骤如下:

  1. 定义工厂类 :继承AbstractGatewayFilterFactory,泛型为配置类(存储过滤参数)。

  2. 实现方法 :重写apply方法(生成 GatewayFilter)和shortcutFieldOrder方法(指定参数顺序)。

  3. 注册为 Bean :通过@Component注解注册。

代码示例:自定义 "请求耗时统计" 过滤器工厂

java 复制代码
// 配置类:存储是否打印日志的参数
@Data
public class RequestTimeLogConfig {
    private boolean enabled; // 是否启用日志
}
​
// 自定义过滤工厂
@Component
public class RequestTimeLogGatewayFilterFactory 
    extends AbstractGatewayFilterFactory<RequestTimeLogConfig> {
​
    public RequestTimeLogGatewayFilterFactory() {
        super(RequestTimeLogConfig.class);
    }
​
    @Override
    public GatewayFilter apply(RequestTimeLogConfig config) {
        return (exchange, chain) -> {
            if (!config.isEnabled()) {
                return chain.filter(exchange); // 不启用则直接放行
            }
​
            // 前置逻辑:记录请求开始时间
            long startTime = System.currentTimeMillis();
            
            // 执行后续过滤器链
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                // 后置逻辑:计算耗时并打印
                long endTime = System.currentTimeMillis();
                long cost = endTime - startTime;
                log.info("请求路径:{},耗时:{}ms", 
                    exchange.getRequest().getPath(), cost);
            }));
        };
    }
​
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("enabled");
    }
}

配置示例

java 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/product/**
          filters:
            - name: RequestTimeLog  # 自定义过滤器前缀
              args:
                enabled: true  # 启用耗时统计日志

六、过滤器的执行顺序

请求路由后,网关会把当前项目中的GatewayFilter和GlobalFilter合并到⼀个过滤器链(集合)中,并进行排序,依次执行过滤器。

每⼀个过滤器都必须指定⼀个int类型的order值,默认值为0,表示该过滤的优先级,order值越小,优先级越高,执行顺序越靠前。

Filter通过实现Order接口或者添加@Order注解来指定order值。

Spring Cloud Gateway提供的Filter由Spring指定,用户也可以自定义Filter,由用户指定。当过滤器的order值⼀样时, 会按照 defaultFilter > GatewayFilter > GlobalFilter的顺序执行。