首页 > 解决方案 > Spring Cloud Gateway:不路由请求,最终遇到413请求实体太大

问题描述

我正在尝试设置一个简单的 Spring Cloud Gateway 示例。

我有 2 个在本地运行的 docker 容器,它们会在命中以下端点时AAA做出响应ZZZ

http://localhost:2000/restmessage
http://localhost:2001/restmessage

我正在尝试制作一个简单的网关,它将路由到这些服务之一。最终会有实际的逻辑来做出这个决定,但现在我只想看到一些工作并且已经硬编码到第一个实例。

这是我的GlobalFilter

@Component
public class MacFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerWebExchange modifiedExchange = exchange.mutate()
                .request(rq -> rq.uri(
                        UriComponentsBuilder.fromUri(exchange.getRequest().getURI())
                        .host("localhost")
                        .port(2000)
                        .build()
                        .toUri()
                ))
                .build();

//        ServerWebExchangeUtils.setAlreadyRouted(modifiedExchange);


        return chain.filter(modifiedExchange);
    }
}

和属性

spring.cloud.gateway.routes[0].id=routezero
spring.cloud.gateway.routes[0].uri=http://localhost:8081
spring.cloud.gateway.routes[0].predicates[0]=Path=/restmessage

每次我使用 restmessage ( http://localhost:8080/restmessage) 访问网关时,此过滤器都会运行。但是如果被注释的setAlreadyRouted方法被注释掉了,它会命中数百次。最终 curl 命令失败并显示413 REQUEST ENTITY TOO LARGE. 通过查看 docker 服务的日志,我可以看出它们从未被击中。

$ curl localhost:8080/restmessage -i
HTTP/1.1 413 Request Entity Too Large
content-length: 0

如果我取消注释该setAlreadyRouted方法,它不再调用数百次并且请求立即返回,但响应为空,并且不再调用 docker 容器。

$ curl localhost:8081/restmessage -i
HTTP/1.1 200 OK
content-length: 0

我也用 aFilterFactoryRouteLocatorBean 尝试过这个,但它们都表现出相同的行为。

我一直在搜寻所有文档,但我能找到的一切似乎都表明这应该可以工作。有人可以帮帮我吗?

标签: javaspringrestgatewayspring-cloud-gateway

解决方案


您要做的是定义后端服务的路由。在您当前的设置中,您正在创建到在端口 8081 上运行的服务的路由,据我在您的描述中所读到的,该端口上没有运行任何服务。

因此,换句话说,如果您有 2 个相同的服务,一个在 localhost:2000 上运行,另一个在 localhost:2001 上运行,您将需要 2 个路由,一个用于一个服务,一个用于另一个。当然,由于服务公开了相同的端点,您将需要一些东西来区分您要路由到哪个服务。例如,这可以通过在您的请求中添加标头来完成。

示例设置可能是这样的。在您的 application.yaml 中(所以不在您的 application.properties 中,也可以在属性文件中完成,但 yaml 更适合此目的),输入如下内容:

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
        - id: 2000service
          uri: http://localhost:2000
          predicates:
            - Path=/restmessage
            - Header=route, service-one
        - id: 2001service
          uri: https://localhost:2001
          predicates:
            - Path=/restmessage
            - Header=route, service-two

您可以摆脱 GlobalFilter 和您定义的属性。现在启动您的应用程序:

mvn spring-boot:run

然后对您的服务进行 curl(假设您的网关在端口 8080 上运行):

curl http://localhost:8080/restmessage -H "route: service-one"

您现在应该看到您的请求被路由到在端口 2000 上运行的服务。

希望这可以帮助!


推荐阅读