Java 为多个用户优化rest执行的异步操作

Java 为多个用户优化rest执行的异步操作,java,spring,java-8,java-threads,completable-future,Java,Spring,Java 8,Java Threads,Completable Future,在下面的代码中,我有一个异步方法,由经过身份验证的用户通过rest执行。在这个方法中,我执行循环,在循环中定期检查新数据的缓存 @Async public CompletableFuture<List<Data>> pollData(Long previousMessageId, Long userId) throws InterruptedException { // check db at first, if there are new data no nee

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

@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);
}
我为每个请求在单独的线程中执行此检查,因为每个用户的数据都不同

我需要为许多用户(大约10000个活跃用户)优化此代码。在当前状态下,它不能很好地工作,因为在有更多请求的地方,这些请求正在等待一些新的空闲线程,并且每一个请求都需要很长的时间(例如,5分钟而不是100秒)


你能帮我改进一下吗?感谢您的建议。

如果没有其他并发调用pollData方法,则最多需要~100秒

参数maxPoolSize定义可以并发运行@Asynch方法的最大线程数

So(用户数*执行时间)/线程数=10K*100/2=500K[s]

我还没有完全理解您希望通过此方法达到的目标,但我建议您检查此功能的设计

(例如,看看spring缓存,@execute,…)


(注意,如果您有多个@async,您可以通过将名称添加到注释@Bean(“Pool1”)和@Asynch(“Pool1”)中,将池配置与@Asynch方法绑定。)

如果没有其他并发调用pollData方法,则最多需要~100秒

参数maxPoolSize定义可以并发运行@Asynch方法的最大线程数

So(用户数*执行时间)/线程数=10K*100/2=500K[s]

我还没有完全理解您希望通过此方法达到的目标,但我建议您检查此功能的设计

(例如,看看spring缓存,@execute,…)


(注意,如果您有多个@async,您可以通过将名称添加到注释@Bean(“Pool1”)和@Asynch(“Pool1”)中,将池配置与@Asynch方法绑定。)

我不完全理解您想要做什么。 但我认为很明显,它很快就会填满你的思路

我认为您应该尝试使用MessageBroker或类似的工具

不要试图通过等待新的附加来响应请求,您应该使用AMQP、WebSocket、Webhook来连接您的客户机。。。等在服务器上,当您检测到新信息时,会通知您的客户机


因此,您不需要占用客户端的一个线程。

我不完全理解您想要做什么。 但我认为很明显,它很快就会填满你的思路

我认为您应该尝试使用MessageBroker或类似的工具

不要试图通过等待新的附加来响应请求,您应该使用AMQP、WebSocket、Webhook来连接您的客户机。。。等在服务器上,当您检测到新信息时,会通知您的客户机


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

目标是“立即”对新数据做出反应。因此,当一个用户调用pollData时,他的请求正在等待新数据,当另一个用户在他的请求中发送数据时,有关数据库中新数据的通知保存在缓存中。这就是我在循环中检查它的原因。我在多线程方面不是很好,所以我会很感激具体的回答,例如我应该改变什么。考虑不发送轮询就发送新数据的通知。当用户发送数据时,您检索所有正在侦听/等待这些数据的用户,并通知他们。但是,我应该使用哪种技术进行通知?我们正在考虑rest,它与防火墙和旧浏览器没有问题。WebSocket是我们最后的选择。目标是“立即”对新数据做出反应。因此,当一个用户调用pollData时,他的请求正在等待新数据,当另一个用户在他的请求中发送数据时,有关数据库中新数据的通知保存在缓存中。这就是我在循环中检查它的原因。我在多线程方面不是很好,所以我会很感激具体的回答,例如我应该改变什么。考虑不发送轮询就发送新数据的通知。当用户发送数据时,您检索所有正在侦听/等待这些数据的用户,并通知他们。但是,我应该使用哪种技术进行通知?我们正在考虑rest,它与防火墙和旧浏览器没有问题。WebSocket是我们最后的选择。但我有相同的答案告诉你们我应该使用哪种技术来发送通知?我们正在考虑rest,它与防火墙和旧浏览器没有问题。WebSocket是我们最后的选择。对于AMQP,我没有任何经验,所以我应该了解它,您能否提供示例,说明is应该如何与客户端一起工作?对于AMQP,您可以使用ApachePAHO作为浏览器客户端。对于websocket,您可以使用支持旧客户端长轮询(http)的SpringWebSocket。Webhook不适用于浏览器客户端。您仍然可以简单地进行轮询。每个客户端每5秒钟发送一次请求,服务器立即响应,没有线程。睡眠。我不能准确地告诉你使用哪种技术。有几种技术适用于您的用例。对于MessageBroker,有SpringWebSocket、rabbitMQ、activeMQ、kafka。。。等等,大家好,所以我们决定使用WebSocket进行交流。我们考虑以下孤独:websocket频道将只提供通知,因此当一些用户通过post rest发送新数据时,通知将通过websocket发送给收件人,这会导致这些客户端创建get请求。您能告诉我您对该解决方案的看法吗?我认为该解决方案会起作用。但是我认为在通知中设置数据比发出GET请求更容易。这是一个不太容易实现的Web服务。但我有相同的答案,我应该使用哪种技术来实现该通知?我们正在考虑rest,它与防火墙和旧浏览器没有问题。韦伯斯托克
@Bean
public Executor asyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(2);
    executor.setQueueCapacity(500);
    executor.initialize();
    return executor;
}