问题描述

先说背景。网站是用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. 芝麻HTTP: Python爬虫入门之Urllib库的高级用法

    1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...

  2. 浅谈JS中的浅拷贝与深拷贝

    前端工程师应该都比较熟悉浅拷贝和深拷贝的概念,在日常业务代码的过程中,特别是做数据处理的时候,经常行的会遇到,比如如何在不修改原对象的基础上,重新生成一个一模一样的对象,加以利用,又或是,如何巧妙地运 ...

  3. Linux之批量挂载硬盘

    ############parted工具分区############### #!/bin/bash #shell脚本开头格式PATH=/bin:/sbin:/usr/bin:/usr/sbin #保证 ...

  4. 小例子理解SQL的左连接与右连接

    假设有A,B两个表. 表A记录如下: aID aNum a20050111 a20050112 a20050113 a20050114 a20050115 表B记录如下: bID bName ---- ...

  5. 登录对话框(窗体程序)--JAVA基础

    1.用到的JFrame(框架)类对象(这里设JFrame类对象是frame)的方法有: frame.add(); 添加组件到frame框架中 frame.setVisible(); 设置框架是否可见 ...

  6. 游戏中实现粒子碰撞,纯java

    package com.totoo.TouhouMassLight;import android.content.Context;import android.graphics.Bitmap;impo ...

  7. 【BZOJ2818】Gcd(莫比乌斯反演)

    [BZOJ2818]Gcd(莫比乌斯反演) 题面 Description 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的 数对(x,y)有多少对. Input 一个整数N Ou ...

  8. [BZOJ1024] [SCOI2009] 生日快乐 (搜索)

    Description windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕.现在包括windy,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋 ...

  9. [BZOJ1045] [HAOI2008] 糖果传递 (贪心)

    Description 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. Input 第一行一个正整数n<=,表示小朋友的个数.接下来n行,每行 ...

  10. 记录一次网站漏洞修复过程(三):第二轮处理(拦截SQL注入、跨站脚本攻击XSS)

    在程序编写的时候采用参数化的SQL语句可以有效的防止SQL注入,但是当程序一旦成型,再去修改大量的数据库执行语句并不是太现实,对网页表单上输入进行校验是易于实现的方法.在webForm 页面中开启校验 ...