Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring DefaultSubscriptionRegistry无法适应高并发和异常情况_Spring_Stomp_Spring Websocket - Fatal编程技术网

Spring DefaultSubscriptionRegistry无法适应高并发和异常情况

Spring DefaultSubscriptionRegistry无法适应高并发和异常情况,spring,stomp,spring-websocket,Spring,Stomp,Spring Websocket,我使用SpringWebSocket和stomp开发了一个聊天系统。最近发现,有时许多线程(超过400个)在DefaultSubscriptionRegistry$DestinationCache$1被阻塞: "http-nio-8686-exec-41" #3822 daemon prio=5 os_prio=0 tid=0x00007f26bc021000 nid=0x8c7a waiting for monitor entry [0x00007f2837af7000] java.la

我使用SpringWebSocket和stomp开发了一个聊天系统。最近发现,有时许多线程(超过400个)在
DefaultSubscriptionRegistry$DestinationCache$1被阻塞:

"http-nio-8686-exec-41" #3822 daemon prio=5 os_prio=0 tid=0x00007f26bc021000 nid=0x8c7a waiting for monitor entry [0x00007f2837af7000]
   java.lang.Thread.State: BLOCKED (on object monitor)
at org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry$DestinationCache.getSubscriptions(DefaultSubscriptionRegistry.java:269)
    - waiting to lock <0x00000004c6969f98> (a org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry$DestinationCache$1)
    at org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry.findSubscriptionsInternal(DefaultSubscriptionRegistry.java:184)
    at org.springframework.messaging.simp.broker.AbstractSubscriptionRegistry.findSubscriptions(AbstractSubscriptionRegistry.java:116)
    at org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.sendMessageToSubscribers(SimpleBrokerMessageHandler.java:328)
    at org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.handleMessageInternal(SimpleBrokerMessageHandler.java:260)
    at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.handleMessage(AbstractBrokerMessageHandler.java:238)
    at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:135)
    at org.springframework.messaging.support.ExecutorSubscribableChannel.sendInternal(ExecutorSubscribableChannel.java:91)
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:117)
    at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:104)
    at org.springframework.messaging.simp.SimpMessagingTemplate.sendInternal(SimpMessagingTemplate.java:184)
    at org.springframework.messaging.simp.SimpMessagingTemplate.doSend(SimpMessagingTemplate.java:159)
    at org.springframework.messaging.simp.SimpMessagingTemplate.doSend(SimpMessagingTemplate.java:47)
“http-nio-8686-exec-41”#3822守护程序prio=5 os_prio=0 tid=0x00007f26bc02100 nid=0x8c7a等待监视器输入[0x00007f2837af7000]
java.lang.Thread.State:阻塞(在对象监视器上)
位于org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry$DestinationCache.getSubscriptions(DefaultSubscriptionRegistry.java:269)
-等待锁定(org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry$DestinationCache$1)
位于org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry.findSubscriptionsInternal(DefaultSubscriptionRegistry.java:184)
位于org.springframework.messaging.simp.broker.AbstractSubscriptionRegistry.findSubscriptions(AbstractSubscriptionRegistry.java:116)
位于org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.sendMessageToSubscribers(SimpleBrokerMessageHandler.java:328)
位于org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.handleMessageInternal(SimpleBrokerMessageHandler.java:260)
位于org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.handleMessage(AbstractBrokerMessageHandler.java:238)
位于org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:135)
位于org.springframework.messaging.support.ExecutorSubscribableChannel.sendInternal(ExecutorSubscribableChannel.java:91)
位于org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:117)
位于org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:104)
位于org.springframework.messaging.simp.SimpMessagingTemplate.sendInternal(SimpMessagingTemplate.java:184)
位于org.springframework.messaging.simp.SimpMessagingTemplate.doSend(SimpMessagingTemplate.java:159)
位于org.springframework.messaging.simp.SimpMessagingTemplate.doSend(SimpMessagingTemplate.java:47)
我认为
DestinationCache.getSubscriptions
将通过使用
synchronized(this.updateCache)
this.accessCache
中找不到目标而阻塞

某些情况会导致许多线程在此函数上被阻塞

一个是模式目的地,它不在accessCache中

另一种情况是用户和目的地太多,但默认情况下,
cacheLimit=1024
,因此一些将从缓存中删除

另一种情况是网络不好或其他一些事情,这使得许多或所有WebSocket立即断开连接,但消息通过使用
SimpMessageTemplate.convertAndSend
来发送,然后线程将被阻塞在
DestinationCache.getSubscriptions
,因为找不到目的地


我想知道是否有更好的方法避免阻塞?

今天我发现了同样的问题。似乎增加
cacheLimit
是一个好方法

一个是模式目的地

用户可以按模式订阅目的地,但当您向目的地发送消息时,目的地的名称是已知的。 例如,
getSubscriptions(…)
接受不是模式的
destination
参数

因此,再次强调,增加
cacheLimit
应该足以解决线程阻塞问题

不幸的是,在SpringWS-XML配置中,不可能为
简单代理指定
cacheLimit
。可以将以下内容添加到XML中以绕过它:

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler#0" />
    <property name="targetMethod" value="setCacheLimit" />
    <property name="arguments" value="8096"/>
</bean>

使用Ant matcher会导致
同步块中的性能非常差

您应该实现一个自定义的
subscriptionRegistry
,比如
DefaultSubscriptionRegistry
,而不使用Ant Matcher