简体   繁体   English

STOMP Spring WebSocket 消息超出大小限制

[英]STOMP Spring WebSocket message exceeds size limit

I am implementing Spring WebSocket into our Spring MVC web application.我正在将 Spring WebSocket 实施到我们的 Spring MVC web 应用程序中。 However I am running into message over size limits when I am trying to send a really big message to an endpoint.但是,当我尝试向端点发送一条非常大的消息时,我遇到了超过大小限制的消息。

I am getting the following error:我收到以下错误:

message:The 'content-length' header 68718  exceeds the configured message buffer size limit 65536

14:49:11,506 ERROR [org.springframework.web.socket.messaging.StompSubProtocolHandler] (http-localhost/127.0.0.1:8080-4) Failed to parse TextMessage payload=[13684590},..], byteCount=16384, last=true] in session vlsxdeol. Sending STOMP ERROR to client.: org.springframework.messaging.simp.stomp.StompConversionException: The 'content-length' header 68718  exceeds the configured message buffer size limit 65536
at org.springframework.messaging.simp.stomp.BufferingStompDecoder.checkBufferLimits(BufferingStompDecoder.java:148) [spring-messaging-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.messaging.simp.stomp.BufferingStompDecoder.decode(BufferingStompDecoder.java:124) [spring-messaging-4.1.6.RELEASE.jar:4.1.6.RELEASE]

Here is my configuration:这是我的配置:

@MessageMapping("/user/sockettest" )
@SendTo("/topic/sockettestresult")
public String sockAdd(ListId[] listIds) {
..
SecurityContextHolder.getContext().getAuthentication().getPrincipal();

return stringRet;
}

The xml config looks like the following: xml 配置如下所示:

<websocket:stomp-endpoint path="/user/sockettest">
<websocket:sockjs/>
</websocket:stomp-endpoint>

<websocket:simple-broker prefix="/topic"/>

<websocket:message-converters register-defaults="false">
    <bean id="mappingJackson2MessageConverter" class="org.springframework.messaging.converter.MappingJackson2MessageConverter">
        <property name="objectMapper" ref="objectMapper"></property>
    </bean>
</websocket:message-converters>
</websocket:message-broker>

The client side code looks like this:客户端代码如下所示:

function versionFiles() {
        stompClient.send("/testbrkr/user/sockettest", {}, JSON.stringify(listIds));
    }

Can you let me know what would be a good work-around?你能告诉我什么是好的解决方法吗?

Answer : If you know what would be the maximum size limit答案:如果您知道最大尺寸限制是多少

 <websocket:transport message-size="75536" send-buffer-size="75536"></websocket:transport>

I am looking on how to do partial messaging, will post it here as soon as I find out and get it working我正在研究如何进行部分消息传递,一旦发现并使其正常工作,就会将其发布在这里

Consider <websocket:transport message-size=""/> option for the <websocket:message-broker> definition:考虑<websocket:transport message-size=""/> <websocket:message-broker>定义的<websocket:transport message-size=""/>选项:

Configure the maximum size for an incoming sub-protocol message.配置传入子协议消息的最大大小。 For example a STOMP message may be received as multiple WebSocket messages or multiple HTTP POST requests when SockJS fallback options are in use.例如,当使用 SockJS 回退选项时,STOMP 消息可能会作为多个 WebSocket 消息或多个 HTTP POST 请求接收。

The same can be achieved in annotation configuration using WebSocketMessageBrokerConfigurer.configureWebSocketTransport(WebSocketTransportRegistration) implementation and with the setMessageSizeLimit() on the matter.使用WebSocketMessageBrokerConfigurer.configureWebSocketTransport(WebSocketTransportRegistration)实现和setMessageSizeLimit()在注释配置中可以实现相同的目的。

I was getting similar javascript errorr when the default value of 65kb was set.. then i set it to some random and again got some error like the当设置了 65kb 的默认值时,我得到了类似的 javascript errorr .. 然后我将它设置为一些随机值,并再次得到一些错误,如

connection was interrupted连接中断

. . So tried increasing the time limit and that worked for me.所以尝试增加时间限制,这对我有用。 Actually when the limit exceeds, the messages are sent into packets/or frames, and while it was receiving the response from server, it timed out.实际上,当超过限制时,消息被发送到数据包/或帧中,并且在它从服务器接收响应时,它超时了。

You can use tweak it as below您可以使用如下调整

@EnableWebSocketMessageBroker
public class AppWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
----
---
    @Override
        public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
            registration.setMessageSizeLimit(200000); // default : 64 * 1024
            registration.setSendTimeLimit(20 * 10000); // default : 10 * 10000
            registration.setSendBufferSizeLimit(3* 512 * 1024); // default : 512 * 1024

        }
---
}
        List<Transport> transports = new ArrayList<Transport>();
        WebSocketContainer container = ContainerProvider.getWebSocketContainer();
        container.setDefaultMaxTextMessageBufferSize(512*1024);  //FIX
        WebSocketClient wsClient = new StandardWebSocketClient(container);
        transports.add(new WebSocketTransport(wsClient));
//      transports.add(new RestTemplateXhrTransport());

        SockJsClient sockJsClient = new SockJsClient(transports);
        WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
        stompClient.setMessageConverter(new SimpleMessageConverter());
        stompClient.setInboundMessageSizeLimit(512 * 1024);      //FIX


Lines commented as FIX resolved the issue for me. 行评论为 FIX 为我解决了这个问题。


