在下面的代码中我有异步方法,由经过身份验证的用户执行休息。在这个方法中,我执行循环,其中定期检查新数据的缓存。
@Async
public CompletableFuture<List<Data>> pollData(Long previousMessageId, Long userId) throws InterruptedException {
// check db at first, if there are new data no need go to loop and waiting
List<Data> data = dataRepository.findByLastAndByUser(dataId, userId));
data not found so jump to loop for some time
if (data.size() == 0) {
short c = 0;
while (c < 100) {
// check if some new data added or not, if yes break loop
if (cache.getIfPresent(userId) != null) {
break;
}
c++;
Thread.sleep(1000);
System.out.println("SEQUENCE: " + c + " in " + Thread.currentThread().getName());
}
// check database on the end of loop or after break from loop
data = dataRepository.findByLastAndByUser(dataId, userId);
}
// clear data for that recipient and return result
cache.clear(userId);
return CompletableFuture.completedFuture(data);
}
和executor bean:
@Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.initialize();
return executor;
}
我在每个请求的单独线程中执行此检查,因为每个用户的这些数据都不同。
我需要为许多用户(大约10k活跃用户)优化此代码。在当前状态下,它不能很好地工作,因为在有更多请求的情况下,这些请求正在等待一些新的自由线程,并且每隔一个请求需要很长时间(例如5分钟而不是100秒)。
你可以帮我改进吗?谢谢你的建议。答案 0 :(得分:1)
如果没有对pollData方法的其他并发调用,则最多需要约100秒。
参数maxPoolSize定义了可以同时运行@Asynch方法的最大线程数。
所以(用户数量*执行时间)/线程数= 10K * 100/2 = 500K [s]。
我还没有完全理解您希望使用此方法达到的目标,但我建议您查看此功能的设计。
(例如,看一下spring cache,@ _evict,...)
(请注意,如果您有多个@async,可以通过将名称添加到注释@Bean(&#34; Pool1&#34;)和@Asynch(&)来将池配置与@Asynch方法绑定。 #34;库1&#34))
。答案 1 :(得分:1)
我不完全明白你想做什么。 但我认为很快就会填补你的线索。
我认为您应该尝试使用消息代理或类似的东西。
您不应该尝试通过等待新的追加来响应请求,而应该使用AMQP,WebSocket,Webhook等连接您的客户端......在您的服务器上,当您检测到新信息时,您会通知您的客户。 / p>
所以你不需要占用客户端的一个线程。