Spring Cloud Gateway:不路由请求,最终遇到413个请求实体太大

时间:2020-06-16 19:14:19

标签: java spring rest gateway spring-cloud-gateway

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

我有2个本地运行的docker容器,当以下端点被命中时,它们将以AAAZZZ响应

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

每次我使用重新发送消息(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

我也使用FilterFactoryRouteLocator Bean进行了尝试,但是它们都表现出相同的行为。

我一直在搜寻所有文档,但是我发现的所有内容似乎都表明这应该起作用。有人可以帮我吗?

2 个答案:

答案 0 :(得分:0)

也许像尤里卡这样的发现中心将解决您的问题。

  • 首先,将docker服务器注册到eureka;
  • 然后,给spring cloud gateway一个eureka配置;
  • 最后,在您的Spring Cloud Gateway应用程序类中设置@EnableDiscoveryClient。

此外,此期的帖子可以为您提供很多帮助:https://github.com/spring-cloud/spring-cloud-gateway/issues/383

答案 1 :(得分:0)

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

因此,换句话说,如果您有两个相同的服务,一个在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

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

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

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

希望这会有所帮助!