【问题标题】:Delaying access to the server to try to avoid peak hours延迟访问服务器以尽量避免高峰时间
【发布时间】:2017-07-15 14:31:52
【问题描述】:

数千人使用的 JAVA 7 离线软件会在用户早上运行时自动将备份发送到云端。每个发送的备份都会消耗服务器带宽。见下表:

可以注意到,08:15 AM 到 09:45 AM 之间形成了一个高峰。这是因为大多数用户在此时间间隔之间运行软件。

我们需要更改软件,使其每 10 分钟向云端发送一次备份。这将大大增加带宽消耗,我们担心会达到一些限制,因为许多用户在同一高峰时间运行该软件。

作为一种解决方法,我们计划将第一次备份随机推迟到服务器。但是,我们并不认为这是一个好的解决方案。

这类问题常见吗?有没有标准的解决方案?


这是我们正在考虑的算法,但我们不相信这是一个好的解决方案:

new Thread(new Runnable(){                          
    @Override
    public void run(){

        String hhmmNow = new SimpleDateFormat("HH:mm")
                .format(Calendar.getInstance().getTime());

        if( hhmmNow.compareTo("08:15")>=0 && hhmmNow.compareTo("09:45")<=0 ){
            Thread.sleep(new Random().nextInt(3600000)); //Sleep from 0 to 1h
        }

        while(true){
            sendBackupToTheCloud();
            Thread.sleep(600000); //Sleep 10 minutes
        }       
    }
}).start();

编辑: 根据 Mcdowella 的建议改为以下解决方案:

new Thread(new Runnable(){                          
    @Override
    public void run(){

        int periodicity = 10 * 60 * 1000;

        //Randon sleep between 0 and 10 minutes to 
        //distribute backups within the ten-minute interval.
        Thread.sleep(new Random().nextInt(periodicity));

        //Send new backup to server every 10 minutes
        while(true){
            sendBackupToTheCloud();
            Thread.sleep(periodicity);
        }       
    }
}).start();

【问题讨论】:

  • 一个应用发送到服务器的备份大小是多少?
  • 备份大小在 500KB 到 4MB 之间变化。
  • ok,如果成千上万的用户正在将备份上传到同一台服务器。您应该考虑在您的服务器上使用负载平衡器。这样您就无需更改软件中的算法。或者如果您仍然需要实施,那么在将备份上传到云之前,您应该请求服务器了解是否有足够的带宽可供您上传。有办法通过编程检查服务器端的带宽
  • 如果您有日志可以告诉您用户何时上传特定日期的备份,您可以使用这些日志来计算当天任何特定睡眠策略的结果。我倾向于总是随机睡眠,但最多只能睡 10 分钟。然后每个用户都有可能在每 10 分钟重复一次的时间表内选择任何给定的时间段。
  • @mcdowella 您的评论帮了很多忙。我没有使用日志,而是使用当前存储的备份的总大小、每个用户的平均备份数量以及每个用户在一天中打开软件的平均时间。另外,我会按照你的建议睡 0 到 10 分钟。我明白你的意思,我需要在 10 分钟的间隔内分配用户。我也理解对方的建议,但实施起来比较复杂,我没有必要的技能。我做了数学计算,麦克道拉的建议就足够了。

标签: java algorithm optimization bandwidth


【解决方案1】:

有几种不同的方法可以解决这个问题。您可以做一个稍微有点闲聊的协议,其中客户端首先请求进行备份并等待服务器响应服务器允许他们上传他们的数据,从而允许服务器在高负载时对某些客户端进行排队。

执行此操作的一种方法是发送 408 请求超时,然后写入客户端以在延迟后重试。

另一个想法是使用显式thread pool 来处理请求,以便在任何给定时间处理的客户端数量都有保证的限制。通常,大多数 Web 服务器都会有一种配置方式,例如 maxThreads option on Tomcat

问题中建议的随机化可能不是一个好主意,因为分布式系统往往提供非常大的样本量,以至于即使看似罕见的事件也不可避免。

【讨论】:

    【解决方案2】:

    不好。从繁忙时间开始延迟的用户可能最终会成为高峰期的服务器。一些用户即使在不需要时也会延迟。

    虽然随机化会使峰值稍微变平,但这肯定不是一个好主意。简单地询问服务器是否可以处理请求是简单且更有效的。它不需要是一个单独的请求,HTTP 状态503 Service Unavailable 就是针对这种情况的。您的客户端应在几分钟后重试。

    虽然随机分布使峰值趋于平缓,但询问服务器是随着时间推移完美保持利用率的唯一方法。

    请注意,您当前的带宽低于 1 Mb/s,这比我的 IP 提供商提供的标准私人家庭连接百倍。您可以使用负载平衡器,或者只是让客户端从服务器池中进行选择,如果它对于一台服务器来说太多了。但是,单个服务器应该很容易使磁盘带宽饱和,对于旧 HDD,它大约为 50 MB/s = 400 Mb/s。

    【讨论】:

    • 你是对的。我的想法最终会导致同时发送大量备份。但是,如果我遵循 Mcdowella 的建议,我认为这将有助于在 10 分钟间隔内很好地分配备份。我知道这并不完美,因为用户的备份大小和带宽速度不同,但这已经足够了。毕竟,根据我的数学计算,我最终将平均分配 9 MBps。
    • 当然可以,但无论如何我还是建议询问服务器,因为它更具前瞻性。您可能会获得 10 倍的用户或多台服务器,有些服务器可能会出现故障……并且询问他们总是会告诉您该怎么做。 +++ 而且,随机分布还是有一些高峰和低谷,所以你的服务器不会被完美利用。
    猜你喜欢
    • 1970-01-01
    • 2021-05-24
    • 2019-10-09
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    • 2012-01-24
    相关资源
    最近更新 更多