sudone.com 服务器系统架构分析日志


nginx中的一个有用的变量:request_body_file

[2010-04-15 16:10:19]
今天在网上意外发现一种说法,众所周知,往nginx代理服务器上传一个文件,nginx会自己将这个文件保存下来,然后再往后端发送。在这个过程中,nginx会创建一个临时文件,既然是临时文件,很显然会在文件系统上存有一个文件,于是,nginx就可以往后端发送一个临时文件的文件名,而不是一整个文件!然后后端拿到这个文件名可以直接读取。

这个文件名在nginx由一个变量提供,那就是$request_body_file,在nginx的php fastcgi_params配置文件中,因为一般都是直接抄的,所以通常都带有这句:

fastcgi_param REQUEST_BODY_FILE $request_body_file;

于是,在nginx的proxy配置中,也可以写上:

proxy_set_header request_body_file $request_body_file;

虽然nginx可以将这个临时文件的文件名传到后端,但是仍然需要满足一些条件才能利用到这个优化的:

1) 后端要和代理在同一台机器上,这个不必要解释。
2) 后端要支持这项优化,在大多数应用服务器上就是能够关闭上传功能,仅仅读取request_header就可以,这么看来,有了这个变量,居然能使不支持上传的应用服务器软件轻易就增加了上传文件的功能。

----------------

今天测试了一下,发现还有几个问题:

1) 对于比较小的文件,比如一般的文本和小图片,nginx会将其保存在内存里,并没有写入文件,这时后端可能会拿不到request_body_file这个头,或者拿到的文件是不存在的。通过配置:

client_body_in_file_only on;

就可以让nginx将所有上传文件都写入文件,这样测试才会顺利。

2) 虽然可以拿到request_body_file这个文件,但是这个文件并不能直接使用,它里面有一点点格式,类似:

-----------------------------7d9abd10206
Content-Disposition: form-data; name="img1"; filename="D:\Pic\11.jpg"
Content-Type: image/pjpeg

[图片文件内容]省……
-----------------------------7d9abd10206

因此拿到这个文件后,要对其作一些处理才能成为真正的文件,虽然这个处理原理很简单,但仍显得繁琐。

其中7d9abd10206这个数值可以在request header的Content-Type中得到,本例的Content-Type是:

Content-Type: multipart/form-data; boundary=---------------------------7d91092110206

3) 如果同时上传两个文件,那么保存的这个文件就变成:

-----------------------------7d9abd10206
Content-Disposition: form-data; name="img1"; filename="D:\Pic\11.jpg"
Content-Type: image/pjpeg

[图片文件内容1]省……
-----------------------------7d9abd10206
Content-Disposition: form-data; name="img2"; filename="D:\Pic\12.jpg"
Content-Type: image/pjpeg

[图片文件内容2]省……
-----------------------------7d9abd10206

这显然更是难缠,如果要节约系统IO,追求高效率,还是要撰写一个模块来处理才行。

4) 我在测试中尝试使用:

proxy_pass_request_body off;

来阻止nginx往后端发送request_body内容,但是这样居然触发了nginx的bug,致使请求超时不能完成,我测试用的nginx是 0.7.59版。

站名:sudone.com; 站长:Ayou; 服务器:ubuntu+nginx+squid+php
老细网