一旦队列填满,WebSocket异步发送可能导致阻塞发送

时间:2014-10-08 19:03:41

标签: java websocket jetty

我有一个非常简单的基于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)

1 个答案:

答案 0 :(得分:8)

如果同步发送出现错误消息,则您有多个线程尝试在同一RemoteEndpoint上发送消息 - 这是协议不允许的。一次只能发送一条消息。 (基本上没有同步发送队列)

如果异步发送出现错误消息,那么这意味着您将队列中的消息等待发送,但您仍在尝试编写更多异步消息。

尽量不要同时混合同步和异步(很容易意外地将输出变成无效的协议流)

使用Java Futures:

您需要使用FuturesendBytesByFuture()方法返回时提供的sendStringByFuture()个对象来验证邮件是否实际已发送(可能是一个错误),如果有足够的开始排队,你就会发送更多的消息,直到远程端点赶上来。

此处适用标准Future行为和技巧。

使用Jetty回调:

WriteCallbacksendBytes(ByteBuffer,WriteCallback)方法中还有sendString(String,WriteCallback)行为可以在成功/错误时调用您自己的代码,您可以在其中放置一些逻辑来围绕您发送的内容(限制它,发送它,排队,过滤它,删除一些消息,优先处理消息等等)

使用屏蔽:

或者您可以使用阻止发送来永远不会有太多的消息排队。