Gateway网关动态路由配置(YAML格式 + JSON格式)

1、前言

在我们开发微服务系统时,Gateway是必不可少的一个组件,我们可以通过Gateway来转发用户进行的请求,这样就可以隐藏具体系统的信息。
在微服务系统开发中,常常是以团队的方式进行开发的,所以就需要在Gateway中进行路由的配置,Gateway为开发者提供了三种路由配置的方式:

  1. 自定义RouteLocator 对象,通过硬编码的方式实现路由配置。
  2. 通过YAML文件配置routes属性。
  3. 实现ApplicationEventPublisherAware接口结合Nacos,监听Naocs中的路由文件,完成动态路由配置。

其中第二种和第三种都可以结合Nacos实现动态路由,主要看开发者怎么选择。第二种就是结合Nacos的配置中心,将routes参数下的数据放入到nacos中,我这里使用第三种进行展示,用JSON的格式配置路由信息。

2、前置知识

我们知道Gateway有两个重要的组件:PredicatesFilters

2.1、Predicates

Predicates的主要功能是进行请求的拦截和筛选。当一个请求来到Gateway时,Predicates会根据配置的规则对请求进行评估,如果请求满足某种条件,那么这个请求就会被分发到相应的路由。

2.1.1、Path

Path表示请求当前服务的路径的匹配格式。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
      - id: path_route  
        uri: http://127.0.0.1:8080  
        predicates:  
        - Path=/path/**,/path-server/**

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "Path",  
            "args": {   
                "_genkey_0": "/path/**",  
                "_genkey_1": "/path-server/**"  
            }  
        }  
    ]  
}

_genkey_0、_genkey_1可以自定义,没有限制,表示的是Path这个参数下的值。

2.1.2、Method

进入当前服务的请求方式。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
      - id: path_route  
        uri: http://127.0.0.1:8082  
        predicates:  
        - Method=GET,POST

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "Method",  
            "args": {   
                "_genkey_0": "GET",  
                "_genkey_1": "POST"
        }  
    ]  
}

2.1.3、After

路由在指定时间之后生效。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
      - id: path_route
        uri: http://127.0.0.1:8082  
        predicates:
        - After=2021-08-16T07:36:00.000+08:00[Asia/Shanghai]

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "After",  
            "args": {  
                "datetime": "2023-09-23T07:36:00.000+08:00[Asia/Shanghai]"  
            }  
        }  
    ]  
}

有关时间的参数,只能为datetime,此处可在源码AfterRouterPredicateFactory类中找到

2.1.4、Before

路由在指定时间之前有效。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
      - id: path_route  
        uri: http://127.0.0.1:8082  
        predicates:  
        - Before=2023-09-23T07:36:00.000+08:00[Asia/Shanghai]

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "Before",  
            "args": {  
                "datetime": "2023-09-23T07:36:00.000+08:00[Asia/Shanghai]"  
            }  
        }  
    ]  
}

2.1.5、Between

路由在指定时间之间有效。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
        - id: path_route
          uri: http://127.0.0.1:8082  
          predicates:  
            - Between=2023-09-23T07:36:00.000+08:00[Asia/Shanghai], 2023-09-23T08:15:00.000+08:00[Asia/Shanghai]

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "Between",  
            "args": {  
                "datetime1": "2023-09-23T07:36:00.000+08:00[Asia/Shanghai]",  
                "datetime2": "2023-09-23T08:18:00.000+08:00[Asia/Shanghai]"  
            }  
        }  
    ]  
}

args对应值的key只能为datetime1和datetime2,此处可在源码BetweenRouterPredicateFactory类中找到。

2.1.6、Cookie

表示cookie中存在指定名称,并且对应的值符合指定正则表达式,才算匹配成功

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
      - id: path_route
        uri: https://127.0.0.1:8080
        predicates:  
        - Cookie=session, fly

session是cookie的名称,fly是cookie的值。

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "Cookie",  
            "args": {  
              	"name": "session",  
              	"regexp": "fly"  
            }  
        }  
    ]  
}

regexp表示正则的意思。

2.1.7、Header

表示header中存在指定名称,并且对应的值符合指定正则表达式,才算匹配成功。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
      - id: path_route
        uri: https://example.org  
        predicates:  
        - Header=X-Request-Id, \d+

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "Header",  
            "args": {  
                "header": "X-Request-Id",  
                "regexp": "\\d+"  
            }  
        }  
    ]  
}

2.1.8、Host

表示请求的host要和指定的字符串匹配,并且对应的值符合指定正则表达式,才算匹配成功。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
      - id: path_route
        uri: http://127.0.0.1:8082  
        predicates:  
        - Host=localhost:8080,localhost:8081

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "Host",  
            "args": {  
                "_genkey_0": "localhost:8080",
                "_genkey_0": "localhost:8081"
            }  
        }  
    ]  
}

2.1.9、Query

在请求中要带有指定的参数,且该参数的值需等于配置的值或匹配正则表达式,才算匹配成功。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:
      - id: path_route
        uri: http://127.0.0.1:8082
        predicates:  
        - Query=name, fly

有一个叫做name的参数,值为fly。

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "Query",  
            "args": {   
                "param": "name",  
                "regexp": "fly"  
            }  
        }  
    ]  
}

2.1.10、RemoteAddr

匹配指定来源的请求。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
      - id: path_route
        uri: http://127.0.0.1:8082
        predicates:  
        - RemoteAddr=192.168.0.1

JSON格式:

{  
    "id": "remoteaddr_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "RemoteAddr",  
            "args": {   
                "_genkey_0": "192.168.0.1"  
            }  
        }  
    ]  
}

2.1.11、Weight

按照权重将请求分发到不同的位置。

YAML格式:

spring:  
  cloud:  
    gateway:  
      routes:  
      - id: path_route
        uri: http://127.0.0.1:8082
        predicates:  
        - Weight=group1, 8

JSON格式:

{  
    "id": "path_route",  
    "uri": "http://127.0.0.1:8082",  
    "predicates":[  
        {  
            "name": "Weight",  
            "args": {   
                "weight.group": "group1",
                "weight.weight": "8"
            }
        }  
    ]  
}

权重这个一般不用咯,因为在微服务中一般有loadblance负载均衡器在,所以请求的分发一般由它来负责。

2.2、Filters

与Predicates相比,Filters的功能更加全面。它不仅可以在请求到达目标之前进行拦截,还可以对响应进行修改和修饰。具体来说,Filters可以用于修改响应报文,增加或修改Header或Cookie,甚至可以修改响应的主体内容。这些功能是Predicates所不具备的。

2.2.1、AddRequestHeader

添加请求头信息。

YAML格式:

spring:
  cloud:
	gateway:
	  filters:
		- AddRequestHeader = X-Request-Foo,Bar

添加一个名为X-Request-Foo的请求头参数,值为Bar。

JSON格式:

{
	"name":"AddRequestHeader",
	"args":{
		"_genkey_0":"X-Request-Foo",
		"_genkey_1":"Bar"
	}
}

2.2.2、RewritePath

路径重写。

YAML格式:

spring:
  cloud:
	gateway:
	  filters:
		- RewritePath = /path/(?<segment>.*), /$\{segment}

JSON格式:

{
	"name":"RewritePath",
	"args":{
		"_genkey_0":"/foo/(?<segment>.*)",
		"_genkey_1":"/$\\{segment}"
		}
}

2.2.3、AddRequestParameter

添加请求参数。

YAML格式:

spring:
  cloud:
	gateway:
	  filters:
		- AddRequestParameter = foo,bar

JSON格式:

{
	"name":"AddRequestParameter",
	"args":{
		"_genkey_0":"foo",
		"_genkey_1":"bar"
	}
}

2.2.4、AddResponseHeader

添加响应参数。

YAML格式:

spring:
  cloud:
	gateway:
	  filters:
		- AddResponseHeader = X-Request-Foo,Bar

JSON格式:

{
	"name":"AddResponseHeader",
	"args":{
		"_genkey_0":"X-Request-Foo",
		"_genkey_1":"Bar"
	}
}

2.2.5、PrefixPath

路径前缀增强(添加路径)。

YAML格式:

spring:
  cloud:
	gateway:
	  filters:
		- PrefixPath = /mypath

JSON格式:

{
	"name":"PrefixPath",
	"args":{
		"_genkey_0":"/mypath"
	}
}

2.2.6、StripPrefix

路径前缀删除。

YAML格式:

spring:
  cloud:
	gateway:
	  filters:
		- StripPrefix = 2

删除前面两个前缀。

JSON格式:

{
	"name":"StripPrefix",
	"args":{
		"_genkey_0":"2"
	}
}

2.2.7、RedirectTo

重定向。要指定响应码和重定向路径。

YAML格式:

spring:
  cloud:
	gateway:
	  filters:
		- RedirectTo = 302,https://www.baidu.com

JSON格式:

{
	"name":"RedirectTo",
	"args":{
		"_genkey_0":"302",
		"_genkey_1":"https://www.baidu.com"
	}
}

2.2.8、RemoveRequestHeader

删除请求头属性。

YAML 格式:

spring:
  cloud:
	gateway:
	  filters:
		- RemoveRequestHeader = X-Request-Foo

JSON格式:

{
	"name":"RemoveRequestHeader",
	"args":{
		"_genkey_0":"X-Request-Foo"
	}
}

2.2.9、RemoveResponseHeader

删除响应头属性。

YAML格式:

spring:
  cloud:
	gateway:
	  filters:
		- RemoveResponseHeader = X-Request-Foo

JSON格式:

{
	"name":"RemoveResponseHeader",
	"args":{
		"_genkey_0":"X-Request-Foo"
	}
}

3、动态路由的实现

动态路由的原理:将路由信息存放在某个中间层,然后在项目启动后对这个文件进行加载和监听,这个中间层可以是数据库或者文件,重要的是能在这个文件被修改后监听到这个文件的变化并重新加载。
这里的中间层使用的是nacos的配置心中,Gateway整合了Naocs配置中心后,可以很好的监听指定的配置文件。

3.1、Gateway中的YAML文件

server:
  port: 8000
nacos_server: 127.0.0.1:8848
spring:
  application:
    name: gateway-server
  cloud:
    nacos:
      discovery:
        server-addr: ${nacos_server}
      config:
        file-extension: yaml
        server-addr: ${nacos_server}

因为在Gateway中整合了Nacos配置中心,所以默认会监听gateway-server.yaml或者gateway-server这两个文件。在项目启动的时候可以看到的。故此,我就想gateway的基本配置放在配置中心中了。

配置如下:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
    sentinel:
      transport:
        dashboard: http://localhost:8080
      datasource:
        flow-control:
          nacos:
            server-addr: ${nacos_server}
            data-id: gateway_flux-control_config.json
            rule-type: gw_flow
        degrade-control:
          nacos:
            data-id: gateway_degrade-control_config.json
            server-addr: ${nacos_server}
            rule-type: degrade
      eager: true

## 自定义的配置文件信息
dynamic-routes:
  nacos-addr: ${nacos_server}
  data-id: gateway-dynamic-routes.json
  group: DEFAULT_GROUP

3.1、路由文件

我们需要结合前置知识来编写路由规则,并将文件存放在Nacos配置中心中。

[
    {
        "id":  "feign-test",
        "uri": "http://localhost:8082",
        "predicates":[{
            "name": "Path",
            "args":{
                "pattern": "/feign/**"
            }
        }],
        "filters":[{
            "name": "StripPrefix",
            "args":{
                "value1": 1
            }
        }]
    },
    ## 下面还可以写其他的路由配置。
]

3.2、实现ApplicationEventPublisherAware接口

我们可以使用ApplicationEventPublisherAware的实现类来监听路由文件的变化并重新加载。

@Component
public class NacosDynamicRouteService implements ApplicationEventPublisherAware, ApplicationRunner {

    @Value("${dynamic-routes.data-id}")
    private String dataId;
    @Value("${dynamic-routes.group}")
    private String group;
    @Value("${dynamic-routes.nacos-addr}")
    private String serverAddr;
    
    private final RouteDefinitionWriter routeDefinitionWriter;
    private ApplicationEventPublisher applicationEventPublisher;
    private static final List<String> ROUTE_LIST = new ArrayList<>();


    public NacosDynamicRouteService(RouteDefinitionWriter routeDefinitionWriter){
        this.routeDefinitionWriter = routeDefinitionWriter;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @Override
    public void run(ApplicationArguments args) {
        try {
        // 获取nacosService对象
            ConfigService configService = NacosFactory.createConfigService(serverAddr);
            // 获取指定的路由配置文件
            String config = configService.getConfig(dataId, group, 5000);
            // 添加对路由文件的监听器
            configService.addListener(dataId, group, new NacosDynamicRouteListener(config));
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }

// 清除路由信息
    private void clearRoute() {
        for (String id : ROUTE_LIST) {
            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
        }
        ROUTE_LIST.clear();
    }

	// 路由文件监听器
    private class NacosDynamicRouteListener extends AbstractListener{

        public NacosDynamicRouteListener(String config){
            receiveConfigInfo(config);
        }

        @Override
        public void receiveConfigInfo(String s) { // S就是路由文件
            clearRoute();
            List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(s, RouteDefinition.class);
            for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
                routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
                ROUTE_LIST.add(routeDefinition.getId());
            }
            applicationEventPublisher.publishEvent(new RefreshRoutesEvent(routeDefinitionWriter));
        }
    }


}
### 回答1: Spring Cloud Gateway动态路由是指在Spring Cloud Gateway网关中,路由规则可以在运行时动态地进行添加、删除、修改等操作。相比于静态路由动态路由可以根据实际情况进行动态调整,从而更加灵活、方便地进行流量控制和负载均衡。例如,在服务上线、下线或者进行扩容缩容的时候,可以通过修改路由规则,动态地将流量引导到不同的服务实例中,从而实现动态负载均衡和容错能力。 ### 回答2: Spring Cloud Gateway动态路由是指在Spring Cloud Gateway网关中,根据某些条件动态地将请求路由到不同的目标服务实例上。传统的静态路由需要事先配置路由规则,但是在微服务架构中,服务的实例会动态地增加、减少、更新,因此需要一种能够动态适应变化的路由机制。 Spring Cloud Gateway动态路由的实现需要依赖于服务注册与发现组件,比如Eureka或Consul。当服务实例注册到服务注册中心时,Spring Cloud Gateway会订阅服务注册中心的变化,当有新的服务实例上线或下线时会自动更新路由规则。 动态路由可以根据多种条件进行判断和匹配,如路径、域名、Header、请求参数等。可以根据业务需求动态配置路由规则,使得请求能够被准确地路由到目标服务实例上。动态路由能够实现动态扩展和负载均衡,提高系统的灵活性和可伸缩性。 Spring Cloud Gateway动态路由配置通常以YAMLJSON的形式进行,可以通过配置文件、配置中心或接口的方式进行配置。支持多种动态路由配置方式,如断言(Predicate)、过滤器(Filter)、转发(Forwarding)、重定向(Redirecting)等,可以根据具体需求实现各种功能。 总之,Spring Cloud Gateway动态路由是一种能够根据条件动态路由请求到不同服务实例的机制,具有灵活、可扩展、高效的特点,是构建微服务架构中的网关的重要特性。 ### 回答3: Spring Cloud Gateway动态路由是一种基于Spring Cloud Gateway框架的动态路由功能。传统的静态路由是在网关配置文件中预先定义好所有的路由规则,而动态路由可以在运行时根据业务需要实时插入、修改和删除路由规则,实现灵活的请求转发和负载均衡。通过动态路由,可以根据不同的路径或者请求头等匹配条件,将请求转发到指定的目标服务,从而实现微服务架构中的请求路由和负载均衡功能。动态路由配置可以通过网关的API接口或者命令行工具进行管理,使得路由配置更加灵活和方便。同时,动态路由还支持动态修改和重载路由规则,可以根据实际情况动态调整路由策略,提高系统的可用性和弹性。Spring Cloud Gateway动态路由的实现是基于Spring Framework中的路由器和过滤器的概念,通过使用reactive编程模型处理请求,并且支持使用各种插件来扩展网关的功能,例如服务发现、熔断器、限流等。总之,Spring Cloud Gateway动态路由提供了一种灵活、易用且高性能的路由解决方案,适用于构建微服务架构的API网关
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值