如何极致优化博客访问速度
Jan 3, 2021 02:15 · 2157 words · 5 minute read
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,浏览器上就会“奖励”一个漂亮的小锁图标,反之则是醒目的“不安全”。
我相信赏心悦目的 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,全面收录了各种优秀的开源三方库。
但是引入了第三方的域名,也就意味着要多走一次 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 对用户体验造成的影响不大。
以上涉及到不少综合知识和钱包使用技巧,如果你都掌握了,那真的挺好的。