我有一个非常简单的基于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)
客户在接收数据时没有进行任何计算,因此他们可能无法成为缓慢的加入者。
所以我想知道如何解决这个问题呢? (使用Jetty 9.2.3)
答案 0 :(得分:8)
如果同步发送出现错误消息,则您有多个线程尝试在同一RemoteEndpoint
上发送消息 - 这是协议不允许的。一次只能发送一条消息。 (基本上没有同步发送队列)
如果异步发送出现错误消息,那么这意味着您将队列中的消息等待发送,但您仍在尝试编写更多异步消息。
尽量不要同时混合同步和异步(很容易意外地将输出变成无效的协议流)
使用Java Futures:
您需要使用Future
和sendBytesByFuture()
方法返回时提供的sendStringByFuture()
个对象来验证邮件是否实际已发送(可能是一个错误),如果有足够的开始排队,你就会发送更多的消息,直到远程端点赶上来。
此处适用标准Future
行为和技巧。
使用Jetty回调:
WriteCallback
和sendBytes(ByteBuffer,WriteCallback)
方法中还有sendString(String,WriteCallback)
行为可以在成功/错误时调用您自己的代码,您可以在其中放置一些逻辑来围绕您发送的内容(限制它,发送它,排队,过滤它,删除一些消息,优先处理消息等等)
使用屏蔽:
或者您可以使用阻止发送来永远不会有太多的消息排队。