前言
对象存储 OSS 是经常被用于网盘存储的底层 PaaS 产品之一,但是在接触过程中很多的客户都表示使用对象存储 OSS 就怕流量控制不住,如果是企业网盘万一员工大量下载大容量文件就会导致添加流量账单。
那么是否有办法给对象存储“限速”呢?比如说限制到100Mbps带宽或者50Mbps带宽,这样就不怕流量费用控制不住了,自己也有一个清楚的网络费用预算。
那么针对这个需求,我们就可以使用 Nginx S3 Gateway 来作为对象存储的网关,对象存储和公网云服务器之间用内网传输,这样就可以“限速” OSS了。
因为对象存储 OSS 是支持 S3 兼容协议的,所以我们可以使用 NGINX S3 Gateway 来实现我们想要实现的“限速”功能。
Nginx S3 Gateway 的场景
很多人其实会纳闷,“对象存储已经在大规模为文件传输和存储提供服务了,何必在前面又多加一层呢?”
答案很简单:S3、OSS 等对象存储只擅长一件事情:存储和检索对象。
而 Nginx 是一个高度可配置的反向代理,能够在作为基础对象存储网关的前提下提供更多功能。因此,它可以很好地支持多种用例,其中包括以下这些典型用例。
场景一:高速缓存
对象存储系统是为存储大量数据而生,故并没有针对重复检索相同对象(例如文件或二进制数据)的情况进行优化。一般认为,最好的做法是在对象存储前面设置一个缓存层,以防止不必要的读取操作。使用 Nginx 作为缓存网关可以减少对象传递的延迟,防止中断,并降低使用成本。 当然了,用户也可以使用 CDN 产品帮助 OSS 优化这个场景,但是本文的“限速” 和 固定带宽的场景不是 CDN 所擅长的,CDN 擅长的是无上限的内容分发和加速。
场景二:安全控制
虽然 S3 有自己的身份验证和基于策略的访问系统,但不一定能满足您特定的身份验证需求。NGINX 支持多种不同的安全控制因此作为网关的它可以提供符合这些需求的身份验证和访问控制。用户甚至可以使用安全链路模块创建带签名的链接!
场景三:访问内部应用
基于 AWS 签名的身份验证并不好实现,许多应用和平台都没有支持与 S3 轻松通信的客户端库。通过将 NGINX 用作访问 S3 的内部服务的网关,这些应用无需生成 AWS 签名便可轻松访问 S3 资源。
场景四:内容压缩和优化
很多用户都会希望压缩对象存储中的数据以节省存储成本,但仍然能够为不支持压缩的客户端提供内容。在这种情况下,您可以配置 Nginx 使其在数据发送之前对其进行实时解压缩处理。
又或者,您可能会在对象存储中存储未压缩的内容,然后希望通过在传输之前压缩数据来缩短传输时间。在这种情况下,您可以配置内置的 Gzip 模块或 Brotli 动态模块,以缩短到终端用户的传输时间。
Nginx 还支持其他类型的实时内容修改,例如 Image-Filter 动态模块可以转换 GIF、JPEG 和 PNG 图像,PageSpeed 等工具能够将 Web 性能的最佳实践自动应用到页面和相关多媒体资源,从而缩短页面加载时间。
当然压缩和优化功能很多对象存储也都附带了这个功能,但会额外收取请求数的费用,如果用户想要控制预算的话,用 Nginx 模块 + S3 Gateway 也是一个不错的控制预算的场景。
场景五:安全性
Nginx 允许用户在 S3 API 前面构建另一个安全层,从而可以对发出过多下载请求的用户进行速率限制、限制存储桶内可以访问的对象路径等。还可以使用 ModSecurity WAF 等集成式 Web 应用防火墙 (WAF) 保护 S3 API。
场景六:应用网关
从站点提供内容时,对所有资源使用同一域名来满足安全、品牌、一致性和可移植性的要求十分常见。因此,从同一主机同时提供静态和动态内容也是常有的需求。当被用作 S3 API 网关时,Nginx 不仅可以从对象存储中提供静态文件,而且还可以针对来自应用服务器的动态内容请求提供代理和负载均衡功能。
特性和限制
本文探讨的 NGINX S3 Gateway 实现具有以下特性和限制:
- 支持 AWS 签名版本 2 和 版本 4
- 仅支持
GET
和HEAD
请求 - 支持 NGINX 开源版和 NGINX Plus
- 支持单个存储桶
- 缓存时长:1 小时
- 未配置 SSL/TLS
- 默认情况下未安装 WAF
- 默认情况下未启用压缩(例如 GZIP 或 Brotli)
- 代理缓冲设置为默认值(您可以根据您的工作负载和对象大小修改这些设置)
教程
一、配置变量
首先,我们需要创建一个变量文件,方便后续引入一些配置信息。
S3_BUCKET_NAME=mf8bizbucket //OSS的Bucket 名称 S3_ACCESS_KEY_ID=ZTAI5t158dszmf8bizKdrNN //OSS 的访问控制子账户 AK S3_SECRET_KEY=ZLuhjLfYOBh1mf8bizopHntUG //OSS 的访问控制子账户 AKSK S3_SERVER=oss-ap-southeast-1-internal.aliyuncs.com //OSS 的内网 Endpoint 地址 S3_SERVER_PORT=80 //OSS访问端口 S3_SERVER_PROTO=http //OSS的访问协议 S3_REGION=ap-southeast-1 //OSS的地域名称 S3_STYLE=virtual //OSS只能填这个,默认 ALLOW_DIRECTORY_LIST=false //是否允许展示文件目录列表 S3_DEBUG=false //是否Debug AWS_SIGS_VERSION=4 //签名版本,OSS 支持 4,那么就用最新的 PROXY_CACHE_VALID_OK=1h //设置响应代码200和302的缓存时间 PROXY_CACHE_VALID_NOTFOUND=1m //设置响应代码404的缓存时间 PROXY_CACHE_VALID_FORBIDDEN=30s //设置响应代码403的缓存时间
例如将这个文件存到 /opt/mf8/biz/settings
这个文件。
1.如果不知道 Region ID 和 Endpoint 的名称,可以查看:
https://help.aliyun.com/document_detail/31837.html
2.因为是走的内网,所以S3_SERVER_PORT
和S3_REGION
,都是按 HTTP 协议来的,如果有公网的链接需求,建议按 HTTPS 协议,即 443 端口来。
二、运行 S3 Gateway
Nginx S3 Gateway 的运行依赖 Nginx 和 nginx-module-njs 和 nginx-module-xslt 两个模块,本文将以 Docker 容器的方式运行 S3 Gateway,如果有在本机运行作为 systemd 服务的话,可以参考 这个 Ubuntu 示例脚本。
1.安装 Docker,这里以 Ubuntu/Debian 快速安装为例
国内服务器运行:
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
海外服务器运行:
curl -fsSL https://get.docker.com | bash -s docker
2.然后运行 S3 Gateway 容器,这里我用 80 端口直接显示了,用于测试,生产场景建议用非标端口。
docker run -itd --restart=always \ --env-file /opt/mf8/biz/settings \ -p 80:8080 --name nginx-s3-gateway \ nginxinc/nginx-s3-gateway:latest
3. 查看,如下图所示,我在OSS传输一张图片:
4. 查看 S3 Gateway 是否运行:
说明我们的 S3 Gateway 已经运行成功。
那么在一些网盘或者附件媒体中设置,只需要将对象存储的域名、CDN地址等改成运行 S3 Gateway 的路径即可。
进阶
成功运行 Docker 容器版的 S3 Gateway 后,其实我们只是正常将私有权限的 Bucket 可以向公网、内网传输了。
但是,如果我们想要绑定域名、运行HTTP/2,或者向前文内容介绍的一样,运行WAF或者应用压缩,我建议是将 S3 Gateway 容器放在后端,用本机的 Nginx 或者阿里云的 ALB 应用负载均衡去进行反代。