静态请求CDN
更新后的静态请求的架构图:
DNS用CNAME解析到源站
配置域名:
去CNAME配置加速服务地址:
为购买的域名添加解析域规则:
添加主机信息:
使用域名访问页面:
当用户发起一个请求到DNS服务器时,DNS服务查询到是CNAME地址,则DNS将请求解析转发到就近的云服务器的CNAME地址上面,云服务器会解析出来用户IP属地,返回就近的CDN节点,让用户去访问这个节点的ip地址,然后这个节点判断本地缓存中是否含有请求的资源,如果有的话直接静态数据返回,没有的话就回源到配置的原始云服务器ip上面。
使用jmeter进行压测:
配置使用域名请求:
测试结果:
回源缓存设置
http cache control响应头:
cache control: 服务端用来告诉客户端这个httpResponse可不可以缓存,用什么样的策略去缓存。
private:客户端可以缓存
public:客户端和代理服务器都可以缓存
max-age=xxx:缓存的内容将在xxx秒后失效
no-cache:强制向服务端再验证一次(会将对应的缓存存储在客户端,但是在下次用的时候要向服务端验证一次是否可以使用去决定使用之前的缓存)
no-store:不缓存请求的任何返回内容
有效性判断:
ETag:资源的唯一标识,将请求资源的内容做MD5加密成ETag标识,在返回的内容中加上这个标识,浏览器会存储对应的标识,下次请求会将之前的ETag一起带到服务器上,服务端会将其与本地的文件的ETag值做比较,若一致则返回304 not modify。
If-None_Match:客户端发送的匹配ETag标识符
Last_modified:资源最后被修改的时间
If-Modified-Since:客户端发送的匹配资源最后修改的时间的标识符(这个时间早于Last时间则无效)
判断流程图:
浏览器的三种刷新方式:
1.回车刷新或a连接:看cache-control对应的max-age是否仍然有效,有效则直接from cache,若cache-control中为no-cache,则进入缓存协商逻辑。
2.F5刷新或command+R刷新:去掉cache-control中的max-age或直接设置max-age为0,然后进入缓存协商逻辑
3.ctrl+F5或commond+shift+R刷新:去掉cache-control和协商头,强制刷新
协商机制:比较Last-modified和ETag到服务端,若服务端判断没变化则304不返回数据,否则200返回数据。
强推失效
CDN自定义缓存策略:
可自定义目录过期时间
可自定义后缀名过期时间
可自定义对应权重
可通过界面或api强制cdn对应目录刷新(非保成功)
静态资源部署策略(一)
css,js,img等元素使用带版本号部署,例如a.js?v=1.0不方便,且维护困难
css,js,img等元素使用带摘要部署,例如a.js?v=45edw存在先部署html还是先部署资源的覆盖问题
css,js,img等元素使用带摘要做文件名部署,例如45edw.js,新老版本并存且可回滚,资源部署完后要再部署html
静态资源部署策略(二)
对应静态资源保持生命周期内不会变,max-age可设置的很长,无视失效更新周期
html文件设置no-cache或较短max age,以便于更新
html文件仍然社会在较长的max age,依靠动态的获取版本号请i去发送发到后端,异步下载最新的版本号的html后展示渲染在前端
静态资源部署策略(三)
动态请求也可以静态化成json资源推送到cdn上
依靠异步请求获取后端节点对应资源状态做紧急下架处理
可通过跑批紧急推送cdn内容以使其下架等操作
全页面静态化
定义:在服务端完成html,css,甚至js的load渲染成纯html文件后直接以静态资源的方式部署到cdn上。类似于爬虫技术。
phantomjs(重要)
无头浏览器,可以借助其模拟webkit js的执行
官网演示:www.phantomjs.org
应用:修改需要全页面静态化的实现,采用initView和hashInit方式防止多次初始化;编写对应轮询生成内容方式;将全静态化页面生成后推送到cdn。
vim getitem.js
var page = require("webpage").create();
var fs = require("fs");
page.open("http://miaoshaserver/resources/getitem.html?id=6",funtion(status){
console.log("status = " + status);
setTimeout(function(){
fs.write("getitemphantom.html",page.content,"w");
phantom.exit();
},1000);
});
执行:
phantomjs bin/phantomjs js/getitem.js
访问页面可以看到还是发送了ajax请求。
这是因为document在浏览器中打开时又被请求了一次ajax请求。输出对应的html文件已经在爬虫的无头浏览器中执行过一次了。但是没有防重机制就导致真正用户打开时又访问了一次请求。
方案2:
修改需要全页面静态化的实现,采用initView和hasInit方式防止多次初始化;
编写对应轮讯生成内容方式;
将全静态化页面生成后推送到cdn。
在前端的页面中田间隐藏域:
<input type="hidden" id="isInit" value="0">
开两个全局函数:
function hasInit(){
var isInit = $("#isInit").val();
return isInit;
}
function setHasInit(){
$("#isInit").val("1");
}
function initView(){
var isInit = hasInit();
if(isInit == "1"){
return;
}
//获取页面数据ajax请求,在请求成功后调用setHasInit();
}
修改getitem.js:
var page = require("webpage").create();
var fs = require("fs");
page.open("http://miaoshaserver/resources/getitem.html?id=6",funtion(status){
console.log("status = " + status);
var isInit = "0";
setInterval(function(){ //每隔1s之后发现这个页面isInit不等于1的话,就执行initView方法
if(isInit != 1){
page.evaluate(function(){
initView();
});
isInit = page.evaluate(function(){ //等待下次判断
return hasInit();
});
}else{
fs.write("getitemphantom.html",page.content,"w");
phantom.exit();
}
},1000);
});
前端重新打包部署,请求地址可以看到:
并没有发送getItem()请求。