【发布时间】:2011-05-09 08:06:49
【问题描述】:
假设您正在编写一个为作业队列提供服务的守护进程。各种其他软件将守护程序的作业写入队列。守护程序每隔几秒轮询一次队列以查找待处理的作业。假设队列被实现为 MySQL 数据库中的一个表,并且守护进程是一个简单的循环:
- 从队列中获取所有到期作业
- 做好工作
- 睡N秒
- 转到 1
守护程序必须能够承受来自 MySQL 数据库服务器的服务中断和数据库连接中断。
你会设计守护进程在每个周期连接一次数据库服务器吗?即在 1. 之前连接并在 2 和 3 之间断开连接?
或者你会让守护进程保持连接打开?在这种情况下,它还需要 a) 检测服务器或连接何时不工作,b) 断开连接并重新连接,以及 c) 在不累积 DB 连接、无用连接描述符或其他死资源的情况下这样做。
如果您有偏好,为什么?
优点和缺点?
影响设计的因素?
还有其他方法吗?
这里的答案:mysql connection from daemon written in php 并没有说明为什么保持连接打开会更好。我在别处读到 MySQL 中每个连接的开销非常小。因此,为什么永久使用一个服务器连接比每隔几秒连接/断开连接更好,这一点并不明显。
在我的例子中,守护进程是用 PHP 编写的。
【问题讨论】:
-
你想做什么?根据具体情况,听起来 FIFO 文件或套接字可能更适合触发守护进程......(我会做的是在每个轮询间隔重新创建连接,但我又不会每隔几秒轮询一次)...
-
@ircmaxell:在我的情况下,FIFO 并不方便,因为将作业放入队列的进程需要能够读取它,并且作业队列状态需要在服务器重新启动后继续存在。队列的 MySQL 复制也很方便。
-
我并不是要通过 FIFO 传递所有数据。只是为了触发守护进程从基于 mysql 的队列中读取。所以基本上你会
INSERT INTO queue VALUES (job),然后是file_put_contents('fifo.file', '1');。守护进程会在试图打开 fifo 时进入休眠状态。所以如果它处理完所有它基本上会阻塞fopen('fifo.file', 'r');。下一次进程添加到队列时,它只是通知守护进程,然后立即开始处理作业。但是,当它处于休眠状态时,它不会消耗任何资源,因为它是一个阻塞的系统调用(即使一次是几个小时)。 -
@ircmaxell:如果您想在将作业放入队列后启动守护程序以服务队列,这是一种很好的方法。如果,otoh,排队的作业可能被指定为仅在未来某个时间之后运行,那么它就没有用了。