为许多用户优化休息执行的异步操作

时间:2018-04-18 09:59:45

标签: java spring java-8 java-threads completable-future

在下面的代码中我有异步方法,由经过身份验证的用户执行休息。在这个方法中,我执行循环,其中定期检查新数据的缓存。

@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秒)。

你可以帮我改进吗?谢谢你的建议。

2 个答案:

答案 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>

所以你不需要占用客户端的一个线程。