java 如何使用服务发现为Spring Cloud Gateway重写serviceId

eqzww0vc  于 2023-02-28  发布在  Java
关注(0)|答案(3)|浏览(154)

我正在将zuul网关迁移到SCG。我的服务在kubernetes中运行并通过consul注册。典型的服务名称是xxx-service。因此,使用当前网关配置,我可以通过http://address/api/xxx-service/some-path调用它们
我的当前配置:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
          predicates:
            - name: Path
              args:
                pattern: "'/api/' + serviceId + '/**'"
          filters:
            - name: RewritePath
              args:
                regexp: "'/api/' + serviceId + '/(?<remaining>.*)'"
                replacement: "'/${remaining}'"

但是客户端调用它们时服务名中不应该有“-service”后缀。如何配置SCG以使其能够通过http://address/api/xxx-service/some-path调用服务
先前配置:

zuul.routes.xxx.service-id=xxx-service
zuul.routes.aaa-bbb.service-id=aaa-bbb-service
zuul.routes.aaa-bbb.path=/aaa/bbb/**
zuul.strip-prefix=true
zuul.prefix=/api
hlswsv35

hlswsv351#

我的位置完全相同。你找到解决这个问题的诀窍了吗?我知道我们可以在RouteLocator中定义所有路线,如下所示:

/**
 * Route constructions.
 *
 * @param builder
 *                the builder instance
 * @return the final route locator
 */
@Bean
public RouteLocator gatewayRoutes(final RouteLocatorBuilder builder) {
return builder.routes()
    // Declare First service
    .route(r -> r.path("/prefix/myservice1-service/**")
        .filters(f -> f.rewritePath("/prefix/myservicename1-service/(?<remaining>.*)", "/${remaining}"))
        .uri("lb://myservice1").id("myservice1"))

    // Declare Second service
    .route(r -> r.path("/prefix/myservice2-service/**")
        .filters(f -> f.rewritePath("/prefix/myservicename2-service/(?<remaining>.*)", "/${remaining}"))
        .uri("lb://myservice2").id("myservice2"))

    // Etc... Then build
    .build();
}

我不确定,但也许你需要禁用发现定位器才能正确地做到这一点。

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: false

但如果能找到一种不那么脏的解决方案就太好了。

wztqucjr

wztqucjr2#

除了@Rémi Gélibert变体之外,我们还可以实现自己的RouteLocator。它允许您为您的路线选择指定 predicate ,以及能够根据您的意愿修改请求的特殊过滤器
这样,我们就可以将路由配置提取到某种application.properties

@Component
public class CustomRouteLocator implements RouteLocator {

  Map<String, Pattern> prefixPatternsByServiceNames; // external configuration
  Map<String, String> prefixesByServiceNames;        // external configuration 
  Set<String> servicesNames;                         // external configuration

  @Override
  public Flux<Route> getRoutes() {

    return Flux.fromIterable(servicesNames)
        .map(serviceName -> Route.async()
            .id("ROUTE_" + serviceName)
            .predicate(exchange -> {
              String path = exchange.getRequest().getPath().toString();
              return prefixPatternsByServiceNames.get(serviceName).matcher(path).find();
            })
            .filter((exchange, chain) -> {
              ServerHttpRequest origRequest = exchange.getRequest();
              String query = origRequest.getURI().getQuery();
              String originalPath = origRequest.getPath().toString();
              String newPath = originalPath.substring(prefixesByServiceNames.get(serviceName).length());

              ServerHttpRequest request = exchange.getRequest().mutate()
                  .path(query == null? newPath : newPath + "?" + query)
                  .build();
              return chain.filter(exchange.mutate()
                  .request(request)
                  .build());
            })
            .uri("http://" + serviceName)
            .build());
  }

}

请注意:
我的网关依赖于kubernetes服务发现,因此我将uri改写为uri("http://" + serviceName)
如果你有领事馆/欧洲发现集成,你可以尝试这样做的其他方式:uri("lb://" + serviceName)

ppcbkaq5

ppcbkaq53#

您可以进行以下配置以满足您的需要:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
          # defaults is in GatewayDiscoveryClientAutoConfiguration.class
          # SpEL expression context is ServiceInstance.class
          predicates:
            - name: Path
              args:
                pattern: "'/api/'+serviceId.replace('-service', '')+'/**'"
          filters:
            - name: RewritePath
              args:
                regexp: "'/api/.+/?(?<remaining>.*)'"
                replacement: "'/api/'+serviceId+'/${remaining}'"

官方文件:https://cloud.spring.io/spring-cloud-gateway/reference/html/#configuring-predicates-and-filters-for-discoveryclient-routes

相关问题