所以我将我的网站从Apache移到了Nginx上,我遇到了这个场景的问题:
用户上传照片。此照片已调整大小,然后复制到S3。如果磁盘上有合适的空间(或者文件无法传输到S3),则会保留本地版本。
我希望对这些图像(例如http://www.mysite.com/p/1_1.jpg)的请求首先查看p /目录。如果不存在本地文件,我想将请求代理到S3并呈现图像(但不是重定向)。
在Apache中,我这样做了:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^p/([0-9]+_[0-9]+\.jpg)$ http://my_bucket.s3.amazonaws.com/$1 [P,L]
我尝试在Nginx中复制此行为是:
location /p/ {
if (-e $request_filename) {
break;
}
proxy_pass http://my_bucket.s3.amazonaws.com/;
}
每个请求都会尝试命中Amazon S3,即使该文件存在于磁盘上(如果它在亚马逊上不存在,我也会收到错误。)如果我删除了proxy_pass行,那么请求获取文件磁盘DO工作。
有关如何解决此问题的任何想法?
答案 0 :(得分:33)
这不应该是使用try_files
的一个例子吗?
location /p/ {
try_files $uri @s3;
}
location @s3{
proxy_pass http://my_bucket.s3.amazonaws.com;
}
确保S3网址上没有以下斜杠
答案 1 :(得分:12)
您可以像这样改进您的s3代理配置。改编自https://stackoverflow.com/a/44749584:
location /p/ {
try_files $uri @s3;
}
location @s3 {
set $s3_bucket 'your_bucket.s3.amazonaws.com';
set $url_full '$1';
proxy_http_version 1.1;
proxy_set_header Host $s3_bucket;
proxy_set_header Authorization '';
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
proxy_intercept_errors on;
resolver 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 10s;
proxy_pass http://$s3_bucket$url_full;
}
答案 2 :(得分:3)
感谢保留我的coderwall帖子:)为了缓存目的,你可以稍微改进一下:
http {
proxy_cache_path /tmp/cache levels=1:2 keys_zone=S3_CACHE:10m inactive=24h max_size=500m;
proxy_temp_path /tmp/cache/temp;
server {
location ~* ^/cache/(.*) {
proxy_buffering on;
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
...
proxy_cache S3_CACHE;
proxy_cache_valid 24h;
proxy_pass http://$s3_bucket/$url_full;
}
}
}
还有一个建议是将解析器缓存扩展到5分钟:
resolver 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 10s;
答案 3 :(得分:0)
break
并没有完全按照你的期望nginx做你最后要求的事情,如果你开始挖掘模块,这是有意义的......但基本上用来保护你的proxy_pass不存在版本
if (-f $request_filename) {
break;
}
if(!-f $request_filename)
proxy_pass http://s3;
}
答案 4 :(得分:0)
我最终通过检查文件是否存在来解决这个问题,如果是,则重写该请求。然后我处理重写的请求并在那里执行proxy_pass,如下所示:
location /p/ {
if (!-f $request_filename) {
rewrite ^/p/(.*)$ /ps3/$1 last;
break;
}
}
location /ps3/ {
proxy_pass http://my_bucket.s3.amazonaws.com/;
}