问题描述

先说背景。网站是用PHP开发的,未用任何框架,代码结构也非常简单。运行于阿里云服务器,并采用其CDN来做分发。根据业务需求,有的页面会判断用户浏览器类型,依此来选择PC或者手机端内容。

在一次上线过程中,遇到比较诡异的问题:用PC和手机分别访问页面时,网页内容未根据浏览器类型来区分。而在开发环境,页面却能正常显示。仔细排查了代码,没有发现问题出在什么地方。而线上环境也不好调试,只能靠猜了。

解决过程

开发环境一切正常,说明代码出问题的可能性不大(当然后面发现还是代码的问题~)。而线上与开发环境的差别就在于多了一层CDN。会不会是CDN的问题?然而本人对CDN也是一知半解的,只知道是它会缓存源网站内容,并就近对用户进行内容分发,来加速访问。如果用户请求的内容CDN并未缓存,就会发生回源。对图片、css、js等静态资源,CDN缓存是理所应当的。但是对html内容,因为一般都是PHP动态生成的,会有一些业务逻辑,缓存这些内容就不太合适了。由于相关判断浏览器类型的代码是经过验证的,所以问题应该不在网站本身。考虑到上面CDN相关内容,我就在怀疑是不是CDN把html都缓存下来了,导致用户请求压根没到网站服务器。于是打开浏览器console,查看请求响应头,并把问题页的响应头和正常页面进行对比,果然发现了问题。正常页面每次刷新后,响应头里的Date字段都会改变;而问题页的Date字段一直没变化!也就是说问题页取到的内容一直都是CDN缓存。再次对比发现,正常页面还有Cache-Control相关内容,而问题页没有。于是推测CDN会根据响应头来决定是否会缓存内容。在问题页代码中增加缓存控制相关header后,果然正常了。然而问题又来了,正常页面的Cache-Control是哪里输出的呢?代码中并没有看到对应内容,估计是线上人为加了相关header,与开发环境代码不一致。

总结

一直以来对http响应头中的缓存控制相关内容都没有注意,遇到问题才发现它们的重要性。本次解决这个问题,主要是增加了以下header:

header('Pragma: no-cache');//兼容老版本协议 http1.0可能不识别Cache-Control
header('Cache-Control: no-store, no-cache, must-revalidate');//告诉浏览器/代理 不缓存内容
header("Expires: Mon, 26 Jul 1970 05:00:00 GMT"); //把过期时间设置为以往的时间,基本等同于Cache-Control:no-cache

页面加上三行代码后基本可保证其内容不被缓存。

阿里云CDN响应头中有几个关于缓存的字段需要注意:

X-Cache,值包含HIT时,表示命中缓存;MISS则表示未命中,需要回源
X-Swift-SaveTime 缓存保存时间
X-Swift-CacheTime 缓存时长
Age 当前资源已缓存的时间,达到X-Swift-CacheTime时缓存过期,会回源

想了解更多HTTP协议相关内容,请查看HTTP协议简介

