如何在写入文件时阻止对文件的访问,并在文件写入后恢复执行?
Posted
技术标签:
【中文标题】如何在写入文件时阻止对文件的访问,并在文件写入后恢复执行?【英文标题】:How can I prevent access to a file while it is being written to, and resume execution once the file has been written? 【发布时间】:2020-06-09 21:18:34 【问题描述】:当我的服务器收到请求时,我运行我的函数foo
。在foo
期间的某个时间点,我检查我的机器上是否存在某些文件(基于请求),然后我远程获取那些不存在的文件,并将它们保存在本地以备将来请求时使用。
如果我同时收到多个请求,这些请求都引用同一个文件bar
,而我的服务器上不存在该文件,我会遇到问题。以下是所发生情况的示例时间表:
-
请求 1 异步检查是否存在
bar
请求 2 异步检查是否存在 bar
请求1看到bar
不存在,所以异步下载文件
请求2看到bar
不存在,所以异步下载文件
请求 1 向bar
打开一个写入流,并将文件响应异步传送到该写入流中
请求 2 向bar
打开一个写入流,并将文件响应异步传送到该写入流中
请求 1 完成文件写入,尝试使用图像加载库加载其内容(图像),最终引发错误。
这是因为文件内容无效,因为文件正在被请求 2 覆盖。
我知道解决这个问题可能会涉及文件锁定,因此第一个看到文件在本地丢失的请求可以创建一个锁定文件,以向后续请求指示它已经被提取/写入。我不确定的是如何让这些后续请求等到文件加载完成。
我是否应该使用生成器函数,如果发现其他请求正在获取此远程文件,则暂停执行我的函数?在那种情况下,我以后如何恢复它?我是否必须维护一些暂停请求的全局队列?
是否有任何资源可以帮助我更好地理解在这里做什么?
【问题讨论】:
这是一个没有外部争用文件的服务器问题吗?或者这是一个多服务器问题和/或文件也存在外部争用。如果这是一个服务器问题,选项会简单得多。此外,请显示您拥有的任何实际代码的相关部分,因为您如何检查文件是否存在(以防止竞争条件)的详细信息也很重要。 【参考方案1】:您将需要某种形式的同步。只要你只运行一个 NodeJS 进程,最简单的方法就是使用 javascript 的单线程行为:
const fileLoading = new Map();
async function getFile(id)
if(fileLoading.has(id))
await fileLoading.get(id);
else
const load = (async function()
await fetchFile(id);
fileLoading.remove(id);
)();
fileLoading.set(id, load);
await load;
return await readFile(id);
【讨论】:
以上是关于如何在写入文件时阻止对文件的访问,并在文件写入后恢复执行?的主要内容,如果未能解决你的问题,请参考以下文章
如何锁定文件以防止读取/写入同一文件的多个 ajax 请求?