当前位置: 首页 > 知识库问答 >
问题:

频繁发送到spring websocket会话:在传输过程中丢失

范玄裳
2023-03-14

我得到了一个SpringwebSocket服务器的负载测试设置(基于Jetty和Spring版本4.3.2。RELEASE)和客户端,生成许多连接(基于Spring的示例java webSocket客户端)。下面的代码将数据发送到给定的webSocket会话:代码段利用了可以使用sesionId而不是User ID的情况(Spring WebSocket@SendTo会话:将消息发送到特定会话)。我可能会非常频繁地执行这段代码,每2-3毫秒执行一次。我使用SimpleMessageBroker。

 public void publishToSessionUsingTopic(String sessionId, String subscriptionTopic, Map<String, CacheRowModel> payload) {

        String subscriptionTopicWithoutUser = subscriptionTopic.replace(USER_ENDPOINT, "");
        // necessary message headers for per-session send
        SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
        headerAccessor.setSessionId(sessionId);
        headerAccessor.setLeaveMutable(true);          
        simpMessagingTemplate.convertAndSendToUser(sessionId, subscriptionTopicWithoutUser, Collections.singletonList(payload), headerAccessor.getMessageHeaders());

}

当这段代码在大约100个会话中非常频繁地执行(每2-3毫秒)时,虽然我在日志中看到它被运行并被称为转换器和SendToUser,但有些会话不会收到消息。我感谢任何关于如何清理这一问题的建议。

共有1个答案

曾德水
2023-03-14

我认为你的问题在于:

@Bean
public ThreadPoolTaskExecutor clientOutboundChannelExecutor() {
    TaskExecutorRegistration reg = getClientOutboundChannelRegistration().getOrCreateTaskExecRegistration();
    ThreadPoolTaskExecutor executor = reg.getTaskExecutor();
    executor.setThreadNamePrefix("clientOutboundChannel-");
    return executor;
}

其中,它将此配置用于执行器

protected ThreadPoolTaskExecutor getTaskExecutor() {
    ThreadPoolTaskExecutor executor = (this.taskExecutor != null ? this.taskExecutor : new ThreadPoolTaskExecutor());
    executor.setCorePoolSize(this.corePoolSize);
    executor.setMaxPoolSize(this.maxPoolSize);
    executor.setKeepAliveSeconds(this.keepAliveSeconds);
    executor.setQueueCapacity(this.queueCapacity);
    executor.setAllowCoreThreadTimeOut(true);
    return executor;
}

请参阅,未配置RejectedExecutionHandler。默认情况下,它类似于:

private RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();

因此,当您有足够多的消息和任务超过ThreadPool时,任何额外的消息和任务都将被中止。

要解决此问题,您应该实现websocketmessagebrokerconfigure并覆盖其configureClientOutboundChannel(),以提供一些自定义任务执行器(ThreadPoolTaskExecutor taskExecutor),例如使用新的ThreadPoolExecutor。CallerRunPolicy()

 类似资料:
  • 问题内容: 我有一个与该线程中的问题相似的问题,即使不完全相同: 仅在GoogleChrome和URL重写中随机丢失会话变量 但是该线程中的所有解决方案都不适合我。我的PHP / MySQL应用程序中只有Google Chrome出现了奇怪的行为。如果我在Firefox上尝试过,它可以工作,但Chrome不能。 我导航到购物车中的某个位置,并在代码中的多个位置存储会话数据。不用担心我开始会议或与此

  • 有没有办法通过耳机传送麦克风输入,同时通过智能手机扬声器使用音频输出? 我已经看了几个小时了,我看到这在iOS上显然是不可能的,但是Android呢... 我用的是三星Galaxy S4。 这是我的代码的一部分,即使耳机已插入,也可以通过扬声器路由音频输出: 但当我试图通过耳机的麦克风控制我的应用程序时,什么都没有。所以我试着用智能手机的那一个,它显然起作用了。 它看起来不像其他AudioMana

  • 在发布这个问题之前,我谷歌了很多这个问题,并且在网络Socket@ServerEndpoint中从HttpServletRequest访问Http会话是我能找到的最好的问题/答案之一,但它似乎不能解决我的问题。 我可以通过这种方式从websocket访问HttpSession,但是我无法访问与普通HTTP请求相同的CDI会话bean实例。 我也尝试在会话中存储Weld实例,并尝试在WebSocke

  • TLDR:我如何使用从后台发送的数据初始化我的对话,并在与用户的整个对话中使用这些信息? 使用Microsoft botbuilder,提供了一种“反向通道”机制,我可以通过它向bot发送数据,也可以从bot发送数据。 与此答案类似,我正在使用backchannel方法向bot发送conversationStarted事件,以便按照您的预期启动对话。 收到事件后,我启动一个对话框,向用户发送主动消

  • 问题内容: 我已按照以下指示在Google App Engine应用程序中配置了JSF 2.1: https://sites.google.com/a/wildstartech.com/adventures-in-java/Java-Platform- Enterprise-Edition/JavaServer-Faces/javaserver-faces-21/configuring- java