Nginx代理Amazon S3资源

Rob*_*ber 57 proxy nginx amazon-s3 amazon-web-services http-headers

我正在执行一些WPO任务,因此PageSpeed建议我利用浏览器缓存.我已经成功改进了我的Nginx服务器中的一些静态文件,但是仍然缺少存储在Amazon S3服务器中的图像文件.

我已经阅读了有关更新S3中每个文件的方法,以包含一些标头元标记(Expires和Cache-Control).我认为这不是一个好方法.我有成千上万的文件,所以这对我来说不可行.

我认为最方便的方法是配置我的Nginx 1.6.0服务器来代理S3文件.我已经读过这个,但我在服务器配置上并不熟练,所以我从这些网站得到了几个例子:https://gist.github.com/benjaminbarbe/1961db5ffbaad57eff12

我在我的nginx配置文件中的服务器块中添加了这个位置代码:

#inside server block
location /mybucket.s3.amazonaws.com/ {


        proxy_http_version     1.1;
        proxy_set_header       Host mybucket.s3.amazonaws.com;
        proxy_set_header       Authorization '';
        proxy_hide_header      x-amz-id-2;
        proxy_hide_header      x-amz-request-id;
        proxy_hide_header      Set-Cookie;
        proxy_ignore_headers   "Set-Cookie";
        proxy_buffering        off;
        proxy_intercept_errors on;      
        proxy_pass             http://mybucket.s3.amazonaws.com;
      }
Run Code Online (Sandbox Code Playgroud)

当然,这对我不起作用.我的请求中不包含标头.所以,首先我认为请求与位置不匹配.

Accept-Ranges:bytes
Content-Length:90810
Content-Type:image/jpeg
Date:Fri, 23 Jun 2017 04:53:56 GMT
ETag:"4fd0be549fbcaf9b47c18a15146cdf16"
Last-Modified:Tue, 09 Jun 2015 09:47:13 GMT
Server:AmazonS3
x-amz-id-2:cKsq1qRra74DqVsTewh3P3sgzVUoPR8aAT2NFCuwA+JjCdDZfk7/7x/C0WPjBa51GEb4C8LyAIc=
x-amz-request-id:94EADB4EDD3DE1C1
Run Code Online (Sandbox Code Playgroud)

Ana*_*oly 112

您通过Nginx代理S3文件的方法很有意义.它解决了许多问题,并带来额外的好处,如屏蔽URL,代理缓存,通过卸载SSL/TLS加速传输.你做的几乎是正确的,让我展示剩下的东西让它变得完美.

对于示例查询,我使用S3存储桶和原始问题的公共评论中提到的图像URL .

我们首先检查Amazon S3文件的标头

curl -I http://yanpy.dev.s3.amazonaws.com/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg

HTTP/1.1 200 OK
Date: Sun, 25 Jun 2017 17:49:10 GMT
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Accept-Ranges: bytes
Content-Type: binary/octet-stream
Content-Length: 378843
Server: AmazonS3
Run Code Online (Sandbox Code Playgroud)

我们可以看到丢失的Cache-Control,但已经配置了条件GET头.当我们重用E-Tag/Last-Modified(这就是浏览器的客户端缓存如何工作)时,我们得到HTTP 304以及空的Content-Length.对此的解释是客户端(在我们的例子中为curl)查询资源,说除非在服务器上修改了文件,否则不需要数据传输:

curl -I http://yanpy.dev.s3.amazonaws.com/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg 
--header "If-None-Match: 37a907fc5dd7cfd0c428af78f09e95a9"

HTTP/1.1 304 Not Modified
Date: Sun, 25 Jun 2017 17:53:33 GMT
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Server: AmazonS3

curl -I http://yanpy.dev.s3.amazonaws.com/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg 
--header "If-Modified-Since: Wed, 21 Jun 2017 07:42:31 GMT"

HTTP/1.1 304 Not Modified
Date: Sun, 25 Jun 2017 18:17:34 GMT
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Server: AmazonS3
Run Code Online (Sandbox Code Playgroud)

"PageSpeed建议利用浏览器缓存",这意味着缺少Cache = control.Nginx作为S3文件的代理不仅解决了丢失标头的问题,而且还使用Nginx代理缓存节省了流量.

我使用macOS,但Nginx配置在Linux上的工作方式完全相同而无需修改.一步步:

1.安装Nginx

brew update && brew install nginx
Run Code Online (Sandbox Code Playgroud)

2.将Nginx设置为代理S3存储桶,请参阅下面的配置

3.通过Nginx请求文件.请查看Server标头,我们现在看到的是Nginx而不是Amazon S3:

curl -I http://localhost:8080/s3/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg

HTTP/1.1 200 OK
Server: nginx/1.12.0
Date: Sun, 25 Jun 2017 18:30:26 GMT
Content-Type: binary/octet-stream
Content-Length: 378843
Connection: keep-alive
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Accept-Ranges: bytes
Cache-Control: max-age=31536000
Run Code Online (Sandbox Code Playgroud)

通过Nginx请求文件

4.使用条件GET使用Nginx代理请求文件:

curl -I http://localhost:8080/s3/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg 
--header "If-None-Match: 37a907fc5dd7cfd0c428af78f09e95a9"

