我有一个后台线程,每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分钟窗口内均匀分散负载的正确方法。
答案 0 :(得分:1)
这在某种程度上会有所帮助,但是在第一次变异之后,时间表仍然是固定的。另一种分散负载的方法是使用"schedule with fixed delay"并在每次执行中放置一个短暂的随机暂停(例如Thread.sleep(Math.random()*5000L)
之前的callService()
。随着时间的推移会导致更多的变化。
另外,为了测试可变性,您可以创建一个简单的测试程序,打印出当前时间(以毫秒为单位),而不是调用实际服务。使用不同的算法运行您的测试程序一小时并绘制结果图表。选择能让你获得最佳传播的版本。