DiscoveryClient 路由定义定位器 (DiscoveryClient Route Definition Locator)
你可以配置网关,使其根据在与 DiscoveryClient 兼容的服务注册中心中注册的服务来自动创建路由。
默认情况下,创建的路由使用协议 lb://service-name(其中 service-name 是 DiscoveryClient::getServices 返回的字符串),这意味着它们是经过负载均衡的。因此,你还需要在类路径中包含 org.springframework.cloud:spring-cloud-starter-loadbalancer 依赖项。
要启用此功能,请设置 spring.cloud.gateway.discovery.locator.enabled=true,并确保类路径中已包含并启用了 DiscoveryClient 的实现(如 Netflix Eureka、Consul、Zookeeper 或 Kubernetes)。
1. 为 DiscoveryClient 路由配置断言和过滤器
默认情况下,网关为使用 DiscoveryClient 创建的路由定义了一个断言和一个过滤器。
- 默认断言:是一个路径(Path)断言,定义的模式(Pattern)为
/serviceId/**,其中serviceId是来自DiscoveryClient的服务 ID。 - 默认过滤器:是一个重写路径(RewritePath)过滤器,其正则表达式为
/serviceId/?(?<remaining>.*),替换值为/${remaining}。这会在请求发送到下游之前从路径中剥离服务 ID。
如果你想自定义 DiscoveryClient 路由使用的断言或过滤器,请设置 spring.cloud.gateway.discovery.locator.predicates[x] 和 spring.cloud.gateway.discovery.locator.filters[y]。在进行此类配置时,如果你想保留原有的默认功能,需要确保包含上述的默认断言和过滤器。
以下示例展示了在 properties 和 yaml 格式中这种配置的样子:
Example 1. application.properties
spring.cloud.gateway.discovery.locator.predicates[0].name=Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]="'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name=Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]="'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name=CircuitBreaker
spring.cloud.gateway.discovery.locator.filters[0].args[name]=serviceId
spring.cloud.gateway.discovery.locator.filters[1].name=RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]="'/' + serviceId + '/?(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]="'/$\{remaining}'"Example 2. application.yml
spring:
cloud:
gateway:
discovery:
locator:
predicates:
- name: Host
args:
pattern: "'**.foo.com'"
- name: Path
args:
pattern: "'/'+serviceId+'/**'"
filters:
- name: CircuitBreaker
args:
name: serviceId
- name: RewritePath
args:
regexp: "'/' + serviceId + '/?(?<remaining>.*)'"
replacement: "'/${remaining}'"补充教学 —— 自动化路由的“双刃剑”
DiscoveryClient 路由定位器(通常被称为 “自动路由” 或 “服务发现路由”)是 Spring Cloud Gateway 中非常迷人但也需要谨慎使用的功能。
1. 为什么要用它?(省事) 在微服务非常多的情况下,手动在 application.yml 里写几十个服务的路由配置(每个都要写 id, uri, predicates, filters)简直是灾难。开启这个功能后,只要服务往 Eureka 或 Nacos 一注册,网关立马就能根据服务名自动生成路由。
2. 它是如何工作的? 假设你有一个服务在注册中心叫 USER-SERVICE。网关会自动生成一个类似这样的路由:
- 入口:
http://gateway:8080/USER-SERVICE/login - 转发:
lb://USER-SERVICE/login(自动去掉了/USER-SERVICE前缀,并根据负载均衡找到实例)。
3. 注意事项与风险(避坑指南):
- 服务名大小写:很多注册中心(如 Eureka)默认会将服务名转为大写。如果开启了自动路由,你必须访问
/USER-SERVICE/...。如果你想支持小写,可能需要额外配置spring.cloud.gateway.discovery.locator.lower-case-service-id: true。 - 暴露所有服务:它会默认把注册中心里所有的服务都暴露出来。这在生产环境可能是个安全隐患。如果你只想暴露部分服务,通常建议关闭此功能,改用手动配置。
- 配置语法的特殊性:在自定义
predicates或filters时,你会看到一些奇怪的引号嵌套,比如"'/' + serviceId + '/**'"。这是因为这里使用了 SpEL 表达式。serviceId是一个动态变量,网关在遍历每个服务生成路由时会把真实的服务名填进去。
总结: 初学者和快速原型开发阶段强烈推荐开启,它能极大简化配置。但在大型生产系统、对安全性要求极高的场景下,显式手动配置每一条路由依然是更稳妥的选择。