阻塞消息挂起 10000 用于阻塞 ..使用 spring websockets

Posted

技术标签:

【中文标题】阻塞消息挂起 10000 用于阻塞 ..使用 spring websockets【英文标题】:Blocking message pending 10000 for BLOCKING..using spring websockets 【发布时间】:2016-03-30 10:14:37 【问题描述】:

我在使用 spring websockets 时遇到以下错误:

用例:在我们的服务器端代码中,我们具有在数据库中搜索值的功能..如果数据库中不存在这些值..它将命中一个 servlet 并获取数据..第二部分即命中servlet和获取数据是异步调用。

所以对于一个请求,我们必须在数据库中搜索多个内容..

示例:在请求中我们得到了一些参数通道:1 此通道映射到多个 id,例如 1 映射到 1,2,3,4,5

在 websocket 中,一旦请求到达服务器,我将提取通道并获取所有 id 的映射并在 id 上运行循环,如下所示:

for(int i=0;i<ids.length;i++)


SomeObject databaseRespObj=callToDatabase(i); //SomeObject contains two fields value exists and string values

if(!databaseRespObj.valuesExists)

AsynchronouscallToServelt(i); 
//once response received it will send message immediately using session



在执行上述服务器端代码时,有时只有我面临以下错误。

java.lang.IllegalStateException: Blocking message pending 10000 for BLOCKING
        at org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint.lockMsg(WebSocketRemoteEndpoint.java:130) ~[websocket-common-9.3.8.v20160314.jar:9.3.8.v20160314]
        at org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint.sendString(WebSocketRemoteEndpoint.java:379) ~[websocket-common-9.3.8.v20160314.jar:9.3.8.v20160314]
        at org.springframework.web.socket.adapter.jetty.JettyWebSocketSession.sendTextMessage(JettyWebSocketSession.java:188) ~[spring-websocket-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.web.socket.adapter.AbstractWebSocketSession.sendMessage(AbstractWebSocketSession.java:105) ~[spring-websocket-4.2.4.RELEASE.jar:4.2.4.RELEASE]

抱歉,如果上述问题的框架不清楚。spring 是否支持像普通 javax websocket 那样发送异步消息 Session.getAsyncRemote().sendText(String text)

spring中使用websocket session发送异步消息的配置是什么

【问题讨论】:

【参考方案1】:

据我了解,当异步技术启动时,您有多个线程在同一个RemoteEndpoint 上发送消息。

看起来和这个很相似:

WebSocket async send can result in blocked send once queue filled

我不认为您必须必须使用上述帖子中描述的期货或机制。 我真正不明白的是:为什么要对 servlet 进行异步调用?当然有几个可以在同一个RemoteEndPoint..上发送消息 但是您不能简单地对相关类进行同步调用,并保持在数据库中找到记录时使用的相同请求-响应流吗? :)

更新

由于您在 cmets 中添加了需要关注速度的事实,并且由于您当前的解决方案似乎不适用,所以让我们从不同的角度来看看这个问题。

我不是 websocket 专家,但据我了解,您尝试通过异步 servlet 调用实现的目标是不可能的。 但是,如果您更改项目的设计/配置,这应该是可以实现的。

就我个人而言,我使用 Websockets 能够向任意用户发送消息,而不一定发出请求 - 只要他连接,他就必须得到消息。

为此,我只需使用 Spring 在其 websocket 支持中提供的 SimpMessagingTemplate 类。要向我想要的任何用户发送消息,我会这样做:

@Autowired
SimpMessagingTemplate smt;

(.......)
smt.convertAndSendToUser(recipient.getUsername(), "/queue/notify", payload);

所以在你的情况下,你可以,在你的循环中

进行类实例方法调用(而不是 servlet,没有网络传输,你不能更快!只需调用你的 biz-logic/service/whatever) 每次方法返回数据时,使用 SimpMessagingTemplate,就像上面的 sn-p 一样 :) 如果您愿意,您仍然可以异步执行! :)

通过这样做,您可以减少延迟(调用 servlet 会增加很多),并拥有可靠的技术。 您可以根据自己的判断轻松快速地向一个用户或多个用户发送数千条消息,而不会遇到“10000 for BLOCKING”问题,该问题可能来自多个“回答相同问题”的 servlet ;)

要从 Spring 获取 SimpMessagingTemplate,您需要使用 &lt;websocket:message-broker&gt; 标记或等效的 non-xml-java-config。

我建议查看此文档,其中包含更多信息: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html

以及我在使用它的 SO 上创建的以下帖子(我在帖子中遇到了另一个问题,与 spring 配置和上下文层次结构有关,但至少你有一些模板代码要查看,代码是工作):

Spring Websocket : receiving nothing from SimpMessagingTemplate

Spring : how to expose SimpMessagingTemplate bean to root context ?

【讨论】:

我们需要快速的响应时间,因为每秒会有多达 2000 个请求...所以不进行同步的 serverlet 调用..所以我们不能进行同步调用 @niilzone..我已经发布了另一个包含完整详细信息的问题..***.com/questions/36318483/… 代码已经被使用(生活在产品中)并且我们没有使用 stom/socket js 任何其他替代方案?最小的配置更改/提取远程端点? 嘿@svsteja,我看了你的另一个问题,但我不能完全自信地回答它:(我不使用相同的集成类等。我赞成它,因为它看起来像一个好问题,希望这将有助于吸引其他贡献者的一些关注!如果你对你的问题“卡住”了,我建议尝试一个只有 websockets 和一个模拟服务的小项目(也许试试 messagebroker ?)来分离关注点并查明问题

以上是关于阻塞消息挂起 10000 用于阻塞 ..使用 spring websockets的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 协程协程的挂起和恢复 ② ( 协程挂起 和 线程阻塞 对比 )

同步异步,阻塞非阻塞,并发并行

同步与异步,阻塞与非阻塞

线程阻塞和挂起(网络收集)

Nginx理论

阻塞非阻塞同步异步