增加或删除Spring-Boot嵌入式Netty中的内容长度限制

时间:2018-06-22 23:11:55

标签: spring-boot netty spring-cloud-gateway

我将Spring Cloud Gateway置于某些现有微服务的前面。它通常可以正常工作,但是我有一个websocket(SockJS)连接,该连接(显然)可以传输大量数据。

事实证明Netty显然具有最大内容长度-当我在SockJS路由中超过该限制时,会出现此错误:

2018-06-22 16:47:58.740 ERROR 11164 --- [ctor-http-nio-5] r.ipc.netty.channel.ContextHandler       : Error cannot be forwarded to user-facing Mono

io.netty.handler.codec.TooLongFrameException: content length exceeded 65536 bytes.
    at io.netty.handler.codec.MessageAggregator.handleOversizedMessage(MessageAggregator.java:399) [netty-codec-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.handler.codec.MessageAggregator.invokeHandleOversizedMessage(MessageAggregator.java:383) [netty-codec-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.handler.codec.MessageAggregator.decode(MessageAggregator.java:277) [netty-codec-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:88) [netty-codec-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310) [netty-codec-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284) [netty-codec-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459) [netty-transport-4.1.24.Final.jar:4.1.24.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) [netty-common-4.1.24.Final.jar:4.1.24.Final]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]

如何在spring-boot中将嵌入式Netty配置为没有内容长度限制?我无法控制响应中返回的消息的长度。

网关中的路由如下:

- id: check_status_sockjs
  uri: http://foo.example.com:8080
  predicates:
    - Path=/foo/status/**
  filters:
    - RewritePath=/foo/status/(?<segment>.*), /status/$\{segment}

我将sockJS请求路由到另一端的服务也是Spring-Boot应用程序,它是作为战争部署在Tomcat 8.5服务器中的。当我直接与支持服务进行交互时,这种内容长度的东西不会遇到任何问题-仅当我尝试通过网关应用程序中的嵌入式Netty路由时。

我还成功通过这条路由发送和接收了较小的消息-只有当我达到此明显的长度限制时,它才会爆炸。

我在网关中的依赖项是:

  • spring-cloud-starter-gateway(2.0.0.RELEASE)
  • spring-boot-starter-webflux(2.0.2.RELEASE)
  • spring-boot-starter-actuator(2.0.2.RELEASE)

2 个答案:

答案 0 :(得分:5)

  

如何在spring-boot中将嵌入式Netty配置为没有内容长度限制?

当前不可能。 参见reactor-netty #223Spring Framework #16228


分析:

  

事实证明Netty的内容长度显然最大

限制来自Netty,而不直接来自WebsocketInbound

限制来自reactor. ... .WebsocketInbound,这是一个Java接口,每帧最多可聚合65,536字节

我只能找到一个实现HttpServerWSOperations的类:WebsocketInbound.aggregateFrames。此类不会更改默认方法HttpServerWSOperations,因此保留了65k字节的限制。

HttpServerOperations.withWebsocketSupport final 方法ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.EntitySet<Product>("Product"); builder.EntityType<Product>().Function("Users").Returns<Users>(); builder.EntityType<Product>().Function("Companies").Returns<Companies>(); app.UseMvc(routebuilder => { routebuilder.MapODataServiceRoute( "OData", "odata", GetEdmModel()); routebuilder.EnableDependencyInjection(); } 使用,并且直接实例化,因此您不能更改实现。

答案 1 :(得分:1)

现在可以使用以下物料:

dependencyManagement {
  imports {
    mavenBom("org.springframework.boot:spring-boot-dependencies:2.2.2.RELEASE")
    mavenBom("org.springframework.cloud:spring-cloud-dependencies:Hoxton.RELEASE") 
  }
}

然后在网关应用程序配置中可以设置:

spring.cloud.gateway.httpclient.websocket.max-frame-payload-length: <bytes_new_limit>

我为此苦了一段时间,我的弹簧靴在'2.1.10.RELEASE'上。他们在这些托管依赖项随附的新版webflux中对其进行了修复。