在REST中处理相同的并发请求 [英] Processing same concurrent request in REST

查看:131
本文介绍了在REST中处理相同的并发请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问候社区!
我有一个基于jersey的REST应用程序。此应用程序(由于客户的性质)在大致相同的时间(相距约2-5秒)接收相同的HTTP请求(其中3-6个)。
每个请求大约需要10秒钟的时间来处理,并带回大量数据(击中DB,进行数据按摩等)。
在理想的世界中,我希望避免多次处理相同的请求,并正在考虑编写某种仅允许唯一请求通过的请求过滤器,而其他请求过滤器将被阻塞直到允许的回报。
被阻止的请求还会将相同的数据返回给调用方(通过在服务器上查找缓存的响应)

Greetings SO community! I have a REST, jersey based, application. This application(due to nature of it's clients) receives same http requests (3-6 of them) at roughly the same time (~2-5s apart). Each request takes around 10s to process and brings back a ton of data (hitting DB, doing data massaging etc). In an ideal world I'd like to avoid having to process the same request multiple times and was thinking of coding some sort of request filter that would only allow unique requests go through, whist others would be blocked until such time when the allowed one returns. Blocked requests would also then return the same data to the caller (by looking up cached response on the server)

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

What are the pros/cons of this approach? Are there any better solutions to this other than changing client logic ;)

推荐答案

您可以创建一个唯一的对象来锁定每个键。其中的键是一些请求参数,在此示例中为 String 。这样,您只需保留请求(由于同步),一旦完成计算,两个客户端大约会同时获得结果。这样,客户端不必发出多个请求,相反,不是第一个客户端也不必等待第一个客户端启动缓存。

You could create a unique object to lock on for each "key." where the key is some request parameters, in this example a String. That way you just hold onto the request (because of synchronization) and once the computation is done, both clients get the results back at about the same time. This way the clients don't have to make multiple requests, instead the clients who are not first have to wait for the first client to prime the cache.

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 (Java并发实践)具有更强大的方法,可在第5.19节中找到,代码示例可在此处

This is just one kinda sly approach, the book Java Concurrency in Practice has much more robust approach, its in section 5.19 and the code sample can be found here.

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

Here are the pros and cons of this approach:


  • Pro:客户端只需要发出一个请求

  • Pro:您不会重新计算结果

  • 专业版:在序列情况下,没有单个客户端的等待时间增加了

  • 缺点:您在以下时间内保持VM线程:计算,这是每个客户的。

  • 缺点:想想一个合理的时间表来清除缓存可能很棘手

  • Pro: the client has to make only one request
  • Pro: you are not recalculating the results
  • Pro: the wait time for no individual client is increased over the serial case
  • Con: you are holding up a VM thread for the duration of the calculation and this is per client. Seeing as you have view clients this shouldn't be an issue.
  • Con: Thinking of a good schedule to clear the cache might be tricky

这篇关于在REST中处理相同的并发请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