一、预缓存
由于中间用于代理转发的腾讯云CDN和阿里云CDN都是没有缓存的,如果CloudFlare的缓存过期,将需要绕过多层链路回源获取网页内容,相比速度就会慢很多。所以,需要在用户访问之前,先将页面缓存到CloudFlare,这样用户访问就快多了,这就是预缓存的概念。
WordPress插件wp-super-cache以及国内部分CDN都提供了预缓存功能,所以,这是一个很实用的优化。不过CDN提供的热缓存功能都需要用户手工去提交代码,而预热接口则有诸多限制,如图:
相比于这些限制、复杂度,本文分享的预缓存工具就简单粗暴多了,直接模拟浏览器定期访问来实现预缓存,无任何限制!
温馨提示:只要启用了缓存的网站,都可以用到预缓存优化!
其实之前在博客也分享过一个预缓存Shell脚本,确实也可以用,就是效率太低,而且不能指定源站来缓存(除非改造下),于是花了点时间重新写了一个Python版本,支持异步、并发请求网页实现预缓存,而且支持指定具体的主机IP+端口,从而可以支持多CDN、本地缓存等复杂场景。
下面简单介绍下这个新工具的原理及使用方法。
二、工作原理
和之前分享的Shell版本一样:工具会模拟浏览器对网站地图sitemap.xml中的网址进行请求,从而实现这些网页的预缓存。当然前提是你的网址启用了静态缓存或者开启了CDN全站缓存,启用缓存的相关教程可以参考前文:
Nginx开启缓存:Nginx开启fastcgi_cache缓存加速,支持html伪静态页面
Cloudflare优化经验:张戈博客使用CloudFlare CDN加速的经验技巧分享
CDN优化经验:如何正确配置CDN高速缓存,避免越用越慢的尴
在相同原理的基础上,这次的工具也增强了一些特性,请继续往下看使用说明。
三、使用说明
1、基于Docker运行
熟悉Docker的朋友可以基于Docker容器来跑这个工具(Docker安装参考前文),依赖插件都已经集成好了,就不需要入侵本地环境了,命令如下:
docker run --rm --net=host -ti jagerzhang/pre-cache:latest \ --sitemap=https://zhang.ge/sitemap.xml \ --cacheheader=cf-cache-status
如果是拉取DockerHub的速度太慢,也可以先在本地编译Docker镜像,再跑上面的命令,编译方法如下:
git clone https://github.com/jagerzhang/Pre-cache.gitcd Pre-cachedocker build -t jagerzhang/pre-cache:latest ./
2、基于代码运行
基于代码运行需要先初始化一下Python环境,按装工具所依赖的组件,具体命令如下:
git clone https://github.com/jagerzhang/Pre-cache.gitcd Pre-cacheyum install -y python-pippip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
依赖环境初始化完成后,执行如下命令开始预缓存:
python pre_cache.py \ --sitemap=https://zhang.ge/sitemap.xml \ --cacheheader=cf-cache-status
3、基于对象引用
同样工具也支持在其他Python脚本中来作为对象引用,示例代码如下:
from pre_cache import preCachepre = preCache(sitemap="https://zhang.ge/sitemap.xml",host=None,size=10,timeout=10,cache_header="cf-cache-status",user_agent="Pre-cache/python-requests/2.22.0",verify=False)pre.start()
4、执行结果
正常执行结果如下所示:
[root@localhost ~]# docker run -ti --net=host jagerzhang/pre-cache:latest --host=127.0.0.1:8443 --sitemap=https://zhang.ge/sitemap.xml --cacheheader=x-cache-redis站点地图:https://zhang.ge/sitemap.xml指定主机:127.0.0.1:8443并发数量:20超时时间:10秒缓存标识:x-cache-redisUA 标识:Pre-cache/python-requests/2.22.0预缓存开始:---------------------------------------------------------缓存标识头缺失页面:https://zhang.ge/5072.html 不可缓存页面:https://zhang.ge/roll.html 缓存标识头:X-Cache-Redis: BYPASS不可缓存页面:https://zhang.ge/goodarticles 缓存标识头:X-Cache-Redis: BYPASS不可缓存页面:https://zhang.ge/tag/google 缓存标识头:X-Cache-Redis: BYPASS---------------------------------------------------------预缓存完成,页面总数:897,耗时16秒已被缓存页面数:893不可缓存页面数:3缓存标识头缺失页面数:1
Ps:为了让大家快速看到效果,这里就直接贴张戈博客的预缓存命令了,大家浅尝辄止,就不要无聊扫我的网站了。
上面就是快速尝鲜使用这个工具的方法,下面详细介绍工具参数。
5、参数介绍
--help、-h 参数打印帮助信息:
[root@localhost ~]# python pre_cache.py --helpusage: pre_cache.py [-h] -s SITEMAP [-S SIZE] [-t TIMEOUT] [-H HOST][-c CACHEHEADER] [-U USERAGENT] [-v VERIFY]网站预缓存脚本,支持使用CDN或本地有静态缓存的网站.optional arguments:-h, --help show this help message and exit-s SITEMAP, --sitemap SITEMAP网站地图sitemap地址-S SIZE, --size SIZE 并发请求数量,默认20-t TIMEOUT, --timeout TIMEOUT单个请求的超时时间,默认10s-H HOST, --host HOST 指定真实主机,比如 127.0.0.1:8080-c CACHEHEADER, --cacheheader CACHEHEADER缓存标识,比如: x-cache-u USERAGENT, --useragent USERAGENT指定UA标识,默认 Pre-cache/python-requests/__version__-v VERIFY, --verify VERIFY是否校验SSL,默认不校验
其他参数如帮助信息所示,简单说明如下:
| 参数 | 必须 | 默认值 | 说明 |
| --sitemap / -s | 是 | 无 | 指定网站地图sitemap文件网址,必须为xml文件格式。 |
| --cacheheader / -c | 否 | 无 | 指定响应头里面的缓存标识名称,比如CF为cf-cache-status,不指定不影响功能,但是无统计信息。 |
| --host / -H | 否 | 无 | 指定具体主机来访问页面,即绕过CDN或代理访问真实主机,支持端口,比如 127.0.0.1:8080。 |
| --size / -S | 否 | 20 | 指定预缓存时并发访问的数量,并非越大越好,需要自定测试整体耗时来得出最佳值。 |
| --useragent / -u | 否 | 见说明 | 自定义请求时的User-Agent标识来模拟客户端,默认值:Pre-cache/python-requests/xx.xx。 |
| --timeout / -t | 否 | 10 | 指定单个请求的超时时间,默认10秒。 |
| --verify / -v | 否 | False | 是否验证SSL证书,保持默认即可,开启验证可能无法支持指定--host来预缓存。 |
这里,挑几个比较核心的参数继续展开说明下。
--sitemap
整个工具的原理是先请求sitemap内容,然后对sitemap里面的url进行爬扫,因此--sitemap这个参数是必须参数,指定为网站的sitemap地址即可,比如:--sitemap=https://zhang.ge/sitemap.xml,需要注意的是这个xml必须是xml格式,这里推荐使用我博客之前分享的sitemap纯代码版本。如果是用插件生成的,可能是多个sitemap地址,然后有一个汇总的sitemap导航,这种情况的话只需要将这个参数指定为具体的分页sitemap地址,且需要分别执行多次。
--cacheheader
这个参数是指定网页被缓存后,Header头部中的HIT标识,常见的头部标识如下:
| 缓存类型 | 头部名称 | 常见值 |
| Nginx 缓存 | X-Cache/或自定义 | HIT,MISS,EXPIRED,BYPASS |
| CloudFlare | cf-cache-status | HIT,MISS,EXPIRED,DYNAMIC |
| 腾讯云CDN | x-cache-lookup | HIT/MISS/EXPIRED/BYPASS From Upstream/XXX |
| 阿里云CDN | X-Cache | HIT,MISS,EXPIRED,BYPASS |
如果不在上述类别或者自定义过,我们也可以通过浏览器开发者模式查看,方法为:浏览器打开页面-->F12-->NETWORK-->刷新-->查看响应头:
一般出现有HIT,MISS,EXPIRED,BYPASS 值的就是我们这个参数需要指定的名称,比如图中的 cf-cache-status,那我们运行工具的时候只需要指定为 --cacheheaer=cf-cache-status 即可。当然,如果有多层缓存时,需要注意甄别。比如CDN有个HIT,本地Nginx也有个HIT,那么看你需要缓存那个就指定哪个了。
--host
这个参数就比较实用了,可以指定真实IP来访问网页,且支持自定义端口。比如 --host=127.0.0.1 或 --host=127.0.0.1:8080,指定后工具将会请求到指定的主机进行资源拉取实现指定节点预缓存。比如张戈博客开了CDN缓存同时本地也开启了Nginx缓存,我就可以如下分2步执行:
# 先本地预缓存:python pre_cache.py \--sitemap=https://zhang.ge/sitemap.xml \--host=127.0.0.1:8443 \ # 指定本地WEB服务监听的8443端口--cacheheader=x-cache-redis # 我这边自定义了一个缓存头# 然后CDN预缓存(这里需要伪造一下浏览器UA,否则CloudFlare拦截大部分请求,当然伪造后也会有少量拦截,影响不大):python pre_cache.py \--sitemap=https://zhang.ge/sitemap.xml \--cacheheader=cf-cache-status \--useragent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"
其他参数比较简单,就不展开赘述了,看上文的表格即可。
6、定时任务
上文已经详细介绍了如何运行这个工具,那接着我们需要通过crontab添加一个定时任务,定期进行预缓存。比如我博客需要在本地、百度云加速以及CloudFlare 3个层面做预缓存,那么就将基于Docker运行的命打包成shell脚本,并按照先预缓存本地,然后再缓预存CDN的顺序:
#!/bin/bashsource /etc/profile# 注意:通过crontab执行docker是没有tty终端的,所以下面的docker的参数不能有-t# 本地预缓存docker run --net=host --rm -i \jagerzhang/pre-cache:latest \--sitemap=https://zhang.ge/sitemap.xml \--cacheheader=x-cache-redis--host=127.0.0.1:18443 \--size=50# 百度云加速预缓存docker run --net=host --rm -i \jagerzhang/pre-cache:latest \--sitemap=https://zhangge.net/sitemap.xml \--cacheheader=cf-cache-status \--size=50 # CloudFlare预缓存docker run --net=host --rm -i \jagerzhang/pre-cache:latest \--sitemap=https://zhang.ge/sitemap.xml \--cacheheader=cf-cache-status \--size=20 \--useragent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"
然后在系统crontab里面添加一个定时任务,每小时执行一次:
# 进入定时任务编辑,插入如下命令行:[root@localhost ~]# crontab -e * 1 * * * bash /domp/opt/pre_cache.sh >/dev/null 2>&1# :wq保存退出
这样就能实现定期网站预缓存了,其他网站可以参考添加。
四、工具反馈
以上就是这个工具的详细介绍了,整体设计、代码逻辑都比较简单,目前这个工具已经上传到了Github,并且在Docker Hub制作了Docker镜像,大家使用后觉得实用的话可以给个星星,有什么建议也可以留言或github提issue:
GitHub地址:https://github.com/jagerzhang/Pre-cache
DockerHub地址:https://hub.docker.com/r/jagerzhang/pre-cache
EnJoy it!





