gpt4 book ai didi

java - 将线程保持在 Spring 休息请求中以进行长轮询

转载 作者:行者123 更新时间:2023-12-02 11:21:40 25 4
gpt4 key购买 nike

正如我在标题中所写,我们需要在项目中通知或执行另一个线程的某个线程的方法。此实现是长轮询的一部分。在下面的文字中描述并展示我的实现。

所以要求是:
当 UserX 收到先前的响应时,立即从客户端向服务器发送请求(轮询操作)。在服务中执行 spring 异步方法,其中线程立即检查缓存中是否有数据库中的一些新数据。我知道缓存通常用于特定输入期望特定输出的方法。情况并非如此,因为我使用缓存来减少数据库调用,并且我的方法的输出总是不同的。因此,如果我应该检查数据库或不检查数据库,缓存可以帮助我存储通知。此检查在 while 循环中运行,当线程找到在缓存中读取数据库的通知或时间到期时,该检查结束。

假设 UserX 线程(轮询操作)当前处于 while 循环并检查缓存。

在那一刻,UserY(推送操作)向服务器发送一些数据,数据在单独的线程中存储在数据库中,并且在缓存中存储接收者的 userId。

因此,当 UserX 检查缓存时,他找到了收件人的 id(在本例中,收件人的 id == 他的 id),然后中断循环并获取这些数据。

因此,在我的实现中,我使用谷歌 Guava 缓存,它提供手动写入。

private static Cache<Long, Long> cache = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();

在创建方法中,我存储应该读取这些数据的用户 ID。

public void create(Data data) {
dataRepository.save(data);
cache.save(data.getRecipient(), null);
System.out.println("SAVED " + userId + " in " + Thread.currentThread().getName());
}

这是轮询数据的方法:

@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 = findRecent(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 = findRecent(dataId, userId);
}

// clear data for that recipient and return result
cache.clear(userId);
return CompletableFuture.completedFuture(data);
}

用户X得到响应后,他再次发送轮询请求,并重复整个过程。

你能告诉我这个在java(spring)中进行长轮询的应用程序设计是否正确或者是否存在更好的方法?关键是当用户调用 poll 请求时,该请求应该为新数据保留一段时间,而不是立即响应。我上面展示的这个解决方案有效,但问题是它是否也适用于许多用户(1000+)。我担心这个问题,因为当池中没有可用线程时,暂停线程会使另一个请求变慢。感谢您的努力的建议。

最佳答案

检查 Web 套接字。 Spring 从版本 4 开始支持它。它不需要客户端发起轮询,而是服务器将数据实时推送给客户端。

检查以下内容:

https://spring.io/guides/gs/messaging-stomp-websocket/

http://www.baeldung.com/websockets-spring

注意 - Web 套接字在客户端和服务器之间打开持久连接,因此在大量用户的情况下可能会导致更多的资源使用。因此,如果您不需要实时更新并且可以接受一些延迟,那么轮询可能是更好的方法。此外,并非所有浏览器都支持 Web 套接字。

Web Sockets vs Interval Polling

Longpolling vs Websockets

In what situations would AJAX long/short polling be preferred over HTML5 WebSockets?

在您当前的方法中,如果您担心服务器上为多个用户运行大量线程,那么您可以每次都从前端触发轮询。这样,只有短暂的请求线程才会从 UI 中触发,以查找缓存中的任何更新。如果有更新,可以再次调用来检索数据。但是,不要像现在这样每隔一秒就访问一次服务器,否则 CPU 利用率将会很高,并且用户请求线程也可能会受到影响。您应该对时间进行一些优化。

您可以通过分析一段时间内缓存/数据库更新的模式来应用智能算法,而不是在延迟 1 秒后命中缓存 100 次。

通过了解该模式,您可以以指数退避方式触发轮询,以便在最有可能预期更新时命中缓存。这样您就会减少访问缓存的频率,并且更加准确。

关于java - 将线程保持在 Spring 休息请求中以进行长轮询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49878958/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com