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

时间:2016-09-12 09:35:51

标签: java spring spring-mvc websocket spring-websocket

我得到了一个spring websocket服务器(基于Jetty和spring版本4.3.2.RELEASE)和客户端的负载测试设置,它可以生成许多连接(基于spring的示例java websocket客户端)。下面的代码将数据发送到给定的websocket会话:该代码段利用了可以使用sessionId而不是用户ID(Spring WebSocket @SendToSession: send message to specific session)的情况。我可能经常每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());

}

当这段代码非常频繁地(每2-3毫秒)执行~100次会话时,我在日志中看到它已经运行并调用了convertAndSendToUser,其中一些会话赢了收到消息。我很欣赏有关如何清除这些问题的任何建议。

1 个答案:

答案 0 :(得分:0)

好吧,我认为你的问题在于:

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

它将此配置用于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时,任何额外的消息都会被中止。

要解决此问题,您应该实施WebSocketMessageBrokerConfigurer并覆盖其configureClientOutboundChannel()以提供一些自定义taskExecutor(ThreadPoolTaskExecutor taskExecutor),例如new ThreadPoolExecutor.CallerRunsPolicy()