【发布时间】:2012-10-23 17:35:02
【问题描述】:
我有一个 Web 服务器,可以读取和写入磁盘上的数据文件。我希望仅在单个 Web 请求中写入文件。
这是一个说明我的问题的示例程序。它在“/tmp/rw.txt”中保存一个状态文件,并在每次 Web 命中时递增整数内容。运行这个程序,然后运行类似ab -n 10000 -c 1000 http://localhost:3000/ 的东西,表明多次命中从文件中读取了相同的值,并且多次写入。
注意:我知道flock() 和fs-ext。但是,flock() 会将文件锁定到当前进程;由于这里的所有访问都在同一个进程中,flock() 不起作用(并且使这个示例相当复杂)。
另外请注意,我通常会使用 express、async 等来完成大部分工作;只是为了举例而坚持基础。
var http = require("http"),
fs = require("fs");
var stateFile = "/tmp/rw.txt";
var server = http.createServer(function(req, res) {
var writeNum = function(num) {
var ns = num.toString(10);
console.log("Writing " + ns);
fs.writeFile(stateFile, ns, function(err) {
if (err) {
res.writeHead(500, {"Content-Type": "text/plain"});
res.end(err.message);
} else {
res.writeHead(200, {"Content-Type": "text/plain"});
res.end(ns);
}
});
};
switch (req.url) {
case "/reset":
writeNum(0);
break;
case "/":
fs.readFile(stateFile, function(err, data) {
if (err && err.code == "ENOENT") {
// First time, set it to zero
writeNum(0);
} else if (err) {
res.writeHead(500, {"Content-Type": "text/plain"});
res.end(err.message);
} else {
writeNum(parseInt(data, 10) + 1);
}
});
break;
default:
res.writeHead(404, {"Content-Type": "text/plain"});
res.end("No such resource: " + req.url);
}
});
server.listen(3000);
【问题讨论】:
-
本案例与node.js无关。这是一个多线程功能。您不能保证下一个请求会从文件中读取存储上一个请求的值。如果它们之间的时间小于一毫秒或类似(小于磁盘访问),第二个请求将不会知道先前的请求正在更新文件。你可以写一个队列或类似的东西,但这不是必需的,所有的互联网都是这样工作的,因为访问磁盘是 sloooowwww。
-
@GabrielLlamas 您是否尝试运行示例代码?它是用 node.js 编写的,并说明了问题。大多数多线程系统都有锁定机制,如内置的信号量、互斥锁和同步部分。目前,我认为最好的方法是使用进程内锁定机制。
标签: node.js synchronization fs flock