问候SO社区! 我有一个基于REST,运动衫的应用程序。此应用程序(由于其客户端的性质)在大致相同的时间(相隔约2-5秒)接收相同的http请求(其中3-6个)。 每个请求大约需要10秒来处理并带回大量数据(点击数据库,进行数据按摩等)。 在一个理想的世界中,我希望避免多次处理相同的请求,并考虑编写某种请求过滤器,只允许唯一的请求通过,其他人将被阻止,直到允许的请求返回为止。 阻塞的请求也会将相同的数据返回给调用者(通过在服务器上查找缓存的响应)
这种方法的优点/缺点是什么? 除了更改客户端逻辑之外,还有更好的解决方案;)
答案 0 :(得分:1)
您可以创建一个唯一的对象来锁定每个"键。"其中键是一些请求参数,在本例中为String
。这样你就可以保持请求(因为同步),一旦计算完成,两个客户端几乎同时得到结果。通过这种方式,客户端不必进行多个请求,而不是首先必须等待第一个客户端填充缓存的客户端。
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
public class Hold {
private ConcurrentHashMap<String, String> holds =
new ConcurrentHashMap<>(new HashMap<String, String>());
// compose a "hash" for lack of better word, could append a timeout as well
public String hashString (String string) {
return string + "wackystuff";
}
public String doLongComputation () {
// do crazy computation here
return new String();
}
public synchronized String getResults (String key) {
// give us a unique object for this key to lock on
holds.putIfAbsent(key, hashString(key));
// lock on that key
synchronized (holds.get(key)) {
// we have a non lock value so return it
if (!holds.get(key).equals(hashString(key))) {
// could do some timeout here
return holds.get(key);
}
// the cache is empty so do the long computation
holds.put(key, doLongComputation());
}
return holds.get(key);
}
}
这只是一种狡猾的方法,本书 Java Concurrency in Practice 有更强大的方法,它在5.19节中,代码示例可以找到here。
以下是此方法的优缺点:
答案 1 :(得分:0)
在开发与许多REST服务的集成以避免不必要的服务调用期间,我们在收到的响应数据库(JSON字符串)中创建现金。
对于每个此类现金记录,我们保存用于调用Web服务的 params 。如果我们有请求,我们将params与数据库中现有的params进行比较。我们仅针对新的params向REST发出实际请求。此外,我们也有必要,因为有些请求不是免费的。
此外,我们还有一个参数,显示每小时(或几天)内每张现金记录的验证日期,以便在一段时间后我们自动发出真实请求,如果它是很久以前制作的获得免费信息。
这种方法是在使用REST服务几年后创建的,它在我们的解决方案中非常有用。