我得到了一个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,其中一些会话赢了收到消息。我很欣赏有关如何清除这些问题的任何建议。
答案 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()
。