我们知道在gateway中加入下面的配置,则网关会根据路径中的服务名会自动路由到对应的服务,

如 http://gateway.com/my-service-name/login这个请求,将会根据my-service-name这个服务名路由到该服务。

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启根据微服务名称自动转发
          lower-case-service-id: true 

项目需求

现在的需求是:http://gateway.com后面第一级不是服务名,而是按照业务含义定义的业务模块名称,每个微服务中包含了多个业务模块,配置中心维护了业务模块名和服务名的映射关系。这些业务模块在整个平台是唯一的,所以需求就变成了,要根据模块的名称去路由到模块对应的服务上。

如下图所示:user和role模块都属于account-service,所以http://gateway.com/user/add-userhttp://gateway.com/role/add-role都需要路由到account-service中。

我的实现

要想实现上面的需求,我们需要了解俩方面的知识,一是gateway路由的基本流程,而是按照服务名路由是如何实现的?

gateway路由的基本流程

一般我們配置网关时,都需要有如下的配置信息,下图配置了俩个路由,

spring:
  cloud:
    gateway:
      routes: # 路由可以有多个
        - id: service-id1
          uri: http://127.0.0.1:8096
          predicates: 
             - Path=/test1/**
        - id: service-id2
          uri: http://127.0.0.1:8081 # ⽬标服务地址
          predicates: 
             - Path=myservice/test2/**
          filters:
             - StripPrefix=1

上面的配置信息的每个路由在程序中都会对应到一个RouteDefinition对象,如下图所示

路由主要由3部分组成:uri,predicates(断言),filters(过滤器)。下面来说说这三部分的作用。

predicates的作用

当一个请求进入网关时,那么网关如何决定往哪个地址转发呢?

其实是网关会遍历所有的路由列表(下图配置了2个)中,然后从中获取出一个匹配的路由,那么根据什么规则判断一个路由是否匹配当前的路由呢,这就用到了路由中的predicates,

比如下图中配置了- Path=/test1/**,则会根据当前请求的path判断是否与/test1/**匹配,比如我当前请求的地址为http://www.aaa.com/test1/add-test,则会拿host后面的地址/test1/add-test与

/test1/**做匹配,如果匹配成功则就选择当前路由,不匹配则继续与下一个路由进行匹配。那么具体的实现代码在那块呢,其实是在PathRoutePredicateFactory这个类里,类的命名规则就是

- Path=/test1/**中=前面的Path加上RoutePredicateFactory。具体的实现为下图中的apply方法。

 

 

  

uri的作用

那么上面确定了具体的路由之后,到底往哪里转发呢,这就用到了uri,默认情况下,转发的完整地址为uri 拼接上我们请求的path,比如我们请求的地址为http://www.gateway.com/test1/add-test

,匹配到上面的第一个路由后,会转发到http://127.0.0.1:8096/test1/add-test 这个地址。这就是uri的作用。

 

filter的作用

讲解完上面的知识后,其实已经能实现基本的转发功能了,但是实际开发过程中,我们可能有修改转发路径的需求,或者我想在转发之前向请求头里设置一些属性等等一些特殊需求。其实filter就是干这个的。

如上图配置的第二个路由中有- StripPrefix=1,这个其实是去掉path中的第一级路径,然后完成转发,比如我的请求地址是  http://www.gateway.com/myservice/test2/add-test2,这样就匹配到了第二个路由,

但是由于加了 StripPrefix=1 配置,所以会把path(/myservice/test2/add-test2)中的第一级去掉,即path变成了test2/add-test2,然后与uri拼接成完整的地址http://127.0.0.1:8081/test2/add-test2。

StripPrefix的具体实现代码为StripPrefixGatewayFilterFactory类中的apply方法,类的命名也是  StripPrefix    加上固定的GatewayFilterFactory。实现逻辑如下图

下面我们说说按照服务名动态路由是如何实现的。

springCloud-gateway按照服务名动态路由的改造(二)

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