【问题标题】:Nginx Proxy to Files on Local Disk or S3Nginx 代理到本地磁盘或 S3 上的文件
【发布时间】:2011-01-03 23:45:40
【问题描述】:

所以我将我的网站从 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,即使该文件存在于磁盘上(如果它在 Amazon 上不存在,我会收到错误消息。)如果我删除 proxy_pass 行,然后请求文件磁盘可以工作。

关于如何解决这个问题的任何想法?

【问题讨论】:

  • 你能分享virual.conf文件吗?

标签: proxy amazon-s3 nginx


【解决方案1】:

您可以像这样改进您的 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】:

    感谢保留我的 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;
    

    【讨论】:

    • 您不需要在 proxy_pass 指令中使用斜杠,这非常重要。它应该是这样的:proxy_pass http://$s3_bucket$url_full;
    【解决方案3】:

    这不应该是一个使用try_files的例子吗?

    location /p/ {
        try_files $uri @s3;
    }
    
    location @s3{ 
        proxy_pass http://my_bucket.s3.amazonaws.com;
    }
    

    确保 S3 url 上没有斜杠

    【讨论】:

    • 很好的答案!清晰而简单的解决方案。谢谢!
    【解决方案4】:

    我最终通过检查文件是否不存在来解决这个问题,如果存在,则重写该请求。然后我处理重写的请求并在那里执行 proxy_pass,如下所示:

    location /p/ {
      if (!-f $request_filename) {
        rewrite ^/p/(.*)$ /ps3/$1 last;
        break;
      }
    }
    
    location /ps3/ {
      proxy_pass http://my_bucket.s3.amazonaws.com/;
    }
    

    【讨论】:

    • nginx 中的if 具有非常不可预测的行为。尽管这很好用,但建议尽可能使用try_files,就像在 Dan Gayle 的回答中一样。检查wiki.nginx.org/IfIsEvil 以了解if 的细微之处。
    【解决方案5】:

    break 没有做你所期望的那样,nginx 会做你要求的最后一件事,如果你开始挖掘制作模块,这是有道理的......但基本上用 does- 保护你的 proxy_pass不存在版本

    if (-f $request_filename) {
        break;
    }
    if(!-f $request_filename)
        proxy_pass  http://s3;
    }
    

    【讨论】:

    • 我最初尝试过,但如果我在proxy_pass 调用中拥有完整的http://my_bucket.s3.amazonaws.com/,Nginx 将无法启动。我收到以下错误:Restarting nginx: 2010/01/11 20:53:36 [emerg] 1485#0: "proxy_pass" may not have URI part in location given by regular expression, or inside named location, or inside the "if" statement, or inside the "limit_except" block in /etc/nginx/sites-enabled/my_site.com:39 如果我删除尾部斜杠,Nginx 将启动,但我的请求不再正确路由。有什么想法吗?
    猜你喜欢
    • 2020-11-27
    • 2018-03-05
    • 1970-01-01
    • 2021-11-22
    • 2023-03-24
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多