Увеличьте или удалите ограничения длины содержимого во встроенной Netty Spring-Boot

Я устанавливаю Spring Cloud Gateway перед некоторыми существующими микросервисами. В основном это работает, но у меня есть соединение с веб-сокетом (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]

Как мне настроить встроенную Netty в spring -boot, чтобы не было ограничения на длину содержимого? Я не могу контролировать длину сообщения, возвращаемого в ответе.

Маршрут в шлюзе выглядит так:

- 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 в моем приложении шлюза.

Я также успешно отправляю и получаю сообщения меньшего размера по этому маршруту - только когда я достигаю этого видимого предела длины, он взрывается.

Мои зависимости в шлюзе следующие:

  • весна-облако-стартер-шлюз (2.0.0.RELEASE)
  • весна-загрузка-стартер-webflux (2.0.2.RELEASE)
  • пружина-пыльник-пускатель-привод (2.0.2.RELEASE)

person Roddy of the Frozen Peas    schedule 22.06.2018    source источник
comment
Вы пробовали -Dhttp.netty.maxInitialLineLength? См. github.com/playframework/playframework/issues/5036, stackoverflow.com / questions / 43813715 / и stackoverflow.com/questions/29189713/   -  person Tarun Lalwani    schedule 28.06.2018
comment
Я не получаю исключения по поводу длины заголовка .... Мое исключение связано с длиной содержимого.   -  person Roddy of the Frozen Peas    schedule 28.06.2018


Ответы (2)


Теперь можно использовать следующие бомбы:

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, которая поставляется с этими управляемыми зависимостями.

person jwj    schedule 16.12.2019

Как мне настроить встроенную Netty в Spring-boot, чтобы не было ограничения на длину содержимого?

В настоящее время это невозможно. См. Reaction-netty # 223 и Spring Framework # 16228.


Анализ:

Оказывается, у Netty, по-видимому, есть максимальная длина контента.

Ограничение исходит от reactor-netty, а не напрямую от Netty.

Предел исходит от reactor. ... .WebsocketInbound, a Интерфейс Java, который объединяет до 65 536 байт на кадр.

Я смог найти только один класс, реализующий WebsocketInbound: HttpServerWSOperations. Этот класс не изменяет метод по умолчанию WebsocketInbound.aggregateFrames, поэтому остается ограничение в 65 КБ.

HttpServerWSOperations используется final методом HttpServerOperations.withWebsocketSupport и создается напрямую, поэтому вы не можете изменить реализацию.

person Andrei Damian-Fekete    schedule 04.07.2018
comment
Я этого боялся. Правильно ли я понимаю, что это ограничение только для веб-сокетов? - person Roddy of the Frozen Peas; 04.07.2018