Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/rest/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在REST中处理相同的并发请求_Java_Rest_Concurrency_Jersey_Request - Fatal编程技术网

Java 在REST中处理相同的并发请求

Java 在REST中处理相同的并发请求,java,rest,concurrency,jersey,request,Java,Rest,Concurrency,Jersey,Request,大家好! 我有一个休息,基于球衣的申请。此应用程序(由于其客户端的性质)在大致相同的时间(相隔约2-5秒)接收相同的http请求(其中3-6个)。 每个请求大约需要10秒来处理,并带回大量数据(点击数据库、进行数据按摩等)。 在理想情况下,我希望避免多次处理同一请求,并考虑编写某种请求过滤器,只允许唯一请求通过,而其他请求将被阻止,直到允许的请求返回。 被阻止的请求还将向调用者返回相同的数据(通过在服务器上查找缓存的响应) 这种方法的优点/缺点是什么? 除了更改客户端逻辑之外,还有其他更好的解决

大家好! 我有一个休息,基于球衣的申请。此应用程序(由于其客户端的性质)在大致相同的时间(相隔约2-5秒)接收相同的http请求(其中3-6个)。 每个请求大约需要10秒来处理,并带回大量数据(点击数据库、进行数据按摩等)。 在理想情况下,我希望避免多次处理同一请求,并考虑编写某种请求过滤器,只允许唯一请求通过,而其他请求将被阻止,直到允许的请求返回。 被阻止的请求还将向调用者返回相同的数据(通过在服务器上查找缓存的响应)

这种方法的优点/缺点是什么?
除了更改客户端逻辑之外,还有其他更好的解决方案吗;)

您可以为每个“键”创建一个唯一的对象来锁定。其中键是一些请求参数,在本例中是一个
字符串
。这样,您只需保留请求(因为同步),一旦计算完成,两个客户端几乎同时返回结果。这样,客户机就不必发出多个请求,而不是首先发出请求的客户机必须等待第一个客户机启动缓存

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);
    }

}
import java.util.HashMap;
导入java.util.concurrent.ConcurrentHashMap;
公开课举行{
私有ConcurrentHashMap保持=
新的ConcurrentHashMap(新的HashMap());
//为缺少更好的单词而编写一个“哈希”,也可以附加一个超时
公共字符串哈希字符串(字符串字符串){
返回字符串+“wackystuff”;
}
公共字符串计算(){
//在这里做疯狂的计算
返回新字符串();
}
公共同步字符串getResults(字符串键){
//给我们一个唯一的对象让这把钥匙锁定
holds.putIfAbsent(key,hashString(key));
//锁上那把钥匙
已同步(保持。获取(键)){
//我们有一个非锁定值,所以返回它
如果(!holds.get(key).equals(hashString(key))){
//我可以在这里暂停一下吗
返回holds.get(键);
}
//缓存是空的,因此进行长时间计算
holds.put(key,dolongcompulation());
}
返回holds.get(键);
}
}
这只是一种狡猾的方法,这本书《实践中的Java并发》(Java Concurrency in Practice)中有更健壮的方法,它在第5.19节中,代码示例可以找到

以下是这种方法的优缺点:

  • 赞成:客户只需提出一个请求
  • 赞成:你不是在重新计算结果
  • 赞成:没有单个客户端的等待时间在串行情况下增加
  • 缺点:在计算过程中,您正在保留一个VM线程,这是每个客户端的。鉴于您拥有查看客户端,这不应该是一个问题
  • 缺点:考虑一个好的时间表来清除缓存可能很棘手

在开发与多个REST服务的集成过程中为了避免对服务的不必要调用我们正在接收响应(JSON字符串)的数据库中创建一个现金

对于每个这样的现金记录,我们保存用于调用web服务的参数。如果我们有一个请求,我们会将参数与数据库中现有的参数进行比较。我们只为新参数发出真正的休息请求。对我们来说也是必要的,因为有些请求不是免费的

此外,我们还有一个参数,它以小时(或天)为单位显示每个现金记录的验证日期,以便在一段时间后,如果收到免费信息是很久以前发出的,我们会自动发出真正的请求


这种方法是在使用REST服务数年后创建的,在我们的解决方案中效果非常好

谢谢,但我的问题是关于在服务器端这样做的利弊。你认为这种方法有什么问题?我已经更新了我的答案,展示了一些优点和缺点。谢谢@Victory。这是有道理的。对于这个问题,你能想到其他的解决办法吗?我能想到2个(我都不喜欢):1。在客户端和服务器2之间添加代理。在客户端添加筛选器。这两种方法都不能消除服务器端并发请求的风险。我认为代理将更加棘手,因为它需要相同的逻辑,而不需要相同的作用域。过滤器是一个想法,但是你会要求客户“表现良好”,这不是一个好的假设。这是一个良好的API设计IMHO的反模式。