我有一个非常简单的基于Jetty的websockets服务器,负责流式传输小二进制消息以连接客户端。
为了避免服务器端的任何阻塞,我使用了sendBytesByFuture方法。
在将负载从2个客户端增加到20个之后,它们停止接收任何数据。在故障排除过程中,我决定打开同步发送方法,最终得到了潜在的原因:
java.lang.IllegalStateException: Blocking message pending 10000 for BLOCKING
at org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint.lockMsg(WebSocketRemoteEndpoint.java:130)
at org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint.sendBytes(WebSocketRemoteEndpoint.java:244)
客户端在接收数据时不进行任何计算,因此可能不会成为缓慢的加入者。
所以我想知道我能做些什么来解决这个问题?(使用码头9.2.3)
如果错误消息来自同步发送,则有多个线程试图在同一个RemoteEndpoint
上发送消息,这是协议不允许的。一次只能发送一条消息。(基本上没有同步发送的队列)
如果错误消息来自异步发送,那么这意味着您有消息在队列中等待发送,但您仍在尝试写入更多异步消息。
尽量不要同时混合同步和异步(很容易意外地将输出变成无效的协议流)
使用Java期货:
您将希望使用sendBytesByFuture()
和sendStringByFuture()
方法返回时提供的Future
对象来验证消息是否已实际发送(可能是错误),如果有足够多的开始排队未发送,您将停止发送更多消息,直到远程端点能够赶上为止。
标准的Future
行为和技术适用于此。
使用Jetty回调:
sendBytes(ByteBuffer,WriteCallback)
和sendString(String,WriteCallback)
方法中也有WriteCallback
行为,它们会在成功/错误时调用您自己的代码,在这种情况下,您可以围绕发送的内容设置一些逻辑(限制、发送速度较慢、排队、过滤、丢弃一些消息、排定消息优先级等,无论您需要什么)
使用阻塞:
或者,您可以使用阻塞发送来避免太多的消息排队。