新西兰华人网页设计公司|我们的后端工程师David总结的静态站点加速访问经验,通过 Google CDN 加速,如何让你的网站在一秒钟内打开

大家好,我是新西兰软件开发公司local fern的程序员David,最近因工作需要,需要将客户的网站提高访问速度,用到了 Google Cloud Platform的cdn。
 
如果更近一步,除了新西兰本地外,想要让大陆地区访问速度更加快一些的话,我们可以考虑将站点内容放在 Google Cloud Platform 的 Storage 中,并且使用 Google CDN 进行全网加速(主要是因为国内大部分线路可以不绕路使用到香港边缘节点).

本文假设:

你有 Google Cloud Platform 账户,并懂得一些基本操作
在自己的机器上安装了 Google Cloud SDK,如果没有的话,参考 《挂载 Google Storage 到 VPS 文件系统》
账户中已经验证好了自己的域名,如果没有的话,参考 Domain ownership verification
获取 SSL 证书
除非希望托管一个 HTTP 的网站,否则一个证书是必不可少的,Google 不会帮你自动完成这一步。

有多种方式可以获取一个 SSL 证书,如果目前手头没有的话,我们通过 Let’s Encrypt 申请一个好了,首先获取 certbot:
$ git clone https://github.com/certbot/certbot.git
$ cd certbot

由于我自己的一些原因(在迁移前域名解析到 GitHub Pages 上的,不能通过改变解析的方式验证,否则会造成博客访问中断),这里我使用了 DNS 的方式进行获取:
$ ./certbot-auto certonly --manual  --preferred-challenges=dns  --email [email protected] --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d nova.moe

之后会看到一个修改域名 TXT 记录的要求,类似如下:
 

Please deploy a DNS TXT record under the name _acme-challenge.nova.moe with the following value: J50GNXkhGmKCfn-0LQJcknVGtPEAQ_U_WajcLXgqWqo
 
 
 
此时我们只需要做一个 _acme-challenge 的 TXT 解析,内容为上述的 J50G...qo 即可。

如果没有遇到的问题的话我们就可以看到生成好的证书信息,类似如下:
 
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/nova.moe/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/nova.moe/privkey.pem

 
此时通过任何你喜欢的方式把 fullchain.pem 和 privkey.pem 下载到自己本地。

创建 Storage 桶,配置权限,导入文件
创建 Storage 桶

新建一个 Storage 容器,名称就是你希望的域名
 
 

 
 
 
配置权限

由于是对外提供内容的网站,我们需要把 Public Access 设置为 Public 并且为网站配置优化,具体方法如下:

 
 
 
 
 
 
点击最右边的选项,选择 Edit bucket permissions,添加一个 allUsers 账户,权限为 Storage Object Viewer

还是那个选项,选择 Edit website configuration,按照如下填入 index.html 和你的站点 404 页面(比如我的就是 404.html)
 
 

 
 
 
 
导入文件

注意,这里不要参考 《挂载 Google Storage 到 VPS 文件系统》,挂载到本地目录后上传,因为这样会导致文件的 meta 信息错误,导致本来该渲染为图片的地方变成了 octec-stream,本来该是网页的地方变成了 octec-stream ,本来… 然后访问任何页面都是弹出一个下载框了。

