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

Rod*_*eas 6 netty spring-boot 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]
Run Code Online (Sandbox Code Playgroud)

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

网关中的路由如下所示:

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

我正在路由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)

And*_*ete 5

如何在spring-boot中配置嵌入式Netty以不具有内容长度限制?

目前还不可能.请参阅reactor-netty#223Spring Framework#16228.


分析:

事实证明,Netty显然具有最大内容长度

限制来自reactor-netty,而不是直接来自Netty.

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

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

HttpServerWSOperations最终方法使用HttpServerOperations.withWebsocketSupport它并直接实例化,因此您无法更改实现.


小智 3

现在可以使用以下 bom:

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

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

spring.cloud.gateway.httpclient.websocket.max-frame-payload-length: <bytes_new_limit>
Run Code Online (Sandbox Code Playgroud)

我为此苦苦挣扎了一段时间,我的 Spring Boot 处于“2.1.10.RELEASE”状态。他们在新版本的 webflux 中修复了这个问题,该版本附带了这些托管依赖项。