看来,在 Nginx 服务器上,修改正在下载的文件的内容可能会导致客户端收到损坏且不一致的文件。以下是我的实验:
我在局域网中搭建了一个Nginx服务器,服务器上有一个1M大小的文件,文件内容都是a,我用curl下载了这个文件到电脑上(网速有限,速度够慢了),在下载的过程中,我用另一个大小相同,但内容都是b的文件覆盖了服务器上的这个文件,我用linux命令cp完成了这一步,没有报错,最后我查看下载的结果,结果是一个混合文件,前半部分是a,后半部分是b,像这样:“aaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb”
我想知道这是否是预期的结果。如果是这样,有没有办法告诉 Nginx 在仍有活动连接时拒绝任何 IO 操作,或者在文件更改后仅返回错误代码并中止连接?由于更新文件可能是服务器上非常常见的操作,我想应该有一些解决方法。
我的测试环境:
Server OS: Linux 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC
2014 x86_64 x86_64 x86_64 GNU/Linux
Server file system: ext4
Nginx version: nginx/1.4.6 (Ubuntu)
Client OS: Windows 10
Client tool: curl 7.51.0 (x86_64-w64-mingw32) libcurl/7.51.0 OpenSSL/1.0.2j
zlib/1.2.8 libssh2/1.7.0 nghttp2/1.15.0 librtmp/2.3
答案1
读取正在被覆盖的文件将产生不可预测的结果。
通过将修改写入临时位置(在同一文件系统上)并重命名(mv
)临时文件以替换当前版本,您将获得更可预测的结果。重命名文件是原子且即时的。
如果您在重命名文件时 Web 服务器(仍)正在读取和传输旧版本,则它将继续从旧版本执行此操作,直到下载完成,但对该文件的任何新请求都将获得新版本。