Spring Websocket服务器在发送大量数据时重置连接

我遇到问题,当尝试从Spring

Websocket服务器(托管在Tomcat上)发送数据时,它似乎在尝试发送消息的过程中重置了连接。发送大量二进制数据(此处的示例中为5526584字节)时,错误似乎发生的更多,但是我已经看到它发生在文本通道上,并且数据较少。但是,发送多于5

MB的内存似乎会使它相对一致地崩溃。

编辑-

结束编辑块下方是服务器端代码和错误。我现在认为该错误是在服务器端引起的。我放入了一些时间戳,在服务器抛出错误之前,客户端似乎收到了onClose错误。接近的原因是缓冲区溢出。这是我设置websocket容器并开始会话的代码:

WebSocketContainer c = ContainerProvider.getWebSocketContainer();

c.setDefaultMaxTextMessageBufferSize(128000000); // Should we enable these on the client?

c.setDefaultMaxBinaryMessageBufferSize(128000000); // Should we enable these on the client?

c.setDefaultMaxSessionIdleTimeout(500000);

c.setAsyncSendTimeout(50000);

session = c.connectToServer(this, config, new URI("wss://" + SERVER + ":" + PORT + WEBSOCKETENDPOINT));

稍后我打印出会话的MaxBuffer大小,并且它们都按预期设置为128000000。

结束编辑

这是堆栈跟踪:

java.io.IOException: An established connection was aborted by the software in your host machine

at sun.nio.ch.SocketDispatcher.write0(Native Method)

at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)

at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)

at sun.nio.ch.IOUtil.write(IOUtil.java:65)

at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)

at org.apache.tomcat.util.net.SecureNioChannel.flush(SecureNioChannel.java:143)

at org.apache.tomcat.util.net.SecureNioChannel.close(SecureNioChannel.java:494)

at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.close(NioEndpoint.java:1201)

at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doClose(WsRemoteEndpointImplServer.java:167)

at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.close(WsRemoteEndpointImplBase.java:710)

at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:599)

at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:480)

at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:313)

at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:258)

at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendPartialBytes(WsRemoteEndpointImplBase.java:161)

at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendBinary(WsRemoteEndpointBasic.java:56)

at org.springframework.web.socket.adapter.standard.StandardWebSocketSession.sendBinaryMessage(StandardWebSocketSession.java:202)

at org.springframework.web.socket.adapter.AbstractWebSocketSession.sendMessage(AbstractWebSocketSession.java:107)

at org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator.tryFlushMessageBuffer(ConcurrentWebSocketSessionDecorator.java:132)

at org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator.sendMessage(ConcurrentWebSocketSessionDecorator.java:104)

at myHandlerpart2.handleBinaryMessage(myHandlerpart2.java:252)

at myHandler.handleMessageFromClient(myHandler.java:200)

at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:307)

at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)

at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)

at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58)

at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleBinaryMessage(StandardWebSocketHandlerAdapter.java:120)

at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$100(StandardWebSocketHandlerAdapter.java:42)

at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$4.onMessage(StandardWebSocketHandlerAdapter.java:87)

at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$4.onMessage(StandardWebSocketHandlerAdapter.java:84)

at org.apache.tomcat.websocket.WsFrameBase.sendMessageBinary(WsFrameBase.java:576)

at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageBinary(WsFrameServer.java:122)

at org.apache.tomcat.websocket.WsFrameBase.processDataBinary(WsFrameBase.java:535)

at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)

at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:127)

at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:73)

at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148)

at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54)

at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53)

at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)

at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

at java.lang.Thread.run(Thread.java:748)

在我的websocket配置器中,我设置了相当宽松的缓冲区和超时

public ServletServerContainerFactoryBean createWebSocketContainer() {

ServletServerContainerFactoryBean container = new

ServletServerContainerFactoryBean();

container.setMaxTextMessageBufferSize(128000000); //128 MB

container.setMaxBinaryMessageBufferSize(128000000); //128 MB

container.setMaxSessionIdleTimeout(500000);

container.setAsyncSendTimeout(50000);

return container;

}

我还为SubProtoclHandler设置了限制

@Override

public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

SubProtocolWebSocketHandler test = new SubProtocolWebSocketHandler(new DirectChannel(), clientInboundChannel());

test.setSendBufferSizeLimit(128000000);

test.setSendTimeLimit(50000);

for(SubProtocolHandler handler : handlers)

{

test.addProtocolHandler(handler);

}

MyWebSocketHandshakeHandler handshaker = new MyWebSocketHandshakeHandler();

handshaker.setSupportedProtocols(test.getSubProtocols().toArray(new String[0]));

registry.addHandler(test, websocketEndpoint).setHandshakeHandler(handshaker)

.addInterceptors(new HttpSessionHandshakeInterceptor()).setAllowedOrigins("*");

}

最终导致错误的实际发送看起来像这样

byte[] tbuf = null;

try {

tbuf = jsonMapper.writeValueAsBytes(demoLists.get(stage));

ByteBuffer buf = ByteBuffer.allocate(tbuf.length);

buf.put(tbuf);

buf.flip();

WebSocketMessage<ByteBuffer> ret = new BinaryMessage(buf);

System.out.println("Binary limit: " + session.getBinaryMessageSizeLimit());

System.out.println("Sending bytes: " + ret.getPayloadLength());

if(session.isOpen()) {

session.sendMessage(ret);

} else {

System.out.println("Session is closed already.");

}

代码中有很多动人之处,因此,如果您需要任何其他信息,请告诉我。

回答:

经过更多研究后,我发现无法将输入缓冲区大小设置为Tyrus客户端,这导致我进入https://tyrus-

project.github.io/documentation/1.12/user-guide.html#d0e1197。显然,在客户端上设置默认缓冲区大小无法正常工作。在添加了指南建议的内容之后,一切都将正常运行。

ClientManager client = ClientManager.createClient(c); 

client.getProperties().put("org.glassfish.tyrus.incomingBufferSize", 128000000);

session = client.connectToServer(this, config, new URI("wss://" + SERVER + ":" + PORT + WEBSOCKETENDPOINT));

以上是 Spring Websocket服务器在发送大量数据时重置连接 的全部内容, 来源链接: utcz.com/qa/435223.html

回到顶部