0

我有一个每 5 分钟运行一次的后台线程。我正在使用ScheduledExecutorService这个。每五分钟,我都会调用我的一项服务并解析从该服务返回的响应。

public class ThreadScheduler {

private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public void startScheduleTask() {

        scheduler.scheduleAtFixedRate(new Runnable() {
            public void run() {
                try {
                    callService();
                } catch (Exception ex) {
                    // log error
                }
            }
        }, 0, 5L, TimeUnit.MINUTES);
    }

    public void callService() throws Exception {
        // execute the service and parse the response
    }   
}

现在上面的代码在 1000 台机器上运行,它们都同时启动,这意味着它将每 5 分钟同时对我的服务进行所有 1000 次调用。我试图将负载更均匀地分布在 5 分钟的窗口中。上面的代码有可能做到这一点吗?

我只是想在 5 分钟的窗口内将负载更均匀地分布在我的服务上,这样它就不会同时影响我的服务,这将在所有系统同时启动后施加更多负载。

我想出了下面的代码,试图在五分钟的窗口中更均匀地分布负载:

public class ThreadScheduler {

private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public void startScheduleTask() {

        scheduler.scheduleAtFixedRate(new Runnable() {
            public void run() {
                try {
                    callService();
                } catch (Exception ex) {
                    // log error
                }
            }
        }, (int)(Math.random()*5*60), 5*60L, TimeUnit.SECONDS);
    }

    public void callService() throws Exception {
        // execute the service and parse the response
    }   
}

这是在 5 分钟窗口内均匀分布负载的正确方法吗?

4

1 回答 1

1

这会有所帮助,但是在第一次变化之后,时间表仍然是固定的。另一种更分散负载的方法是使用“具有固定延迟的调度”并在每次执行中放置一个短暂的随机暂停(例如Thread.sleep(Math.random()*5000L)就在之前callService())。随着时间的推移,这将导致更多的可变性。

此外,为了测试可变性,您可以创建一个简单的测试程序,打印出当前时间(以毫秒为单位),而不是调用实际的服务。使用不同的算法运行你的测试程序一个小时并绘制结果。选择可以为您提供最佳传播的版本。

于 2014-08-30T16:33:15.433 回答