HTTP/1.1 304 Not Modified
Server: nginx/1.12.0
Date: Sun, 25 Jun 2017 18:32:16 GMT
Connection: keep-alive
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Cache-Control: max-age=31536000
Run Code Online (Sandbox Code Playgroud)

使用带有条件GET的Nginx代理请求文件

5.使用Nginx代理缓存请求文件,请查看X-Cache-Status标头,其值为MISS,直到第一次请求后缓存预热

curl -I http://localhost:8080/s3_cached/img/blog/sailing-routes-around-croatia-central-dalmatia-islands/yachts-anchored-paradise-cove-croatia-3.jpg
HTTP/1.1 200 OK
Server: nginx/1.12.0
Date: Sun, 25 Jun 2017 18:40:45 GMT
Content-Type: binary/octet-stream
Content-Length: 378843
Connection: keep-alive
Last-Modified: Wed, 21 Jun 2017 07:42:31 GMT
ETag: "37a907fc5dd7cfd0c428af78f09e95a9"
Expires: Fri, 21 Jul 2018 07:41:49 UTC
Cache-Control: max-age=31536000
X-Cache-Status: HIT
Accept-Ranges: bytes
Run Code Online (Sandbox Code Playgroud)

使用Nginx代理缓存请求文件

基于Nginx官方文档,我提供了具有优化缓存设置的Nginx S3配置,该设置支持以下选项:

  • proxy_cache_revalidate指示NGINX在从源服务器刷新内容时使用条件GET请求
  • proxy_cache_use_stale指令的更新参数指示NGINX在客户端请求项目时提供过时内容,同时从源服务器下载更新,而不是将重复请求转发到服务器
  • 启用了proxy_cache_lock,如果多个客户端请求缓存中的当前文件(MISS),则只允许第一个请求通过源服务器

Nginx配置:

worker_processes  1;
daemon off;

error_log  /dev/stdout info;
pid        /usr/local/var/nginx/nginx.pid;


events {
  worker_connections  1024;
}


http {
  default_type       text/html;
  access_log         /dev/stdout;
  sendfile           on;
  keepalive_timeout  65;

  proxy_cache_path   /tmp/ levels=1:2 keys_zone=s3_cache:10m max_size=500m
                     inactive=60m use_temp_path=off;

  server {
    listen 8080;

    location /s3/ {
      proxy_http_version     1.1;
      proxy_set_header       Connection "";
      proxy_set_header       Authorization '';
      proxy_set_header       Host yanpy.dev.s3.amazonaws.com;
      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;
      add_header             Cache-Control max-age=31536000;
      proxy_pass             http://yanpy.dev.s3.amazonaws.com/;
    }

    location /s3_cached/ {
      proxy_cache            s3_cache;
      proxy_http_version     1.1;
      proxy_set_header       Connection "";
      proxy_set_header       Authorization '';
      proxy_set_header       Host yanpy.dev.s3.amazonaws.com;
      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_cache_revalidate on;
      proxy_intercept_errors on;
      proxy_cache_use_stale  error timeout updating http_500 http_502 http_503 http_504;
      proxy_cache_lock       on;
      proxy_cache_valid      200 304 60m;
      add_header             Cache-Control max-age=31536000;
      add_header             X-Cache-Status $upstream_cache_status;
      proxy_pass             http://yanpy.dev.s3.amazonaws.com/;
    }

  }
}
Run Code Online (Sandbox Code Playgroud)

  • 亲爱的阿纳托利,谢谢你的工作.我正在尝试使用它,但它仍然产生"MISS"缓存,而我添加`proxy_cache_valid 200 60m;`希望它有助于某人. (2认同)
  • 我直接复制了你添加的代码块.但是,当我添加`proxy_cache_valid 200 60m;`它开始HIT了.我相信它可能与NginX版本有关.我是1.6.0谢谢@Anatoly和@OlegMykolaichenko! (2认同)

小智 5

如果没有Nginx编译模块的详细信息,我们可以说两种向所有文件添加Expires和Cache-Control标头的方法。

Nginx S3代理

这就是您要问的问题-使用Nginx在S3文件上添加过期的缓存控制标头。

Nginx 这个set-misc-nginx-module支持Nginx S3代理&更改/添加到期所需,它可以动态进行缓存控制。这是一个从编译到使用的标准完整指南对于Ubuntu服务器的nginx-extras来说是一个很好的指南。这是WordPress示例的完整指南

还有更多的S3模块用于处理其他事情。如果没有这些模块,Nginx将无法理解,并且config test(nginx -t)将以错误的配置通过测试。set-misc-nginx-module是您需要的最低要求。您想要的关于此Github要点的更好示例

由于并非全部都用于编译,并且设置确实有点困难,因此我也正在编写​​一种方法来为一个Amazon S3存储桶中的所有文件设置Expires和Cache-Control标头。

Amazon S3存储桶到期和缓存控制标头

此外,还可以使用脚本或命令行为一个AWS S3存储桶中的所有对象设置Expires和Cache-Control标头。Github上有许多这样的免费库和脚本,例如本库,bucket ExplorerAmazon的工具Amazon的this docthis doc。该cp CLI工具的命令将如下所示:

aws s3 cp s3://mybucket/ s3://mybucket/ --recursive --metadata-directive REPLACE \
--expires 2027-09-01T00:00:00Z --acl public-read --cache-control max-age=2000000,public
Run Code Online (Sandbox Code Playgroud)