您的位置:

SpringCloudGateway动态路由详解

一、概述

Spring Cloud Gateway是一个基于Spring Boot 2.0+和Spring Framework 5.0+的网关,旨在为微服务架构提供一种简单有效的方式来处理API请求。Spring Cloud Gateway作为Spring Cloud生态系统中的网关,目标是提供统一的路由方式且基于Filter链的方式提供各种便捷的操作,例如:熔断、限流、重试等。

二、动态路由介绍

动态路由是Spring Cloud Gateway最为重要的功能之一,它提供了非常方便的方式来动态增删改路由规则而无需停止服务。采用动态路由可以让我们实现路由的自由发挥,充分发挥Spring Cloud Gateway的优势,使得我们能够在反向代理层面对请求进行拦截和控制,达到限流、鉴权、监控等效果。

三、动态路由配置示例

下面我们以一个示例来讲解如何配置Spring Cloud Gateway的动态路由,假设有三个服务分别是service1、service2、service3,下面是对service1进行动态路由配置的代码示例:

spring:
  cloud:
    gateway:
      routes:
        - id: service1_route
          uri: http://localhost:8080
          predicates: 
            - Path=/service1/**
          filters:
            - RewritePath=/service1(?<segment>/?.*), $\{segment}

上面的配置意味着,所有路径为 /service1/** 的请求将被转发到 http://localhost:8080 这个服务上, RewritePath 告诉网关重新解析路径。如果没有此过滤器,/service1/** 对应的请求将会被发送到后端的 /service1 这个路径上,RewritePath 的作用就是将 /service1/** 路径下的所有请求的 /service1 替换成空字符串。

四、动态路由实现原理

动态路由的实现依赖于 Spring Cloud Gateway 的核心——RouteLocator,Spring Cloud Gateway 将配置中的所有 Route 信息交给 RouteLocator,RouteLocator根据自身的实现方式返回一个包含所有 Route 信息的 RouteDefinition 列表,Spring Cloud Gateway 则将这些 RouteDefinition 转换为 Route,并启动这些 Route 将请求转发到后端的服务。

当注册中心中的服务数量发生变化或者配置方式发生变化时,Spring Cloud Gateway会接收到配置中心发来的消息,更新本地的 RouteLocator 中记录的 RouteDefinition,Spring Cloud Gateway内置了一个RefreshRoutesListener,用来更新 Route,网关收到消息后会触发RefreshRoutesEvent事件,最终调用RefreshRoutesListener的onApplicationEvent方法,执行Route表的刷新操作,具体如下:

public class RefreshRoutesListener implements ApplicationListener {

    private static final Logger log = LoggerFactory.getLogger(RefreshRoutesListener.class);

    private final RouteDefinitionRouteLocator routeDefinitionRouteLocator;

    private final GatewayProperties gatewayProperties;

    private final RouteLocator routeLocator;

    public RefreshRoutesListener(RouteDefinitionRouteLocator routeDefinitionRouteLocator,
                                 GatewayProperties gatewayProperties, RouteLocator routeLocator) {
        this.routeDefinitionRouteLocator = routeDefinitionRouteLocator;
        this.gatewayProperties = gatewayProperties;
        this.routeLocator = routeLocator;
    }

    @Override
    public void onApplicationEvent(RefreshRoutesEvent event) {
        log.debug("Received refresh event");
        routeDefinitionRouteLocator.setRouteDefinitions(event.getRouteDefinitions());
        CompositeRouteLocator routeLocator = new CompositeRouteLocator(this.routeLocator.getRouteLocators());
        routeLocator.getRouteDefinitions().subscribe(this::logRefreshComplete);
        this.routeDefinitionRouteLocator.initialized(routeLocator);
        this.gatewayProperties.getRoutes().stream().filter(
                route -> route.getId().equals("default")).findFirst().ifPresent(defaultRoute -> {
            if (event.getRouteDefinitions().isEmpty()) {
                log.debug("Clear out the default route");
                defaultRoute.setUri(null);
            }
        });
    }

    private void logRefreshComplete(Collection
    routeDefinitions) {
        if (log.isDebugEnabled()) {
            log.debug("Routes refreshed: " + routeDefinitions);
        }
    }
}

   
  

五、动态路由的优点

采用Spring Cloud Gateway的动态路由可以提供以下几个优点:

1、灵活性高:动态路由能够让我们对路由进行更加灵活的控制,能够更加精准地选择服务。

2、可扩展性高:动态路由对后端的服务并没有太多的要求,用户可以通过增加规则的方式对新的服务进行支持。

3、无需重启:实现动态路由之后,即可实现对服务的动态路由,不需要重启 Spring Cloud Gateway 服务。

六、总结

SpringCloudGateway的动态路由功能是SpringCloud Gateway优秀的特性之一,这个特性可以让我们在网关层面实现更加细致化的控制,同时也提高了整个系统的可扩展性和灵活性,是我们在进行微服务架构设计时很好的选择。