Spring cloud 如何使用URL动态路由传入请求->;负责的后端服务映射服务?

Spring cloud 如何使用URL动态路由传入请求->;负责的后端服务映射服务?,spring-cloud,spring-cloud-gateway,Spring Cloud,Spring Cloud Gateway,我是SpringCloudGateway的新手,如果我按照预期的方式解决了问题,我无法回答这个问题。我希望有人能给我指出正确的方向,给出建议或提供一些示例代码 要求: my spring cloud gateway服务的传入请求应转发到正确的后端服务(有X个这样的后端服务,每个后端服务负责一个特定任务)。 请求本身没有足够的信息来决定路由到哪个后端服务 存在将任意URL映射到负责的后端服务名称的其他REST服务。响应格式是一些小型JSON,包含要转发到的后端服务的名称 使用SpringCloud

我是SpringCloudGateway的新手,如果我按照预期的方式解决了问题,我无法回答这个问题。我希望有人能给我指出正确的方向,给出建议或提供一些示例代码

要求: my spring cloud gateway服务的传入请求应转发到正确的后端服务(有X个这样的后端服务,每个后端服务负责一个特定任务)。 请求本身没有足够的信息来决定路由到哪个后端服务

存在将任意URL映射到负责的后端服务名称的其他REST服务。响应格式是一些小型JSON,包含要转发到的后端服务的名称

使用SpringCloudGateway实现此功能的最简单/最佳/最智能/预期解决方案是什么

我尝试实现一个
GatewayFilter
,它首先调用映射服务,并根据交换的结果集
GATEWAY\u REQUEST\u URL\u ATTR
。 这样行。但我还有其他问题

  • 是否可以省略
    .uri(“not://needed”)
    路线设置中的零件

  • 为什么订单值需要高于9999?(参见代码示例)

  • @springboot应用程序
    @RestController
    公共类应用程序{
    公共静态void main(字符串[]args){
    SpringApplication.run(Application.class,args);
    }
    @豆子
    公共RouteLocator myRoutes(RouteLocatorBuilder生成器){
    返回生成器.routes().route(r->r
    .alwaysTrue()
    .filters(f->f.filter(新的CustomRequestFilter()))
    .uri(“not://needed)//如何省略?
    .build();
    }
    公共静态类CustomRequestFilter实现GatewayFilter,已订购{
    @凌驾
    public int getOrder(){
    返回10000;//为什么订单>9999?(低于10000不起作用)
    }
    @凌驾
    公共Mono筛选器(服务器WebExchange exchange、网关筛选器链){
    返回getBackendServiceMappingResult(exchange.getRequest().getURI().toString())//异步调用REST服务映射URL->后端服务名称
    .flatMap(映射结果->{
    URI URI=mapServiceNameToBackendService(mappingResult.getServiceName());
    exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY\u请求\u URL\u属性,uri);
    返回链。过滤器(交换);
    });
    }
    私有URI mapServiceNameToBackendService(字符串serviceName){
    试一试{
    交换机(serviceName){
    案例“serviceA”:返回新URI(“http://httpbin.org:80/get");
    案例“serviceB”:返回新URI(“https://someotherhost:443/");
    }
    }捕获(URISyntaxException e){
    //忽略
    }
    返回null;
    }
    }
    静态类映射结果{
    字符串serviceName;
    公共字符串getServiceName(){
    返回serviceName;
    }
    }
    静态Mono getBackendServiceMappingResult(字符串uri){
    WebClient客户端=WebClient.create(“http://localhost:8080");
    返回client.get();
    }
    }
    

    是否有更好的方法(使用SpringCloudGateway)来解决此需求?

    URI是必需的。我通常使用
    no://op
    ,因为它很短。排序很重要,因为还有其他过滤器可能会影响结果。感谢您的回答@Spencergib。你能提供更多关于过滤器链的信息吗?我只设置了一个单独的过滤器,不管排序是什么,它都应该首先启动。如果我将order设置为Ordered.HIGHEST\u priority或Ordered.LOWEST\u priority,则会产生相同的错误结果。响应只是一个空的body 200er,而不是请求服务的响应。我真的不理解这种行为。此外,我很想知道实现是否与SpringCloudGateway的主要贡献者的想法一致。他们是否以不同的方式解决了需求?我写了gateway的大部分内容。我有一个与此类似的用例,但是我需要进行两个非阻塞调用,第一个之后的第二个,将其拆分为不同的过滤器是最佳做法吗?
    @SpringBootApplication
    @RestController
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
        @Bean
        public RouteLocator myRoutes(RouteLocatorBuilder builder) {
            return builder.routes().route(r -> r
                    .alwaysTrue()
                    .filters(f -> f.filter(new CustomRequestFilter()))
                    .uri("not://needed"))  // how to omit ?
                    .build();
        }
    
    
        public static class CustomRequestFilter implements GatewayFilter, Ordered {
    
            @Override
            public int getOrder() {
                return 10000; // why order > 9999 ?  (below 10000 does not work)
            }
    
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
                return getBackendServiceMappingResult(exchange.getRequest().getURI().toString()) //async call to REST service mapping URL->backend service name
                        .flatMap(mappingResult -> {
                            URI uri = mapServiceNameToBackendService(mappingResult.getServiceName());
                            exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, uri);
                            return chain.filter(exchange);
                        });
            }
    
            private URI mapServiceNameToBackendService(String serviceName) {
                try {
                    switch (serviceName) {
                        case "serviceA": return new URI("http://httpbin.org:80/get");
                        case "serviceB": return new URI("https://someotherhost:443/");
                    }
                } catch (URISyntaxException e) {
                    //ignore
                }
                return null;
            }
        }
    
        static class MappingResult {
            String serviceName;
            public String getServiceName() {
                return serviceName;
            }
        }
    
        static Mono<MappingResult> getBackendServiceMappingResult(String uri) {
            WebClient client = WebClient.create("http://localhost:8080");
            return client.get().uri(uriBuilder -> uriBuilder.path("/mapping").queryParam("uri", uri).build()).retrieve().bodyToMono(MappingResult.class);
        }
    }