【问题标题】:Rest : How to handle thousands of same request休息:如何处理数千个相同的请求
【发布时间】:2019-06-02 00:51:27
【问题描述】:

我有休息网络服务,它基本上需要一个数字,并提供该数字是否为素数,即纯文本真或假。

数以百万计的用户正在使用这项服务。

现在一个用户正在发送非常大的数字,例如(15-20 位数字/大数字),我的服务需要时间来计算该数字是否为质数。该用户连续发送数千个相同号码的请求。那么如何处理这些相同的数千个请求。

例如:

在请求中发送 101221323232324343 号码,我的服务需要 3 秒来确定该号码是否为素数。现在他每秒发送 1000 个请求。

如何处理这种情况?

【问题讨论】:

  • 我猜你可以使用内存缓存。
  • 还有这么多不同数字的用户......缓存会太大......不要认为缓存是一个好的解决方案......
  • 所以你可以施展魔法......:因为要么你使用内存来节省处理时间,要么你为每个请求腾出更多的处理时间......没有第三个选择,如果你有一个聪明的缓存的方式可以节省一些内存,不是简单的把每个请求都放到缓存中
  • 为避免用户发送大量请求,您必须对它们进行速率限制。

标签: java rest web-services


【解决方案1】:

您可以使用逐出内存中缓存来调整其关于最大内存大小或 TTL 的参数。对于一般信息检查,例如LFU cache eviction。有很多实现,而我会推荐 Ben Manes 的 caffeine library 以提高效率。您可以使用数据库,但在这种情况下,它的 IO 可能比新计算更昂贵,因此我可能会将缓存限制在内存中。

【讨论】:

    【解决方案2】:

    您可以在数据库中存储大于给定位数的值。每当收到这样的数字时,您都可以将它是否是素数存储在数据库中。您还可以使用缓存来存储最后 n 个不同的值,因此,当请求一个数字时,您可以检查它是否太长。如果没有,只需计算。如果太长,在缓存中搜索。如果它在那里,请将其退回。如果它不存在,请在数据库中搜索它。如果存在,请将其添加到缓存中(并可能删除最旧的值)并将其返回给用户。如果连数据库里都没有,计算一下,存入数据库,加入缓存,返回给用户。

    【讨论】:

    • @VJS 欢迎您。如果它解决了您的问题,您可能会考虑接受它作为正确答案。无论如何,祝你好运解决这个有趣的问题。
    • 这是一个很好的答案。这是一种直截了当的方法。只是想,我们能不能做点别的事情来处理这种情况。我的意思是,有没有更好的解决方案..
    • @VJS 你可以使用一些额外的优化技术。例如,如果数字之和能被 3 整除,则大数不是素数。如果最后一位数字是对,则大数不是素数。如果您有另一个与该数字足够接近的非质数,您可以检查差异。例如,如果另一个非素数可以被 7 整除,并且差值可以被 7 整除,那么你就有一个非素数。
    • 在使用任何数据库之前,我会检查 IO 成本(考虑到高度并发的查找)与计算时间。同样,如果没有合理的驱逐策略,数据库将很快占用整个存储空间,因为问题是无限的:)
    【解决方案3】:
    @NotThreadSafe 
    public CheckIfPrime extends Servelet  {
        private Long lastNumber;
        private Long isLastNumberPrime;
    
        public Long operation(ServeletRequest req, ServeletResponse res) {
            if(getNumberFromRequest(req) == lastNumber) {
                return isLastNumberPrime;
            } else {
                 return checkForPrimeNumber(getNumberFromRequest);
            }
        }
    
    }
    

    使用同步原语来遵守类的不变量和后置条件(一种方法是使用AtomicLong 而不是Long

    如果您认为请求数量可能太大(耗尽内存),请考虑使用分布式缓存。

    对于非常高的 TPS,使您的应用程序具有响应性。 checkForPrime()opeeation 可以异步完成。为什么要阻塞调用线程?

    【讨论】:

    • 鉴于请求的绝对数量,达到与最后一个相同值的概率接近于零,因此这种优化是无用的。
    • 哦,为什么你认为它会接近于零?正如 OP 所提到的,可能有数千个请求包含相同的数字。
    • 同样的不是最后一个:正如 OP 所说“数百万用户正在使用该服务”,肯定会有数千个相同数字的数千次重复,因此每次有效它都是一个新数字与上一个相比。此外,您的示例不是线程安全的:您应该对这对值/指标使用原子引用并相应地交换它。
    • 在这种情况下,我们可以使用包含数字及其布尔结果的 ConcurrentHashMap 吗?
    • 查看我的(单独的)答案,考虑到问题是无限的,您的代码将在标准映射上迅速耗尽内存,无论是否并发。
    猜你喜欢
    • 2020-12-16
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    • 2021-12-01
    • 2010-12-04
    • 1970-01-01
    • 2014-02-10
    • 2018-01-07
    相关资源
    最近更新 更多