3

Question: Why does an NFS mount using the sync option cause nginx and/or Chrome (and only Chrome; not Safari, Firefox, Edge or curl) to chunk or restart the file upload?

Some background:

I have nginx in front of a server cluster. We added file uploading and we're using nginx to handle the upload and then pass the uploaded file body via its X-FILE header.

Until recently we were only processing uploads on the nginx server, due to the issues with other application servers in the cluster being unable to access the client_body_temp_path (/tmp in this case).

We run on AWS, so I provisioned an EFS (aka NFS) share and mounted this at /mnt/efs and then changed nginx client_body_temp_path to point at /mnt/efs/tmp.

I mounted the NFS share on all the application servers and they can now access the file uploads on /mnt/efs/tmp, but the uploaded files are often zero-length when they're initially read by the other clients, due to the NFS asynchronous writes.

I changed the NFS mount just on the nginx server so it's mounted with sync:

Initial mount:

example.eu-west-1.amazonaws.com:/ /mnt/efs nfs4 vers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport,_netdev,nofail

New mount:

example.eu-west-1.amazonaws.com:/ /mnt/efs nfs4 vers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport,_netdev,nofail,sync

I remounted the share and tried some uploads and happy days, the other NFS clients see the non-empty files in /mnt/efs/tmp.

But with some more testing it turns out that uploaded files over about 10M get restarted or chunked by Chrome.

What happens:

nginx starts to receive the upload (in the video below, I'm sending a 32.7MB file), but at 6.4MB, a new upload starts and then eventually nginx decides that the client's stopped sending, so issues a 499 which causes Chrome to abort the upload and it all fails. You can see all this happening here, as I watch the files coming in to /mnt/efs/tmp:

http://jay.gooby.org/media/video/chrome%20failing.mp4

The upload initially comes in as 0000000006 but then when it gets to 6.4M, a second upload 0000000007 starts (but 0000000006 continues to 12M), and then when 0000000007 hits 6.4, a third, 0000000008 starts (0000000007 continues to 12M). Once 0000000008 hits 12M ngingx issues the 499 and Chrome aborts the upload.

Other useragents don't have this problem. I'm able to upload the same file with Safari, Firefox and curl. Chrome on Mac and Windows both have the same issue.

Here's curl sending the file with no problems: it arrives as 0000000010 single 32M file:

http://jay.gooby.org/media/video/curl%20working.mp4

After tearing my hair out for a bit, I removed the sync option from the NFS mount on the nginx server and lo and behold, files uploaded with Chrome arrive in one piece as a single file. So what gives?

nginx is behind an Elastic IP, but not an ELB, and the upload is over http2.

nginx is compiled with --with-threads option

Update 1: That 6.4mb value seemed significant, as that's the point that each new upload chunk began/restarted. 6.4mb is 51200000 bits which seems like a quite specific value...

The initial bytes of the three files are identical, so it's as if Chrome decided to start resending at the 6.4mb point:

3 identical mp4 file headers

0

You must log in to answer this question.

Browse other questions tagged .