在Spring-Websockets 4.2中,使用SockJS时出现部分消息。

24

我正在使用Spring-Websockets 4.2和SockJS。

由于客户端接收的消息可能相当大,因此我想使用部分消息。我的TextWebSocketHandler子类确实覆盖了supportsPartialMessages以返回true。但是,由Spring创建的SockJsWebSocketHandler不支持部分消息,因此我仍然会收到错误code=1009, reason=The decoded text message was too big for the output buffer and the endpoint does not support partial messages

作为一种解决方法,我增加了缓冲区大小到1 MB,如此处所述,但由于我必须同时支持相当大数量的客户端(~2000),这需要太多的内存。

是否有办法在SockJS中使用部分消息?


你能解决这个问题吗?我也遇到了同样的问题,但一直没有找到解决方案。另外,在 container.setMaxTextMessageBufferSize(16384) 中提到的数字是以什么为单位的?比特、字节、千字节还是其他? - BiJ
不幸的是,我们最终不得不自己实现部分消息传递,通过在发送者处进行分块,在接收者处重新组装。 据我所知,setMaxTextMessageBufferSize以字节为单位。 - Jan
你可以使用类似于粘性会话的负载均衡器来分发消息吗?这听起来几乎像是你需要实现一个反应式流或者使用一个适当的扩展消息队列,而不是使用常规套接字来处理你的消息。 - Dr.Knowitall
@Jan你能分享一些关于这个的细节吗?你使用了WebSocketHandlerDecorator或者是更高级的应用层次的东西吗?客户端呢? - Michiel Haisma
我已经无法访问代码了,但如果我记得正确的话,最终我处理了所有应用层的内容。类似于将整个消息包装在JSON对象中,手动将其分成1MB的块,然后在接收方缓冲区中缓冲,直到最后一个“}”到达。 - Jan
1个回答

1
在我的情况下,我的Tomcat服务器与TextWebSocketHandler一起使用。
在执行此操作之前,您需要检查此内容:supportsPartialMessages
首先,请按如下所示重写supportsPartialMessages()
//This value set as true in my properties file. Just for test. actually you don't need this.
@Value("#{config['server.supportsPartialMessages']}")
private boolean supportsPartialMessages;

//If you need to handle partial message, should return true.
@Override
public boolean supportsPartialMessages() {
    return supportsPartialMessages;     
}

当连接建立时,我会为每个 WebSocket 会话添加“messageRoom”属性,以存储部分消息。
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    super.afterConnectionEstablished(session);

    //I think this is easier to keep each message and each client.
    session.getAttributes().put("messageRoom", new StringBuilder(session.getTextMessageSizeLimit()));
}

当您收到客户端的消息时,请执行以下操作。
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
    super.handleTextMessage(session, message);

    StringBuilder sbTemp = (StringBuilder)session.getAttributes().get("messageRoom");

    //isLast() will tell you this is last chunk or not.
    if(message.isLast() == false) {     
        sbTemp.append(Payload);

    }else {
        if(sbTemp.length() != 0) {          
            sbTemp.append(Payload);     

            this.logger.info(session.getRemoteAddress() + ":RECEIVE_TO[CLIENT][PARTIAL][" + sbTemp.length() + "]:" + sbTemp.toString());
            doYourWork(session, sbTemp.toString());
            //Release memory would be nice.
            sbTemp.setLength(0);
            sbTemp.trimToSize();

        }else {         
            this.logger.info(session.getRemoteAddress() + ":RECEIVE_TO[CLIENT][WHOLE]:" + message.getPayload());
            doYourWork(session, Payload);
        }
    }
}

这是几年前完成的,所以我记不得从哪里得到的。 但我仍然对他们表示感激。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接