Stomp spring web socket消息超出大小限制

时间:2015-12-17 19:59:33

标签: java stomp spring-websocket sockjs spring-web

我正在将spring web-socket实现到我们的spring mvc web应用程序中。但是,当我尝试向端点发送一个非常大的消息时,我遇到了超过大小限制的消息。

我收到以下错误,

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]

这是我的配置

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

return stringRet;
}

xml配置如下所示               

<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>

客户端代码如下所示

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

你能让我知道什么是好的解决方法。

答案:如果你知道什么是最大尺寸限制

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

我正在研究如何进行部分消息传递,我会在发现并将其发布后立即在此处发布

4 个答案:

答案 0 :(得分:4)

考虑<websocket:transport message-size=""/>定义的<websocket:message-broker>选项:

  

配置传入子协议消息的最大大小。       例如,STOMP消息可以作为多个WebSocket消息被接收       或者在使用SockJS后备选项时发出多个HTTP POST请求。

使用WebSocketMessageBrokerConfigurer.configureWebSocketTransport(WebSocketTransportRegistration)实施的注释配置和关于此事的setMessageSizeLimit()可以实现相同的目标。

答案 1 :(得分:1)

        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


当FIX为我解决了该问题时,出现了行注释。


答案 2 :(得分:0)

设置默认值65kb时,我收到了类似的JavaScript错误消息。然后将其设置为随机值,并再次出现诸如

的错误
  

连接被中断

。所以尝试增加时间限制,这对我有用。实际上,当超出限制时,邮件将被发送到数据包/或帧中,并且在接收到来自服务器的响应时会超时。

您可以按以下方式进行调整

@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

        }
---
}

答案 3 :(得分:0)

考虑 <websocket:transport message-size=""/> 定义的 <websocket:message-broker> 选项:

配置传入子协议消息的最大大小。例如,当使用 SockJS 回退选项时,STOMP 消息可能会作为多个 WebSocket 消息或多个 HTTP POST 请求接收。

在注解配置中也可以使用

WebSocketMessageBrokerConfigurer.configureWebSocketTransport(WebSocketTransportRegistration) 

实施并与 setMessageSizeLimit() 一起讨论此事。

这是对的,但是...如果您使用的是 Spring WebSocket,那么 stomp 消息是

StompSubProtocolHandler

@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()));
    }

所以这里的 spring 错误消息大小设置为 websocket:transport message-size 但 WebSocketSession 不是 ... 是 8KB,这个方法会加倍。否作为我们要发送的消息。

我不知道如何解决这个问题;您需要设置 WebSocketSession TextMessageSizeLimit。也许有人更了解 spring boot factory 知道改变 WebSocketSession textMessageSizeLimit 的 spring 方法。 反正我是用 Aop DelegatingIntroductionInterceptor

WebSocketMessageBrokerConfigurer

 @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();
    }

AgentWebSocketHandlerDecoratorFactory 会将 WebSocketHandler 代理到自定义 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();

    }

}

和自定义 DefaultIntroductionAdvisor 将拦截 WebSocketHandler afterConnectionEstablished 并设置 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);
    }
}

这是经过测试的,将接受大于 16KB 的消息 在呈现的情况下,消息限制大小为 50 * 1024 * 1024