如何极致优化博客访问速度

Jan 3, 2021 02:15 · 2157 words · 5 minute read Network

1. 加带宽

简单,粗暴,有效,一分钱一分效果。

也烧钱,个人感觉 2 ~ 3M 的带宽就足够,再往上加提升效果不明显,如果 web 服务本身不到位砸多少钱都是打水漂

2. 全站静态化

个人博客没有啥业务需求,呈现想要展示的内容就完事,用户直接拿 html 文件就行了,避免 JavaScript 调用 API 来动态渲染页面时因多次网络请求和计算造成的延迟;静态页面还有利于 SEO(搜索引擎优化)。

纯静态页面 web 服务就可以使用 Nginx 来托管,这也是目前性能最好的 web 服务器。

https://blog.crazytaxii.com 使用 Hugo(一款 Go 实现的静态网站生成器)生成纯静态页面 + Nginx 托管方案。

Hugo 的用法就按下不表了,自行 google 即可。

3. 启用 gzip

这里没有高并发高吞吐量的,没必要吃力不讨好去调 Linux 内核参数。

Nginx 开个 gzip 压缩传输中的文件体积就够了:

gzip on;
gzip_vary on;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_min_length 256;
gzip_proxied any;
gzip_disable "msie6";
gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

4. HTTPS/SSL 优化

如果全站都走 HTTPS,浏览器上就会“奖励”一个漂亮的小锁图标,反之则是醒目的“不安全”。

safari

chrome

我相信赏心悦目的 web 页面能够带来更好的阅读体验。

启用 OCSP Stapling

要开启 HTTPS 首先要为域名签发 SSL 证书。很多同学都使用 Let’s Encrypt 来签发免费的 SSL 证书,我曾经也是这么干的,毕竟传统的付费 SSL 证书贼贵啊,动辄上千。但是我曾经遇到过 SSL 证书在验证时因 Akamai CDN 回源造成 TLS 握手时数秒的延迟,排查的过程我也记下来了 https://blog.crazytaxii.com/posts/blog_performance_analysis/。于是我改用了阿里云提供的免费 DV 证书,整个 TLS 握手大概 30ms,这是可以接受的。

如果还是想用 Let’s Encrypt 签发的证书,那就开启 OCSP Stapling(Online Certificate Status Protocol,在线证书状态协议),会跳过去第三方验证证书。因为服务器这边将自行查询 OCSP 服务器并缓存响应结果,然后在与浏览器进行 TLS 连接时返回给浏览器,这样浏览器就不需要再去查询了。

在 Nginx 中启用 OCSP Stapling:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/ca.pem;

检查 OCSP Stapling 是否开启:

$ openssl s_client -connect blog.crazytaxii.com:443 -servername crazytaxii.com -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"
OCSP response:
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response

调整 ssl_buffer_size

ssl_buffer_size 控制在发送数据时的 buffer 大小,默认设置是 16k。这个值越小,则延迟越小。16k 更适合大文件传输,静态页面 4k 就行:

ssl_buffer_size 4k;

启用 SSL Session 缓存

启用 SSL Session 缓存可以大大减少 TLS 的反复验证,减少 TLS 握手次数。虽然 session 缓存会占用一定内存,但是用 1M 的内存就可以缓存 4000 个连接,合算的很。个人博客要达到 4000 个同时连接本身也不太可能,因此可以放心大胆地开启,顺带也设置个 4 小时的连接超时关闭时间:

ssl_session_cache shared:SSL:50m;
ssl_session_timeout 4h;

5. 开启 HTTP/2

老实讲对降低延迟帮助不大,但逼格还是要有的。

HTTP/2 标准是从 Google 的 SPDY 上进行的改进,比起 HTTP 1.1 提升了不少性能,尤其是需要并行多个请求的时候可以显着减少延迟。

在 Nginx 中开启 HTTP/2:

listen 443 ssl http2;

检查 HTTP/2 是否开启:

$ curl --http2 -I https://blog.crazytaxii.com
HTTP/2 200
server: nginx/1.16.1
date: Sun, 03 Jan 2021 03:23:17 GMT
content-type: text/html
content-length: 8914
last-modified: Sat, 02 Jan 2021 04:00:27 GMT
vary: Accept-Encoding
etag: "5fefefdb-22d2"
cache-control: no-cache
accept-ranges: bytes

6. 灵活使用 CDN

我们的博客大概率会用到 jquery、font-awesome、highlight.js 这些方便好用的第三方库来提升 web 的用户体验。如果你的云服务器还是小水管带宽,果断上公共 CDN,推荐七牛云赞助的 staticfile.org,全面收录了各种优秀的开源三方库。

staticfile.org

但是引入了第三方的域名,也就意味着要多走一次 TLS 握手,而且这一次你是无法控制的。CDN 的问题在于每个地区访问的延迟差距可能非常大,一旦回源,会造成更大的延迟。如果使用了不靠谱的公共 CDN,甚至经常会发生服务中断,导致资源完全不可访问,这对用户体验来说是致命的。

如果带宽足够,我们就可以把三方库搬回自己的服务器,完全掌控这部分资源,不用担心某个时候公共 CDN 服务中断了,甚至还可以定制这些资源以减小体积。这里需要自己权衡。

图片资源

博客一般都要配图,我选择七牛云的对象存储服务(免费)+ CDN(收费)。图片资源这种大文件分发无脑上 CDN 就完事,虽然不免费但是个人博客那点流量花不了多少钱,我去年一块钱都不到。

7. 减小文件体积

每加载一张配图,一个三方库 css 和 js 文件都对应着一次文件传输,所以我们要尽可能地减小文件体积以降低传输造成的延迟。

图片资源

图片上传至对象存储前要剪裁 + 压缩,我使用 imageoptim 来压缩 jpeg 图片。

wepb 格式相比 jpeg 图像数据压缩算法更先进,能够带来更小的图片体积。但要注意不是所有浏览器都支持 webp。

三方库

font-awesome 为例,这是个体积比较大的 js 资源。

加载 font-awesome 的 all.js 实打实传输了 448 kB 的数据。这份文件中涵盖了上千个图标资源,而实际上我全站仅仅使用了其中的两个。。。

所以我要动手移除 js 文件中其他的图标资源。既然修改了标准三方库文件,那公共 CDN 肯定没法用了,需要将瘦身后的三方库文件托管在自己的主机上,所以我最终放弃了 staticfile.org 选择使用自己的服务器分发各种三方库文件。

8. Google Analytics

很遗憾,要统计博客的一些基本面数据,这玩意必须带上,而且目前也没更好的非商业级替代方案了。

这东西也是要传输一个 js 文件的,Google Analytics 的网络服务虽然在国内没有彻底关闭,但非常不稳定。本着尽可能减小文件体积的原则,我找到了 Minimal Google Analytics Snippet 这个方案,以牺牲某些用户行为数据为代价,将原本 73kB 的 js 文件缩减至 1.5kB,并将这段代码内嵌在了 html 中。

但这段 JavaScript 在执行时向 Google Analytics 发送的一次请求是逃不掉的,这一发请求会带来非常大的延迟,甚至很多时候服务不可用。但在这次请求之前,DOM 内容就已经加载完毕,页面已经可以呈现,所以 Analytics 对用户体验造成的影响不大。


以上涉及到不少综合知识和钱包使用技巧,如果你都掌握了,那真的挺好的。