我的情况......
我有一组 worker ,它们被安排定期运行,每个都以不同的时间间隔运行,并希望找到一个好的实现来管理它们的执行。
示例:假设我有一个工人去商店,每周给我买一次牛奶。我想将这个作业及其配置存储在mysql表中。但是,轮询表(每秒?)似乎是一个真的坏主意,并且看看哪些作业已准备好放入执行管道。
我的所有工作人员都是用javascript编写的,所以我使用node.js执行,beanstalkd作为管道。
如果正在异步创建新作业(即调度工作程序在给定时间运行)并且我需要持久存储作业结果和配置,那么如何避免轮询表?
谢谢!
答案 0 :(得分:2)
我同意这看起来不够优雅,但考虑到计算机工作的方式某些事情 *某处*将需要轮询某种才能弄明白哪些工作要执行。那么,让我们来看看你的一些选择:
轮询数据库表。这根本不是一个坏主意 - 如果你将工作存储在MySQL中,它可能是最简单的选择。每秒一个查询的速率是没有的 - 尝试一下,你会注意到你的系统甚至没有感觉到它。
一些想法可帮助您将此扩展到每秒数百个查询,或者只是降低系统资源要求:
如果你必须进一步扩展,请将主作业表保留在数据库中,并使用我建议的第二个较小的表,只需将该表放入RAM:作为数据库引擎中的内存表,或者在你的程序中的某种队列中。如果你有的话,以极短的间隔查询队列 - 这将需要一些极端的用例来引起任何性能问题。
此选项的主要问题是您必须跟踪内存中但未执行的作业,例如由于系统崩溃 - 为您编写更多代码......
为一堆作业中的每一个创建一个线程(比如,下一分钟需要执行的所有作业),并调用thread.sleep(millis_until_execution_time)(或者其他什么,我不熟悉的node.js)。
此选项与no具有相同的问题。 2 - 您必须跟踪作业执行以进行崩溃恢复。它也是最浪费的imo - 每个睡眠作业线程仍然需要系统资源。
当然可能还有其他选择 - 我希望其他人回答更多的想法。
只是意识到每秒轮询数据库并不是一个坏主意。这是imo最直接的方式(记住KISS),按照这个速度,你不应该有性能问题,所以要避免过早的优化。
答案 1 :(得分:1)
为什么在node.js中没有保存到数据库的Job
对象。
var Job = {
id: long,
task: String,
configuration: JSON,
dueDate: Date,
finished: bit
};
我建议你只将id存储在RAM中,并将所有其他Job
数据保留在数据库中。当你的超时功能最终运行时,它只需要知道.id
来获取其他数据。
var job = createJob(...); // create from async data somewhere.
job.save(); // save the job.
var id = job.id // only store the id in RAM
// ask the job to be run in the future.
setTimeout(Date.now - job.dueDate, function() {
// load the job when you want to run it
db.load(id, function(job) {
// run it.
run(job);
// mark as finished
job.finished = true;
// save your finished = true state
job.save();
});
});
// remove job from RAM now.
job = null;
如果服务器崩溃了,那么查询所有[finished=false]
的作业,将它们加载到RAM中并再次启动setTimeouts。
如果出现任何问题,您应该能够像这样彻底重启:
db.find("job", { finished: false }, function(jobs) {
each(jobs, function(job) {
var id = job.id;
setTimeout(Date.now - job.dueDate, function() {
// load the job when you want to run it
db.load(id, function(job) {
// run it.
run(job);
// mark as finished
job.finished = true;
// save your finished = true state
job.save();
});
});
job = null;
});
});