使用Idp_proxy代理并缓存S3文件

2009-11-09 00:00 [nginx] [idp_proxy] [erlang]


书接上文. 由于我们不能用Nginx直接请求S3,所以需要通过一个中间代理。最初,我是用Ruby+Eventmachine实现的。完成后发现性能不好,当然也可能是我的代码有问题。不管怎么说,实现该功能最佳的语言还是Erlang。我也没编多少代码,只是Mochiweb框架的基础上加了些功能。当然并不是很完美,但是基本可以工作。另外,这也只是一个思路,真正用于生产系统肯定还要更多的优化。

代码放到Git Hub上上.

git clone git://github.com/seven1240/idp_proxy.git

你需要手工下载mochiweb,解压缩后放到deps目录中,或放到其它位置但在deps目录中做个符号链接(就像我在原代码中做的一样)。

另外,目前它使用s3sync获取S3上的文件,你需要把它放到某个路径下让Idp_proxy能找到它(见下面配置)。另外你需要先编辑s3config.yml以保证s3cmd.rb工作正常。看s3sync的README吧。

修改src/idp_proxy.hrl中的相关配置:

INTERNAL_PATH: 相对路径,将被从请求路径中去掉,并把剩下的部分与DOC_ROOT拼成本地文件的路径。

TMP_PATH: 下载时临时存放文件的目录

DOC_ROOT: 就是www root。

cd idp_proxy/deps/mochiweb
make
cd ../..
make

一切就绪后就可以启动了:

./start-dev.sh

测试

test/test.sh

根据测试结果你可以判断它是不是正常工作。接在来需要修改Nginx的配置(在a.com上):

        location /file-internal {
                internal;
                alias /home/some_dir/file-internal;

                proxy_set_header  X-Uri $uri;

                if (!-f $request_filename) {
                        proxy_pass http://127.0.0.1:8910;
                }
        }

以上配置假定Idp_proxy运行在本机8910端口上。当然,你也可以将Idp_proxy运行在别的机器上,并在Nginx上开户proxy_store功能来缓存文件。

注意,上面的配置中,我们加入了一个X-Uri的自定义HTTP头。因为,我们为了保护文件,文件路径可能会被加密,这就造成了路径不一致,如:

curl http://a.com/rails/4hjgqei-加-密-ogjgh4t409dkfjdk.mp3

请求到达rails_app后,rails会将以上路径解密,并在sendfile时返回真正的文件路径,如/file-internal/abc.mp3。Nginx得到该路径后,如果在本地找不到对应的文件,它就会向Idp_proxy发起请求,但在请求的HTTP头中,GET后的路径是不变的,所在我们才加了个自定义的Http header,用户识别,如:

GET /rails/4hjgqei-加-密-ogjgh4t409dkfjdk.mp3 HTTP/1.1
Connection: close
X-Uri: /file-internal/abc.mp3

然后Idp_proxy会根据 X-Uri所指定的文件名到S3上下载对应的文件。

如果不用X-Uri,或许可以使用rewrite,rewrite会将$uri重写后放到GET 后,但我没试过:

	rewrite (.*) $1 break;
《大道至简》

七歌
微信公众号

七歌杜金房
微信视频号