HTTP缓存带来的“bug”--HTTP 协议 Cache-Control的更多相关文章

  1. host缓存,浏览器缓存---解决host缓存带来的伤

    1.缓存 缓存,对应工程师来讲简直太熟悉了,太方便了,省略到资源或数据的获取方式,直接缓存到离用户访问最快的地方,也降低服务器的压力,比如: (1)静态文件获取 服务器->cdn->本地磁 ...

  2. ARP缓存表的构成ARP协议全面实战协议详解、攻击与防御

    ARP缓存表的构成ARP协议全面实战协议详解.攻击与防御 1.4.3  ARP缓存表的构成 在局域网的任何一台主机中,都有一个ARP缓存表.该缓存表中保存中多个ARP条目.每个ARP条目都是由一个IP ...

  3. 缓存系列之一:buffer、cache与浏览器缓存

    缓存系列之一:buffer.cache与浏览器缓存 一:缓存是为了调节速度不一致的两个或多个不同的物质的速度,在中间对速度较快的一方起到一个加速访问速度较慢的一方的作用,比如CPU的一级.二级缓存是保 ...

  4. 服务升级带来的Bug,BAT也不能幸免

    这是标题党,关于阿里的,BT躺枪了. 为什么淘宝上找不到"亲淘"了? 好吧,我今天遇到了一个Bug: 立即更新,然后你看到了: 才发现亲淘不能使用了. 看官方页面: 提示:2016 ...

  5. 由于未清除缓存引发的bug

    在写页面的时候,首先引入了本地react.js和react-dom.js 16版本(cjs)的文件,出现如下错误 发现bug后,将本地的react.js和react-dom.js文件改成16.2(um ...

  6. 浏览器缓存引起的bug总结

    缓存原理 浏览器缓存分为强缓存和协商缓存 先检查是否过期,没有过期直接使用本地缓存.如果过期,查看是否使用协商缓存 协商缓存流程: 后端返回headers: ETag: W/"1e3-175 ...

  7. 网站 cache control 最佳实践

    推荐阅读: 2020年软件开发趋势 高并发案例 - 库存超发问题 负载均衡的分类及算法 异地多活架构 Postman 的替代品来了 有时,当第二次访问网站时,看起来比较怪,样式不正常. 通常,是因为 ...

  8. [转]ASP.NET Core: Static Files cache control using HTTP Headers

    本文转自:https://www.ryadel.com/en/asp-net-core-static-files-cache-control-using-http-headers/ Every sea ...

  9. MemCache分布式缓存的一个bug

    Memcached分布式缓存策略不是由服务器端至支持的,多台服务器之间并不知道彼此的存在.分布式的实现是由客户端代码(Memcached.ClientLibrary)通过缓存key-server映射来 ...

随机推荐

  1. Java利用递归算法统计1-6的数组排列组合数

    Java利用递归算法统计1-6的数组排列组合数 1.设计源码 /** * @Title:ArrayCombination.java * @Package:com.you.data * @Descrip ...

  2. SCRIPT5007:无法获取属性“show”的值,对象为null或未定义

    1.错误描述 SCRIPT5007:无法获取属性"show"的值,对象为null或未定义            dojo.js,行15.字符11808 2.错误原因    requ ...

  3. Struts2(三) 配置struts.xml的提示(在不联网的情况下)

    开发过程中如果可以上网,struts.xml 会自动缓存dtd,提供提示功能.如果不能联网需要我们配置本地dtd,这样才能让struts2 产生提示 1.首先,在EClipse中依次点击工具栏中的wi ...

  4. 芝麻HTTP:redis-py的安装

    对于Redis来说,我们要使用redis-py库来与其交互,这里就来介绍一下它的安装方法. 1. 相关链接 GitHub:https://github.com/andymccurdy/redis-py ...

  5. JavaScript设计模式(9)-享元模式

    享元模式 1. 介绍 一种优化模式 适合解决因创建大量类似对象而累积性能问题 javaScript 代码可能很快就用光浏览器的内容,通过把大量独立对象转化为少量共享对象,可以降低运行 Web 应用所需 ...

  6. Treeview 丢失焦点后依然高亮 SelectedNode

    参考:StackOverFlow.Control.Validating 事件 注意 TreeView 的 HideSelection 要保持为默认值True. private TreeNode pre ...

  7. MyISAM和InnoDB索引实现区别

    首先来讲MyISAM: MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址.下图是MyISAM索引的原理图: 这里设表一共有三列,假设我们以Col1为主键,则上图是 ...

  8. 【BZOJ1500】【NOI2005】维修数列(Splay)

    [BZOJ1500][NOI2005]维修数列(Splay) 题面 不想再看见这种毒瘤题,自己去BZOJ看 题解 Splay良心模板题 真的很简单 我一言不发 #include<iostream ...

  9. 【NOIP2016】换教室(动态规划)

    题目戳我 题解 其实感觉16年的难度不是很大???? 这道题去年考场上DP都想出来了... 只是因为不会数学期望...然后GG.... 这道题目只要把数学期望搞出来就可以啦 设f[i][j][0/1] ...

  10. Redis之Zset

    一.Redis之Zset简介 1. 有序集合Zset是String类型的有序集合. 2. Zset中每个元素都会关联一个double类型的分数值,redis通过分数值来为集合中所有成员进行从小到大排序 ...