正确方法是使用 gsutil 来上传,语法如下:
$ gsutil cp -r dir gs://my-bucket
其中 dir 就是源目录,假设我的博客放在 /var/www/nova.moe/ 目录下 ,my-bucket 是目标 Storage 桶地址,比如我的就是 gs://nova.moe,整理一下就是:
$ gsutil /var/www/nova.moe/* -r dir gs://www.yourdomain.com

可能有同学想到这里如果用 gsutil rsync 的话会不会更好一些,毕竟有增量同步之类的。

不是这样的,这样做的话即不能保留 meta 信息,也不会增量同步,相关描述如下:

Note that by default, the gsutil rsync command does not copy the ACLs of objects being synchronized and instead will use the default bucket ACL (see gsutil help defacl).

The gsutil rsync command copies changed files in their entirety and does not employ the rsync delta-transfer algorithm to transfer portions of a changed file. This is because cloud objects are immutable and no facility exists to read partial cloud object checksums or perform partial overwrites.
 
 
 
设置 Load Balancer

创建一个 HTTP/HTTPS 的 Load Balancer,Backend 创建一个 Backend Bucket,选择刚刚创建的 Storage 桶并勾选 Enable Cloud CDN:

 
 
 
Frontend 那一块选择 HTTPS:
 

 
 
然后导入 SSL 证书,其中 Public Key 和 Chain 全部上传 fullchain.pem, Private Key 就上传 privkey.pem :
 

 
 
 
创建好了之后有一个 Overview,类似如下:
 

 
 
延迟对比

GitHub Pages

 
 
Google Cloud Platform + Google CDN
 

 
 
已知问题 / 缺陷

这样子做的话,每次更新站点的同步也是一个问题,尤其是对于像我这样的 Hexo 用户而言,本地不想安装 SDK,传完文件后手动上服务器 gsutil cp 会很麻烦。

Google Cloud Platform 的 Load Balancer 并不能做 Force SSL,也就是说如果在 HTTPS 只选择了 443 端口的话,用户未添加 https:// 前缀的情况下访问的返回会是 404,如果同时也添加了 80 端口的话,直接访问也不会自动跳转到 https 上面。

一个比较大众化的解决方案是开一个 Compute instance 监听 80 端口专门用来做 SSL 重定向,但这样便失去了便捷性同时也会导致价格无意义地升高(无脑猜测 Google 团队到现在还不提供这个功能是有一定动机的,关于这个的 issue tracker:Redirect all HTTP traffic to HTTPS when using the HTTP(S) Load Balancer 从 15 年到现在还没有一个正式的答复),另一个思路是将域名加入 Preload List,但是现在的网站结构似乎并不能上 List,目前我正在寻找一个更加可靠的解决方案并不定期更新本文,相关更新会优先在 Twitter 上通知,欢迎关注。

2018-08-16 更新:最终我还是选择了新建一个 Compute instance 的方式解决(可以参考:利用 GCE 建立一个 Anycast 网络,超快的香港节点,Google Cloud CDN),Nginx 配置中稍微需要注意一下,Google CDN 会给后端传一个 X-Forwarded-Proto ,鉴于 Google CDN 的 SSL 只到边缘服务器就截止了(其实还是一个 Half-baked SSL),所以后端 Nginx 还是监听在 80 端口的,如果需要 SSL 重定向的话,需要加入以下内容:
 
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}

 Google Load Balancer

我们知道,业界 Load Balancer 一般有以下实现方案:

一个 Anycast IP(比如 Google LB)
一个普通 IP(比如 Ucloud LB)
一个 CNAME 分区解析(比如 AWS ELB)

且不讨论 CNAME 那个看上去像是一个没钱 Anycast 的解决方案,而且如果用给 APEX 解析的话,在没有特殊加成(APEX FLATTEN)的情况会把 MX 记录炸穿(然后你就无法收邮件了),前者看上去是一个比较用户友好的方式,因为你只需要 A 记录到一个 IP 就可以了,绿色无害。

GFE

在了解 Google LB 之前,我们需要了解一个名词——GFE,感谢 Snowden 的 PPT,我们可以有一个直观的图示:

 

 
 
 
所有到 Google 的流量会在 GFE 上 SSL Offload(应该叫 SSL 卸载?),并且后端全部是在 Google 内网内以 HTTP 的方式进行传输。

在 Google Infrastructure Security Design Overview 中,我们也可以看到:


When a service wants to make itself available on the Internet, it can register itself with an infrastructure service called the Google Front End (GFE). The GFE ensures that all TLS connections are terminated using correct certificates and following best practices such as supporting perfect forward secrecy.



Google LB 也是一样,使用 GFE 作为面相用户的前端,将 SSL 流量在 GFE 上终结,然后以 HTTP 的方式回到后端的 Service 上。

使用一个统一的入口好处有很多,比如 GCP 就提供了一个统一的位置修改 SSL Policy:
 

 
可以自己选择心水的 Cipher Suite 和最低 TLS 版本等,和 Cloudflare 差不多(但是要让 Ucloud LB 做到这一点似乎就太困难了,他们基于 HAProxy 搞的 ULB 到本文发布时还不支持 TLS 1.3,而且要改 Cipher Suite 需要提工单)。

Premium IP

GCP 上的 IP 分为两种,一种是 Premium ,一种是 Standard,默认是前者,Google LB 也只能用 Premium。

Premium 使用的是冷土豆路由,所发送的数据包会保持在 Google 的内网内,并且在尽可能靠近用户的 PoP 离开。
 

 
 
 
 
0
Pay Tips 05-04-20

0 comments

If you wanna get more accurate answers, Please Login or Register