您通过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
我们可以看到缺少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
"PageSpeed建议利用浏览器缓存"这意味着缺少Cache-Control。将Nginx作为S3文件的代理不仅解决了缺少标头的问题,还使用Nginx代理缓存节省了流量。我使用macOS,但是Nginx配置在Linux上的工作方式完全相同,无需修改。步骤如下:
1.安装Nginx。"
brew update && brew install nginx
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
![通过 Nginx 请求文件](https://istack.dev59.com/TQ6w8.webp)
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
![使用Nginx代理条件GET请求文件](https://istack.dev59.com/U0kFC.webp)
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
![使用 Nginx 代理缓存请求文件](https://istack.dev59.com/C69fH.webp)
根据 Nginx 官方文档,我提供了优化缓存设置的 Nginx S3 配置,支持以下选项:
- proxy_cache_revalidate 指示 NGINX 在从源服务器刷新内容时使用条件 GET 请求
- proxy_cache_use_stale 指令的 updating 参数指示 NGINX 在更新正在下载的项目时,当客户端请求某个项目时提供陈旧内容,而不是将重复请求转发到服务器
- 启用proxy_cache_lock,如果多个客户端请求未在缓存中(MISS)的文件,则只允许第一个请求通过到源服务器
Nginx 配置:
worker_processes 1;
daemon off;
error_log /dev/stdout info;
pid /usr/local/var/nginx/nginx.pid;
events
http
location /s3_cached/
}
}