I've faced the same issue and solved by configuring WebSocketTransportRegistration and ServletServerContainerFactoryBean.我遇到了同样的问题并通过配置 WebSocketTransportRegistration 和 ServletServerContainerFactoryBean 解决了。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/echo").setAllowedOrigins("*");
    }

    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
        registration.setMessageSizeLimit(2048 * 2048);
        registration.setSendBufferSizeLimit(2048 * 2048);
        registration.setSendTimeLimit(2048 * 2048);
    }

    @Bean
    public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
        ServletServerContainerFactoryBean factoryBean = new ServletServerContainerFactoryBean();
        factoryBean.setMaxTextMessageBufferSize(2048 * 2048);
        factoryBean.setMaxBinaryMessageBufferSize(2048 * 2048);
        factoryBean.setMaxSessionIdleTimeout(2048L * 2048L);
        factoryBean.setAsyncSendTimeout(2048L * 2048L);
        return factoryBean;
    }
}

Consider <websocket:transport message-size=""/> option for the <websocket:message-broker> definition:考虑<websocket:transport message-size=""/> <websocket:message-broker>定义的<websocket:transport message-size=""/>选项:

Configure the maximum size for an incoming sub-protocol message.配置传入子协议消息的最大大小。 For example a STOMP message may be received as multiple WebSocket messages or multiple HTTP POST requests when SockJS fallback options are in use.例如,当使用 SockJS 回退选项时,STOMP 消息可能会作为多个 WebSocket 消息或多个 HTTP POST 请求接收。

The same can be achieved in annotation configuration using使用注释配置也可以实现相同的目的

WebSocketMessageBrokerConfigurer.configureWebSocketTransport(WebSocketTransportRegistration) 

implementation and with the setMessageSizeLimit() on the matter.实现并使用setMessageSizeLimit()解决这个问题。

This is right but... If you are using Spring WebSocket then the stomp message is这是正确的,但是...如果您使用的是 Spring WebSocket,那么 stomp 消息是

StompSubProtocolHandler

and

@Override
    public void afterSessionStarted(WebSocketSession session, MessageChannel outputChannel) {
        if (session.getTextMessageSizeLimit() < MINIMUM_WEBSOCKET_MESSAGE_SIZE) {
            session.setTextMessageSizeLimit(MINIMUM_WEBSOCKET_MESSAGE_SIZE);
        }
        this.decoders.put(session.getId(), new BufferingStompDecoder(this.stompDecoder, getMessageSizeLimit()));
    }

so here is the spring bug message size is set as websocket:transport message-size but the WebSocketSession is not ... is 8KB and this method will double it.所以这里的 spring 错误消息大小设置为 websocket:transport message-size 但 WebSocketSession 不是......是 8KB 并且这种方法会使它加倍。 No as the message that we want to send.否作为我们要发送的消息。

I do not know how to fix that;我不知道如何解决; You need to set WebSocketSession TextMessageSizeLimit .您需要设置 WebSocketSession TextMessageSizeLimit Maybe someone how know better spring boot factory knows a spring way to change the WebSocketSession textMessageSizeLimit .也许有人更了解 spring boot factory 知道改变 WebSocketSession textMessageSizeLimit的 spring 方法。 Anyway I did with Aop DelegatingIntroductionInterceptor无论如何,我用 Aop DelegatingIntroductionInterceptor做了

in the WebSocketMessageBrokerConfigurerWebSocketMessageBrokerConfigurer

 @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
        registry.setMessageSizeLimit(50 * 1024 * 1024); //this not work todo
        registry.setSendBufferSizeLimit(50 * 1024 * 1024);
        registry.setDecoratorFactories(agentWebSocketHandlerDecoratorFactory());
    }

  @Bean
        public  AgentWebSocketHandlerDecoratorFactory agentWebSocketHandlerDecoratorFactory() {
        return new AgentWebSocketHandlerDecoratorFactory();
    }

the AgentWebSocketHandlerDecoratorFactory will proxy the WebSocketHandler to a custom DelegatingIntroductionInterceptor AgentWebSocketHandlerDecoratorFactoryWebSocketHandler代理到自定义的DelegatingIntroductionInterceptor

import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;

public class AgentWebSocketHandlerDecoratorFactory implements WebSocketHandlerDecoratorFactory {


    @Override
    public WebSocketHandler decorate(WebSocketHandler handler) {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTargetClass(AopUtils.getTargetClass(handler));
        proxyFactory.setTargetSource(new SingletonTargetSource(handler));
        proxyFactory.addAdvisor(new DefaultIntroductionAdvisor(new SubProtocolWebSocketHandlerInterceptor()));
        proxyFactory.setOptimize(true);
        proxyFactory.setExposeProxy(true);
        return (WebSocketHandler) proxyFactory.getProxy();

    }

}

and the custom DefaultIntroductionAdvisor will intercept the WebSocketHandler afterConnectionEstablished and set WebSocketSession textMessageSizeLimit并且自定义DefaultIntroductionAdvisor将在afterConnectionEstablished拦截WebSocketHandler 并设置WebSocketSession textMessageSizeLimit

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
import org.springframework.web.socket.WebSocketSession;

public class SubProtocolWebSocketHandlerInterceptor extends DelegatingIntroductionInterceptor {

    @Override
    protected Object doProceed(MethodInvocation mi) throws Throwable {
        if(mi.getMethod().getName().equals("afterConnectionEstablished") ) {
            WebSocketSession session = (WebSocketSession) mi.getArguments()[0];
            session.setTextMessageSizeLimit(50*1024*1024);
        }
        return super.doProceed(mi);
    }
}

This is tested and will accept message biger the 16KB in the presented case message limit size is 50 * 1024 * 1024这是经过测试的,将接受大于 16KB 的消息在所呈现的情况下消息限制大小为 50 * 1024 * 1024

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM