如何在Ubuntu16.04上使用Nginx代理DigitalOceanSpaces
注意: 自本教程发布以来,DigitalOcean Spaces 添加了一个免费的 CDN 选项,其中包含可自定义的端点子域。 此 CDN 功能提供下面介绍的大部分功能,包括缓存、自定义域、SSL 以及将资产移近用户。
请阅读 官方 Spaces 产品文档 了解如何 启用 CDN 和 自定义 CDN 端点。
介绍
DigitalOcean Spaces 是与 S3 API 兼容的 对象存储 服务。 在本教程中,我们将向您展示如何使用 Nginx 代理对您空间上的对象的请求。 Nginx 将接收来自您的用户的 HTTP(S) 请求并将它们传递给 Spaces 服务,该服务将通过 Nginx 将结果发送回。
您可能希望在 Spaces 前面放置 Nginx 代理的一些原因是:
- 添加自定义域
- 添加自己的缓存
- 使用您自己的 SSL 证书
- 使用不同的访问控制机制
- 在离用户更近的数据中心缓存资产
在本教程中,我们将设置 Nginx 来回答我们自己域上的请求(使用可选的 Let's Encrypt SSL 证书)并将这些请求转发到具有 public 资产的空间。 然后,我们将添加缓存以加快对频繁访问的对象的后续响应。
先决条件
要完成本教程,您应该具备以下条件:
安装了 Nginx 的 Ubuntu 16.04 服务器,如我们的教程 How To Install Nginx on Ubuntu 16.04 中所述
根据 如何使用 DigitalOcean 设置主机名,指向您的服务器的域名。 我们将在本教程中使用 assets.example.com
一个数字海洋空间。 您可以通过阅读 DigitalOcean Spaces 简介 了解如何创建新空间。
您需要知道个人空间的 URL。 您可以通过在 DigitalOcean 控制面板中导航到您的空间来找到它。 URL 位于 UI 中空间名称的正下方。 这在下面的屏幕截图中突出显示:
您还需要将文件上传到您的空间以进行测试。 前面提到的 Spaces 文章展示了如何使用 Spaces Web GUI 上传文件。 我们将在本教程中使用
example.png
。
设置代理
在 Ubuntu 上默认安装 Nginx 将为所有请求返回 Welcome to Nginx 占位符页面。 我们需要添加一些新配置来告诉 Nginx 对我们的域的请求执行其他操作。
为此,请在 /etc/nginx/sites-available
中打开一个新的配置文件:
sudo nano /etc/nginx/sites-available/assets.example.com
这将在 nano
文本编辑器中打开一个空白文件。 粘贴以下配置,确保将突出显示的部分替换为您自己的域名和 Spaces URL:
/etc/nginx/sites-available/assets.example.com
server { listen 80; listen [::]:80; server_name assets.example.com; location / { proxy_pass https://example.nyc3.digitaloceanspaces.com/; proxy_hide_header Strict-Transport-Security; } }
完成后保存文件并退出编辑器。 这是一个标准的 Nginx server
块。 首先我们告诉它监听 IPv4 和 IPv6 上的端口 80
,并指定 Nginx 应该响应的 server_name
。
接下来我们创建一个 location
块。 此块中的任何配置指令(在 {
和 }
大括号之间)将仅适用于特定 URL。 在这种情况下,我们指定 /
,即根 URL,因此所有位置都将被此块匹配。
proxy_pass
指令告诉 Nginx 将请求传递给指定的服务器。 proxy_hide_header
行在将响应传递回客户端之前去除了 Strict-Transport-Security
标头。 Spaces 使用此标头强制所有连接到 HTTPS。 如果您的站点可通过 HTTP 和 HTTPS 连接访问,则将此标头传递给您的用户可能会产生意想不到的后果。
现在我们的配置已经设置好了,我们需要启用它。 这是通过在 /etc/nginx/sites-enabled/
目录中创建指向配置文件的链接来完成的:
sudo ln -s /etc/nginx/sites-available/assets.example.com /etc/nginx/sites-enabled/
要检查我们的配置语法,请以 root 身份运行 nginx -t
:
sudo nginx -t
Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
最后,重新加载 Nginx 以获取新配置:
sudo systemctl reload nginx
设置好配置文件后,让我们测试代理。
测试代理
我们可以在命令行使用 curl
测试代理连接。 curl -I
将仅返回响应的 HTTP 标头。 这足以确定一切运行良好。
首先,使用 digitaloceanspaces.com URL 直接从您的空间中获取对象。 我们将使用我们的 example.png
文件:
curl -I https://example.nyc3.digitaloceanspaces.com/example.png
OutputHTTP/1.1 200 OK Content-Length: 81173 Accept-Ranges: bytes Last-Modified: Tue, 28 Nov 2017 21:19:37 GMT ETag: "7b2d05a5bd1bfeebcac62990daeafd14" x-amz-request-id: tx000000000000000002398-005a1edfcd-afba2-nyc3a Content-Type: image/png Date: Wed, 29 Nov 2017 16:26:53 GMT Strict-Transport-Security: max-age=15552000; includeSubDomains; preload
我们可以通过输出第一行的 200 OK
看到这是一个成功的请求。 服务器返回文件的大小 (Content-Length
)、文件类型 (Content-Type
) 和其他一些与日期和缓存相关的信息。
现在通过代理获取相同的文件:
curl -I http://assets.example.com/example.png
OutputHTTP/1.1 200 OK Server: nginx/1.10.3 (Ubuntu) Date: Wed, 29 Nov 2017 16:27:24 GMT Content-Type: image/png Content-Length: 81173 Connection: keep-alive Accept-Ranges: bytes Last-Modified: Tue, 28 Nov 2017 21:19:37 GMT ETag: "7b2d05a5bd1bfeebcac62990daeafd14" x-amz-request-id: tx00000000000000000a045-005a1edfec-a89a3-nyc3a
反应大多相同。 主要变化是标识 Nginx 的 Server
标头。 如果您的输出相似,则您的代理工作正常!
在下一步中,我们将设置缓存以减少代理和空间之间的带宽使用,并加快响应时间。
设置缓存
为了缓存响应,Nginx 需要一个地方来存储键、元数据和实际的响应内容。 我们将在系统的/tmp
目录中设置一个缓存目录。 为此,我们将在 /etc/nginx/conf.d/
中的新文件中添加一个配置片段。 现在打开该文件:
sudo nano /etc/nginx/conf.d/example-cache.conf
粘贴以下行,然后保存并关闭文件:
/etc/nginx/conf.d/example-cache.conf
proxy_cache_path /tmp/example-cache/ levels=1:2 keys_zone=example-cache:16m max_size=10g inactive=60m use_temp_path=off;
这一行定义了缓存的一些特征。 让我们来看看这些选项:
/tmp/example-cache/
是缓存的路径。levels=1:2
设置两级目录层次结构来存储缓存的内容。 将太多文件放在单个目录中会导致速度和可靠性问题,因此 Nginx 将基于此选项在多个目录之间拆分文件。keys_zone=example-cache:16m
命名我们的缓存并设置 16 兆字节的内存来存储密钥。 这应该足够存储超过 100,000 个键的数据。max_size=10g
将缓存大小限制为 10 GB。 您可以对其进行调整以适应您的存储和使用需求。inactive=60m
表示 Nginx 将在 60 分钟后删除缓存的文件,如果在这段时间内没有被访问(即使文件仍然有效且未过期)。 如果你有很多不经常访问的对象,你可能想尝试增加这个。use_temp_path=off
指示 Nginx 将临时文件写入缓存目录,从而可能避免在文件系统之间复制文件的需要,这可能会影响性能。
现在我们已经定义了一个缓存,我们需要在我们的服务器块中启用它,并设置一些额外的选项。 再次打开站点的配置文件:
sudo nano /etc/nginx/sites-available/assets.example.com
将以下内容添加到 location /
块的末尾(在 proxy_hide_header
指令之后,但在结束 }
括号之前):
/etc/nginx/sites-available/assets.example.com
. . . proxy_cache example-cache; proxy_cache_valid 200 60m; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_revalidate on; proxy_cache_lock on; proxy_ignore_headers Set-Cookie; add_header X-Cache-Status $upstream_cache_status; . . .
保存并关闭文件。 让我们一一浏览这些配置选项:
proxy_cache
告诉 Nginx 使用哪个缓存。 在这种情况下,我们指定了example-cache
,我们刚刚在example-cache.conf
文件中设置了它。proxy_cache_valid
指示 Nginx 考虑任何有效期为 60 分钟的200
响应。 这意味着在代理从 Spaces 成功获取文件后,在接下来的 60 分钟内,Nginx 将使用缓存的副本,而无需向 Spaces 请求更新。 请注意,如果您的对象设置了Cache-Control
标头,则标头的值将覆盖此配置。proxy_cache_use_stale
允许 Nginx 在 Spaces 服务器超时、返回错误或缓存响应正在更新时返回陈旧(过期)响应。proxy_cache_revalidate
使代理能够使用 条件 GET 请求重新验证缓存文件。 这意味着当缓存文件过期时,Nginx 需要检查 Spaces 是否有更改,Nginx 将使用If-Modified-Since
或If-None-Match
标头仅在对象确实已更改时才获取该对象。 如果尚未更新,Spaces 将返回304 Not Modified
响应,Nginx 将简单地将现有的缓存响应再次标记为有效。- 当代理已经从后端服务器获取对象时,
proxy_cache_lock
会暂停对对象的后续请求。 当第一个请求完成时,将从缓存中提供其他请求。 proxy_ignore_headers Set-Cookie
忽略 cookie,它会干扰缓存。add_header X-Cache-Status...
添加一个标头,其中包含有关是否从缓存 (HIT
) 或不是 (MISS
) 提供请求的信息。 如果请求在缓存中但已过期,您将看到 (REVALIDATED
) 代替。
我们现在可以验证我们的配置是否没有错误,如果成功,请重新加载 Nginx:
sudo nginx -t sudo systemctl reload nginx
设置好缓存后,我们可以再次测试以确保缓存按预期工作。
测试缓存
为了确保缓存正常工作,我们可以再次使用 curl
,并查找 X-Cache-Status
标头:
curl -I http://assets.example.com/example.png
OutputHTTP/1.1 200 OK Server: nginx/1.10.3 (Ubuntu) Date: Wed, 29 Nov 2017 18:40:28 GMT Content-Type: image/png Content-Length: 81173 Connection: keep-alive Last-Modified: Tue, 28 Nov 2017 21:19:37 GMT ETag: "7b2d05a5bd1bfeebcac62990daeafd14" x-amz-request-id: tx000000000000000013841-005a1eff1b-a89e4-nyc3a X-Cache-Status: MISS Accept-Ranges: bytes
第一个请求应该是 MISS
。 再试一次:
curl -I http://assets.example.com/example.png
OutputHTTP/1.1 200 OK Server: nginx/1.10.3 (Ubuntu) Date: Wed, 29 Nov 2017 18:40:53 GMT Content-Type: image/png Content-Length: 81173 Connection: keep-alive Last-Modified: Tue, 28 Nov 2017 21:19:37 GMT ETag: "7b2d05a5bd1bfeebcac62990daeafd14" x-amz-request-id: tx000000000000000013841-005a1eff1b-a89e4-nyc3a X-Cache-Status: HIT Accept-Ranges: bytes
一个HIT
! 我们现在正在代理和缓存来自 Spaces 的对象。 在下一步中,我们将设置 SSL 证书以保护与代理的通信。
设置 TLS/SSL
尽管此步骤是可选的,但强烈建议您的网站和资产通过安全的 HTTPS 连接可用。 您可以通过阅读我们的教程 如何在 Ubuntu 16.04 上使用 Nginx 服务器块设置 Let's Encrypt 来了解如何从 Let's Encrypt 证书颁发机构下载和安装免费证书。
结论
在本教程中,我们创建了一个 Nginx 配置来代理对 Spaces 服务的对象请求。 然后,我们添加了缓存以提高性能,并添加了 TLS/SSL 证书以提高隐私和安全性。
此处显示的设置是一个很好的起点,但您可能希望根据自己独特的流量模式和需求优化一些缓存参数。 Nginx 文档,特别是 ngx_http_proxy_module 可以提供有关可用配置选项的更详细信息。