温馨提示:
本文所述内容具有依赖性,可能因软硬条件不同而与预期有所差异,故请以实际为准,仅供参考。
一、背景
Google Cloud CDN(内容交付网络)使用 Google 的 全球分布式边缘点 来缓存与用户接近的 HTTP(S)负载平衡内容。在 Google 网络边缘缓存内容可以更快地向用户提供内容传输,同时降低服务成本。
这篇文章将介绍如何利用 GCE(Google Compute Engine) 建立一个 Anycast 网络,想要实现这个功能,就需要使用 Cross-Region Load Balancing(跨地区的负载均衡),此功能就相当于一个 HTTP(S) 的反向代理,所以只能针对 HTTP/HTTPS 请求进行负载均衡。
二、概述
GCE 上所实现的这个功能是基于第七层的网络代理,所以其拓扑图是这样的:
用户 —> 边缘服务器 —> 实例
- 用户到边缘服务器之间的连接:使用 HTTP 或 HTTPS;如果是 HTTPS 连接,那么 TLS 加密过程是在边缘服务器上实现。
- 边缘服务器到实例的连接:使用 HTTP 或 HTTPS 连接,之前的网络是走的 Google 的专线。
不论配置了几个位置的实例,边缘服务器都是使用 Google 全部的边缘服务器。
启用这个功能后,就会得到另一个 Anycast 的 IP 地址,这是个独享的 IP 地址。
需要注意的是,Google CDN 仅适用于 Google 负载平衡器和云存储,这意味着如果不在GCP(Google Cloud Platform)上托管应用程序,那么将无法使用他们的 CDN,换句话说,就是不支持外部来源。 简单。
所以本文的实例是在 GCP 上运行,并使用负载平衡器(LB)来使用 Google CDN,你猜对了,Google CDN 也不能将 VM 作为原点,它只能在负载均衡器上启用。
三、配置
大致步骤:
建立实例 —> 建立实例组 —> 建立健康检查 —> 建立负载平衡器 —> 启用 CDN。
现已支持单个实例开启 CDN,
不需要
创建多个实例、多个实例组。创建实例组时选择非托管式实例组
即可。
如需更详细的实例配置详情,请参考《配置启用 Google Cloud CDN 实例详解》
1、建立实例
首先,需要前往到 GCE 后台,建立至少两个不同地区的实例,我专门为测试 Anycast 功能建立了三个新的实例:
每个地区也可以建立多个实例以提高可用性,而我只给每个地区建立了一个实例,分别为 gce-jp、gce-us 和 gce-sg。
2、建立实例组
实例组用于负载平衡设置,为 LB 的后端服务。需要给 每个地区 的实例建立一个实例组,三个地区 VM 就需要创建三个实例组,分别为 us-group、jp-group 和 sg-group:
需要注意的是,实例组配置页面中位置里的 “多地区(Multi-zone)” 是指同一个地区(Region)的不同可用区域(Zone),而不是多个不同的地区。
我只给每个地区建立了一个实例,所以我只需要选择 “单地区(Single-zone)”,因为
VM 虚拟机已经建好了,所以组类型选择非托管实例组。
3、建立健康检查
行状况检查对于负载均衡器确定 VM 是否健康至关重要,很多人无法成功开启 Google CDN 都是在这一步失败的。
当虚拟机无法响应查询时,负载均衡器会标记不健康并停止发送流量也就是说,负载均衡通过健康状态检查来判断流量走向,因此需要先创建健康检查:
检查支持 HTTP、HTTPS、TCP、SSL、HTTP/2,如果没有指定
主机 HTTP 标头
(即 Host,点请求路径下面的展开即可看到),那么将会检查默认站点,举个例子:假设服务器 IP 是 1.1.1.1,网站域名是 vircloud.net。
如果没有指定 主机 HTTP 标头
,那么检查的地址将是:http://1.1.1.1
,网站则是服务器配置中的第一个网站或者标记 default
的网站;如果指定 主机 HTTP 标头
为 vircloud.net
,那么检查的地址将是:http://vircloud.net
。
显然后者才是我们需要的检查目标,虽然可能不指定也可能可以检测成功,但不确定性较大,谁知道会不会哪天新建了一个 default 网站呢?所以建议标头设置为网站域名
。
4、建立负载均衡
接下来就需要建立负载均衡的规则了,需要选择 “HTTP(S) 负载平衡” 来实现 Anycast 的功能:
后端配置中,创建后端服务,把这三个实例组都添加到 “后端” 中,然后指定运行状态检查为上一步创建的检查(相当于监控功能,此例中名为 test ),当主机达到某个设定好的条件后能实现切换,会话粘性设为无:
主机和路径规则 保持默认即可:
前端配置中,可以单配或者一起配置 HTTP 及 HTTPS,也可以选择静态或者动态 IP,根据需要了,如果需要 HTTPS,那么还需要指定一个证书:
检查一下:
点击创建(名称不要忘记输了,本例中设为 all),成功后回到负载平衡就可以看到刚创建的平衡器了,点击可以看到如下界面,其中的 IP 地址就是 Anycast IP 了:
5、开启 CDN
在 CDN 下新建,来源选择刚创建的 负载平衡 即可:
至此,Google CDN 基本上就成功启用了。
6、Nginx 的配置
如果你只是单纯的使用 CDN,可以在另外的 VM 开启反代,以下的配置只是为了方便调试,实际使用并不需要。
在这两个主机上都安装 Nginx,然后稍微改动默认的配置文件:增加两个 Header,然后 Reload:
add_header X-Tlo-Hostname $hostname always;
add_header Cache-Control "max-age=36000, public";
7、检测是否可用
在测试 Anycast 之前,先测试这两个主机是否存在问题。为了方便阅读,我将 curl 的 IP 地址换为主机名,并省略两个主机都相同的 Header 字段
$ curl -I gce-us
HTTP/1.1 200 OK
...
ETag: "5a682aae-11"
X-Tlo-Hostname: gce-us
...
$ curl -I gce-jp
HTTP/1.1 200 OK
...
ETag: "5a682abd-12"
X-Tlo-Hostname: gce-jp
...
$ curl -I gce-sg
HTTP/1.1 200 OK
...
ETag: "5a682934-15"
X-Tlo-Hostname: gce-sg
...
可以看到这三个主机都没有什么问题,我们再测试 Anycast IP,新加坡主机访问:
$ curl -I anycast-ip
HTTP/1.1 200 OK
…
ETag: "5a682934-15"
X-Tlo-Hostname: gce-sg
Cache-Control: max-age=36000, public
Accept-Ranges: bytes
Via: 1.1 google
可以看到,这是 gce-sg 主机响应的,然后我们使用另一个在美国的主机继续测试这个 Anycast IP:
$ curl -I anycast-ip
HTTP/1.1 200 OK
…
ETag: "5a682aae-11"
X-Tlo-Hostname: gce-us
Cache-Control: max-age=36000, public
Accept-Ranges: bytes
Via: 1.1 google
此时就是 gce-us 主机响应的,是因为客户端离这个服务器更近,日本主机也是一样的:
$ curl -I anycast-ip
HTTP/1.1 200 OK
…
ETag: "5a682abd-12"
X-Tlo-Hostname: gce-jp
Cache-Control: max-age=36000, public
Accept-Ranges: bytes
Via: 1.1 google
当通过 Anycast IP 访问时,就可以看到 HTTP Header 中的 Via: 1.1 google 字段。
8、排错
如果发现访问 Google CDN Anycast IP 回应 502 Bad Gateway(no-referrer),如下:
$ curl -I anycast-ip
HTTP/1.1 502 Bad Gateway
Content-Type: text/html; charset=UTF-8
Referrer-Policy: no-referrer
Content-Length: 332
Date: Wed, 24 Jan 2018 12:22:40 GMT
那么首先应该考虑是不是运行状况设的有问题(VM 已经在上面测试过是正常的了),查看负载平衡器监控,发现几个 VM 都被判定不良:
Nginx 访问日志也报错:
那么很明显就是运行状况检查有问题了,回到运行状况检查一下,需要注意的地方在代理协议这边:
无特殊需求正确的应该设置为 无,设置好后 Nginx 日志就正常了:
检查也正常了:
再访问 Anycast IP 是不是正常了?
当然了,造成此问题的原因还有可能是防火墙、端口等,但相信你已经先排查一遍了。
额外提一句,运行状况检查生效可能会有延迟,且只有源站 VM 回应检查状态码为 200 时,运行状况检查才会认为源站是健康的,在开启 https 时要特别注意。
运行状况检查来源 IP 为:35.191.0.0/24,CDN 来源 IP 为:130.211.0.0/16,检查 User-Agent 为: GoogleHC/1.0,如果有开启相关防火墙记得放行。
9、速度测试
① Ping 测试
Ping 测试发现速度很快,看来反代的操作是放在 Google 的边缘服务器上了,速度真的很 Google 啊:
中国的速度那更是一流的快,Google 有香港的边缘节点,所以基本上是直接走的香港节点(只有部分 IP 段是完全直连的),比原本的连接台湾可用区快不少:
② HTTP GET 测试
在开启 CDN 功能之前,负载均衡器是不会对任何内容缓存的,所以会发现 Connect 的速度很快,但是 TTFB 延迟还是有不少:
可以预测,如果启用了 HTTPS 功能,其 TLS 所需要的等待时间也会很短,TTFB 时间不变,总时长不会延长太多。
③ 开启 CDN 后进行 HTTP GET 测试
当将 CDN 开启后,负载均衡器就会自动地对静态资源做缓存了,当缓存命中后会显示 Age 字段,这个字段是表示自缓存命中了,后面的数字代表这是多少秒之前缓存的内容。
curl anycast-ip -I
HTTP/1.1 200 OK
…
Via: 1.1 google
Age: 10
经过多次执行这个指令,会发现有一定几率 Age 字段消失,这可能是流量指到了同一个地区的不同可用区上。但总之,是缓存命中率不高,即使之前曾访问过了:
多次运行测试确保有缓存之后,发现速度似乎并没有太多明显的提升。能够明显的看出改善的是:巴黎和阿姆斯特丹的 TTFB 延迟从 200ms 减少到了 100ms,然而还是不尽人意。可能的原因是:Google 并没有将内容缓存到离访客最近的边缘节点上,而是别的节点上。
四、统计与日志
开启了 Load Balancing 后,就会自动在 Google Cloud Platform 下记录一些信息了。
1、实时流量查看
在网页后台的 Network,Load balancing,advanced menu 的 Backend service 下,可以查看实时的流量情况:
2、延迟日志
在网页后台的 Stackdriver,Trace 下,可以看到延迟日志:
这里的延迟包含了网络延迟和服务器响应延迟。
五、总结
GCE 所能实现的 Anycast 功能,只能通过 HTTP 代理(第七层)的方式实现,所以只能代理 HTTP 请求,其他功能(如 DNS)无法实现。所以很多功能受限于负载均衡器的功能(比如证书和 HTTP2 都需要在负载均衡器上配置),然而由于 TLS 加解密过程是在边缘服务器上实现,而且其本身也带有 CDN 功能,所以会比单纯的 Anycast(比如基于 IP 层,或是 TCP/UDP 层)的更快一些。
1、价格
前五个 Rules $18/月,流量费用相比 GCE 不变,已经被缓存的内容的流量有一点优惠。
2、节点
- 亚洲:香港、台湾、孟买、东京、新加坡、悉尼等 19 个
- 美洲、纽约、旧金山、西雅图、迈阿密、波哥大等 31 个;
- 欧洲:柏林、都柏林、米兰、伦敦、巴黎、华沙等 30 个
- 非洲:约翰内斯堡 1 个
3、对比
① Cloudflare
通过使用 Cloudflare 所提供的服务也能实现 Anycast,也是基于第七层的,即将也能实现 Cross-Region Load Balancing 的功能。虽然它还不能根据主机的 CPU 占用率去调整权重(毕竟它拿不到这些数据),却有强大的 Page Rules 功能以及 WAF 功能。
CloudFlare 并不提供独立 IP 地址,不过这不是什么大问题。
由于它属于第三方服务,不受服务提供商的限制,于是就可以给多种不同的服务提供商去做 Anycast 功能;而且无论服务商是否支持,都能够使用。
连接速度上,GCE 的在中国连接速度有明显的优势,目前部分地区已完全连不上 Cloudflare 了。
4、释疑
① 什么是 Anycast ?
Anycast 能够让多个主机使用一个 IP 地址,当用户连接这个 IP 地址的时候,连接到的只是这多个主机中的其中之一,通常会选择最快的线路,能有效的降低延迟,所以很多 DNS/CDN 提供商都使用了 Anycast。
② 区域的概念
刚接触云服务的人可能不理解可用区域的概念,可以参考 AWS 的这篇文章 来理解。简单点说,地区这个概念就是指离得很远的地区(比如城市之间,如北京和上海),所有在北京的服务器都算北京地区,所有在上海的服务器都算上海地区。但是为了能达到更高的可用性,通常还会在同一个地区设立多个数据中心,也就是可用区域。这些可用区域虽在一个地区中,其之间的距离可能相隔几十甚至几百公里,但这些可用区域之间的距离和不同地区之间的距离相比起来要小得多,所以这些可用区域之间的网络延迟也很低。
设立多个可用区域的意义是:可以能加更高的可用性(主要是为了避免外界因素:比如说火灾等),虽然是异地分布,但是可用区域之间的距离并不远,所以网络延迟可以忽略。
③ 什么是 TTFB ?
TTFB (Time To First Byte),是最初的网络请求被发起到从服务器接收到第一个字节这段时间,它包含了 TCP连接时间,发送HTTP请求时间和获得响应消息第一个字节的时间。
参考文章:
1、利用 GCE 建立一个 Anycast 网络,超快的香港节点,Google Cloud CDN
2、Cloud CDN Location
3、Cloud CDN Pricing
4、How to Implement Google Cloud CDN?
5、配置启用 Google Cloud CDN 实例详解
Mac OS X 10_15_6Chrome 84.0.4147.125来自 浙江 的大神
文章写得很棒,有点问题想请教下:CloudFlare 上面设置了 DNS,域名绑定到google负载均衡的Anycast IP,google CDN开启,ping 域名,发现返回的是Anycast IP,这个CloudFlare的cdn好像不太一样,CloudFlare开启cdn之后,客户端在ping 的时候返回的是cdn机器的ip,google cdn能做到这个吗
CloudFlare 也是 Anycast IP 的,就是说其实用 Google CDN ,客户端 ping 的时候也是 CDN 机器的 IP
Mac OS X 10_15_6Chrome 84.0.4147.125来自 浙江 的大神
博主大大好,上面我没表达清楚,我使用了google cdn,ping域名的时候,显示的是负载均衡机器的ip,而并不是google cdn机器ip,这跟cloudflare的行为不一致(cf cdn开启以后,ping域名显示的是cdn机器的ip),所以是我配置的问题,还是google cdn本来就是只能显示负载均衡的机器ip的?博主大大能不能一起研究下这跟问题
这个负载均衡 IP 是 Anycast IP 吗,是的话那就是这个了,不是的话估计是 CDN 就没开启成功,你按文章步骤重新验证一下看看
Mac OS X 10_15_6Chrome 85.0.4183.83来自 浙江 的大神
已经确认了cf也是负载均衡的ip,负载均衡ip不是anycast,是google cdn配置时候GFE的ip,请求访问后端的时候会记录cdn的any cast ip
按步骤操作基本可以成功。自己后台也要配置一下,还原客户端真实 IP,这个我也有写过相关文章,可以参考一下
AWS CloudFront CDN 详细图文部署教程及自选优质 IP 方法 | 我的文本
Mac OS X 10_16_0Chrome 79.0.3945.117来自 香港 的大神
请问文章里的ping图片 是在哪里ping 的
在线 ping 工具,ping Google 分配的 IP,诸如此类工具的有 https://ping.chinaz.com、https://tools.ipip.net/ping.php、https://www.wepcc.com、http://www.webkaka.com/Ping.aspx 等等,截图这个找不到了。
【GCP】CloudStorage_上傳下載_限制CDN存取 - Welcome