nginx 反向代理S3图片

在网页或APP中,使用S3公开的静态资源,比如图片,小视频等。通常有这么几个常用的方式

  • 直接在页面中使用S3的public链接
  • 使用自己的域名,再在Web服务器侧redirect到S3的链接
  • 使用自己的域名,再在服务器上经过反向代理服务,获取S3内容后再返回给客户端或浏览器。
  • 使用自己的域名,再服务器代码端获取S3内容后,再返回给客户端或者浏览器


    反向代理

    反向代理+缓存

使用Nginx来redirect S3的链接

如下是一个简单的Nginx的配置的例子。基于以下几个前提

  • 测试域名
  • 所有放在S3上的静态文件,在网站上都以/s3_redirect路径打头
  • S3 Region为us-west-2, Bucket 为s3-for-blog
  • /s3_redirect开头的文件redirect到真实的S3 URL中。
    nginx侧配置:
location ~ ^/s3_redirect/(.*) {

    return 301 https://s3-for-blog.s3-us-west-2.amazonaws.com/$1;
}

Chrome侧访问测试链接的截图如下, 可以看到nginx返回了301 redirect,将路径重定向到S3中。


image.png

使用Nginx作为反向代理获取S3内容

不使用Nginx Cache时

如下是一个简单的Nginx反向代理获取S3文件再返回给客户端的例子。基于以下几个前提

  • 测试域名
  • 所有放在S3上的静态文件,在网站上都以/s3_proxy路径打头
  • S3 Region为us-west-2, Bucket 为s3-for-blog
  • Nginx从后端S3中获取文件,再返回给客户端

nginx配置:

location /s3_proxy/ {
  proxy_http_version     1.1;
  proxy_set_header       Connection "";
  proxy_set_header       Authorization '';
  proxy_set_header       Host s3-for-blog.s3-us-west-2.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             https://s3-for-blog.s3-us-west-2.amazonaws.com/;
}

测试连接域名/s3_proxy/kulipa.jpg
Chrome侧访问测试链接的截图如下,整个过程对于客户端来说,只有200的response。

image.png

curl 命令输出:

$ curl -L -I 域名/s3_proxy/kulipa.jpg
HTTP/1.1 200 OK
Server: nginx/1.14.0
Date: Thu, 21 Mar 2019 09:18:58 GMT
Content-Type: image/jpeg
Content-Length: 10857
Connection: keep-alive
Last-Modified: Wed, 20 Mar 2019 05:58:56 GMT
ETag: "d98f298bce5a81e41ca8f278324c5056"
Accept-Ranges: bytes
Cache-Control: max-age=31536000

和上面direct方式相比,由于nginx的配置,少了amazon自定义的以x-amz打头的一些header, 并且header Server变为了nginx/xxxx,而不是AmazonS3

使用nginx cache缓存文件

如下是一个简单的Nginx反向代理获取S3文件,缓存后再返回给客户端的例子。基于以下几个前提

  • 测试域名
  • 所有放在S3上的静态文件,在网站上都以/s3_proxy_cache路径打头
  • S3 Region为us-west-2, Bucket 为s3-for-blog
  • Nginx从后端S3中获取文件,返回给客户端,并缓存在本地

nginx配置:

http {
    ....
    proxy_cache_path   /tmp/ levels=1:2 keys_zone=s3_proxy_cache:10m max_size=500m
                     inactive=60m use_temp_path=off;
    ....
    server {
      ......
      location /s3_proxy_cache/ {
        proxy_cache            s3_proxy_cache;
        proxy_http_version     1.1;
        proxy_set_header       Connection "";
        proxy_set_header       Authorization '';
        proxy_set_header       Host [s3-for-blog.s3-us-west-2.amazonaws.com](http://s3-for-blog.s3-us-west-2.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             [https://s3-for-blog.s3-us-west-2.amazonaws.com/](https://s3-for-blog.s3-us-west-2.amazonaws.com/);

      }
      ......
    }
}

测试链接域名/s3_proxy_cache/kulipa.jpg

Chrom访问测试链接的截图如下,对客户端来说,只有200的response。


image.png

curl 命令输出:

$ curl -L -I 域名/s3_proxy_cache/kulipa.jpg
HTTP/1.1 200 OK
Server: nginx/1.14.0
Date: Fri, 22 Mar 2019 05:34:25 GMT
Content-Type: image/jpeg
Content-Length: 10857
Connection: keep-alive
Last-Modified: Wed, 20 Mar 2019 05:58:56 GMT
ETag: "d98f298bce5a81e41ca8f278324c5056"
Cache-Control: max-age=31536000
X-Cache-Status: MISS
Accept-Ranges: bytes
$
$ curl -L -I 域名/s3_proxy_cache/kulipa.jpg
HTTP/1.1 200 OK
Server: nginx/1.14.0
Date: Fri, 22 Mar 2019 05:34:27 GMT
Content-Type: image/jpeg
Content-Length: 10857
Connection: keep-alive
Last-Modified: Wed, 20 Mar 2019 05:58:56 GMT
ETag: "d98f298bce5a81e41ca8f278324c5056"
Cache-Control: max-age=31536000
X-Cache-Status: HIT
Accept-Ranges: bytes
$

可以看到第一次X-Cache-Status状态是MISS,第二次请求就是HIT了。
缓存地址示例

root@ip-192-168-2-161:/tmp/7/56# ls
1ddbbdeff2d2ad676c7adbd09fd9a567
缓存的数据

注意点:

  1. 如果重启nginx时,有"proxy_cache_path" directive is not allowed here in的错误提示时,则需要检查一下proxy_cache_path是不是没有放在配置文件的http下。
  2. 当proxy_cache_path中设置了缓存目录为/tmp,但在/tmp/目录下,却没有找到缓存的文件时。别慌,记得查看下/lib/systemd/system/nginx.service中的PrivateTmp值有没有设为true,如果是true的话,在类似/tmp/systemd-private-1adb681dede84276b650ea38bfa4dc1d-nginx.service-z9XRZN/tmp这样的目录下找一下。

Reference

推荐阅读更多精彩内容