阅读视图

发现新文章,点击刷新页面。

为什么敲几个字母就能访问网站?DNS原理大揭秘

你有没有想过一个问题:为什么输入"baidu.com"就能打开百度?

今天,我用查字典的故事,来讲讲DNS到底在做什么。


原文地址

墨渊书肆/为什么敲几个字母就能访问网站?DNS原理大揭秘


DNS是干嘛的?

想象一下,你想知道某个同学的电话号码。

有两种方式:

  1. 直接记住:你把全班同学的电话号码都背下来
  2. 查通讯录:你不知道,但你可以查学校的通讯录

显然,第二种更现实。

互联网也是一样的:

  • IP地址:就像电话号码,比如112.80.248.76
  • 域名:就像人名,比如baidu.com

你不可能记住所有网站的IP地址,但你可以记住域名。

DNS(Domain Name System,域名系统)就是互联网的"通讯录"——它负责把域名翻译成IP地址。


域名是怎么组成的?

先来看看www.baidu.com这个域名:

www.baidu.com
  │     │    │
  │     │    └──── .com 是顶级域名
  │     └───────── baidu 是二级域名
  └─────────────── www 是三级域名

域名层级

  • 根域名.(那个隐藏的点)
  • 顶级域名.com.cn.org.edu
  • 二级域名baidutaobaogoogle
  • 三级域名wwwmailblog

就像地址一样:

中国 → 北京市 → 海淀区 → 中关村大街1号
.     →   .cn  →  .beijing →  .zhongguancun

DNS是怎么工作的?

你输入baidu.com,浏览器是怎么找到服务器的?

让我用查字典的故事来解释:

想象一下查字典

你想查"百度"这个词的意思:

  1. 先翻记忆(浏览器缓存):上次好像在哪儿见过?
  2. 翻家里的小本子(操作系统hosts):上次记在笔记本上了
  3. 问老师(本地DNS服务器):我们学校有本字典能查
  4. 老师问校长(根DNS服务器):这个词太长了,得分头查
  5. 校长查索引(顶级域名服务器):.com开头的词都归.com部门管
  6. 最后查到(权威DNS服务器):找到了!这个词的意思是"IP 112.80.248.76"

这就是DNS查询的全过程!

更直观的流程图

你输入 baidu.com
        │
        ▼
┌───────────────────┐
│  1. 浏览器缓存    │ 有?直接用
└─────────┬─────────┘
          │ 没有
          ▼
┌───────────────────┐
│  2. 操作系统缓存   │ 有?直接用
└─────────┬─────────┘
          │ 没有
          ▼
┌───────────────────┐
│  3. 本地DNS服务器  │
│   (114.114.114.114)│
└─────────┬─────────┘
          │
          ▼
    一级一级往下问
          │
    ┌─────┴─────┐
    ▼           ▼
 根DNS      .com DNS
    │           │
    │           ▼
    │     baidu.com DNS
    │           │
    └─────┬─────┘
          │
          ▼
┌───────────────────┐
│  返回IP: 112.80.248.76 │
└───────────────────┘
          │
          ▼
   浏览器访问这个IP

每个步骤具体做什么?

步骤 谁在做 做了什么
1 浏览器 检查最近访问过的域名缓存
2 操作系统 检查hosts文件
3 本地DNS 运营商的DNS服务器,帮你递归查询
4 根DNS服务器 负责.和顶级域名(.com.cn
5 权威DNS 域名所有者自己的DNS(百度公司)

整个过程可能只需要几十毫秒,你根本感觉不到!


DNS缓存:不用每次都问

上面的流程看起来很复杂,但因为DNS缓存无处不在,实际上很少走完完整流程:

  • 浏览器缓存:几分钟到几小时
  • 操作系统缓存:Windows、macOS会缓存更久
  • 路由器缓存:你家路由器也可能缓存
  • 运营商缓存:运营商的DNS服务器会缓存

所以第一次访问baidu.com可能慢一点,之后就快了。


DNS记录类型:不止A记录

DNS不只是存IP地址,还有很多类型:

类型 作用 例子
A记录 域名 → IPv4 baidu.com112.80.248.76
AAAA记录 域名 → IPv6 baidu.com240e:ff:e020:9e::100
CNAME 域名 → 另一个域名 www.baidu.comwww.a.shifen.com
MX记录 域名 → 邮件服务器 @baidu.commx.baidu.com
TXT记录 存放文本信息 用来验证域名所有权
NS记录 指定域名由哪个DNS服务器解析 baidu.comdns.baidu.com

CNAME的好处

www.baidu.com其实指向了www.a.shifen.com

这就是CNAME——别名。

百度可以随时把www.baidu.com指向新的IP,只需要改一下CNAME,用户不需要记住新IP,体验不变。


DNS有什么问题?

DNS很棒,但不是完美的。

1. DNS污染

有些运营商或防火墙会篡改DNS结果。你输入google.com,返回了错误的IP——你访问不了Google,或者访问了假网站。

这叫DNS污染(DNS Spoofing)。

2. DNS劫持

黑客黑掉你的路由器或DNS服务器,故意返回错误的IP——你以为是访问银行,实际上是钓鱼网站。

这叫DNS劫持(DNS Hijacking)。

3. 隐私问题

DNS查询是明文的,你的运营商知道你访问了哪些网站。


怎么解决?——DNS over HTTPS

既然DNS有问题,那就加密!

DoH(DNS over HTTPS)

把DNS查询伪装成HTTPS请求,就像普通的网页请求一样。

别人看到了HTTPS请求,但不知道你在查DNS。

DoT(DNS over TLS)

用TLS加密DNS查询,更加安全。

公共DNS

除了运营商的DNS,还有一些公共DNS

  • Google DNS8.8.8.88.8.4.4
  • Cloudflare DNS1.1.1.11.0.0.1

这些公共DNS通常更快、更安全、不劫持。


总结:DNS做了什么?

步骤 做了什么
1. 输入域名 baidu.com
2. 查缓存 浏览器、操作系统、路由器有没有记录?
3. 递归查询 根服务器 → .com服务器 → baidu.com DNS
4. 返回IP 112.80.248.76
5. 访问服务器 浏览器向这个IP发起HTTP请求

写在最后

现在你应该懂了:

  • DNS = 互联网的"通讯录",把域名翻译成IP
  • A记录 = 域名→IP的对应关系
  • CNAME = 别名,让换IP更容易
  • DNS缓存 = 各地都有小本本,不用每次都查
  • DoH/DoT = 加密查询,更安全

下次你输入baidu.com的时候,记得——这背后有一群DNS服务器在帮你"查号"呢。

HTTP裸奔,HTTPS穿盔甲——它们有什么区别?

你有没有想过一个问题:为什么有的网站显示"不安全",有的显示"安全"?同样是HTTP,加了个"S"到底有什么区别?

今天,我用写信的故事,来讲讲HTTPS到底在加密什么。


原文地址

墨渊书肆/HTTP裸奔,HTTPS穿盔甲——它们有什么区别?


HTTP是怎么"裸奔"的?

想象一下,你给朋友寄信。

如果用HTTP,相当于你把信写在明信片上,直接塞进邮筒。

邮递员、门卫、邻居——谁都能看到信里的内容。

你写的「我爱你」「我的密码是123456」——所有人都一览无余。

这就是HTTP的现状:数据是明文传输的,谁都能偷看。

HTTP会被谁偷看?

  • 隔壁老王连上了同一个WiFi
  • 运营商能查到你在访问什么网站
  • 某些"中间人"专门拦截网络流量

所以在HTTP上输密码、填银行卡——跟裸奔没什么区别。


HTTPS是怎么"穿盔甲"的?

现在换一种方式。

你把信放进一个带锁的盒子里,只有你和朋友有钥匙。

邮递员拿到了盒子?没关系,他打不开。

这就是HTTPS:数据是加密传输的,别人看到了也看不懂。

HTTPS怎么做到加密?

这就涉及到两种加密方式:对称加密非对称加密


对称加密:一把钥匙(代表:AES)

对称加密就像一把钥匙,能开锁也能锁门。

  • 加密用这把钥匙
  • 解密也用这把钥匙

AES(Advanced Encryption Standard,高级加密标准)就是最典型的对称加密算法。

  • 优点:速度快,加密1G数据可能只需要几毫秒
  • 缺点:密钥传输问题——怎么把这把钥匙安全地交给对方?

现实中的问题

你想给朋友寄一把钥匙过去,但邮递员能看到啊!他拿到钥匙之后,不就能打开你的盒子了吗?

这就是对称加密的困境:钥匙送不到对方手里。

AES到底有多强?

AES是现在最常用的对称加密算法,被美国政府采用,取代了之前的DES。

它有多安全?

  • AES-128:密钥长度128位,暴力破解需要上万亿年
  • AES-256:更安全,连量子计算机都很难破解

所以AES本身是非常安全的,关键是怎么安全地把密钥送到对方手里。


非对称加密:两把钥匙(代表:RSA)

后来密码学家发明了非对称加密,像是一把神奇的锁。

它配两把钥匙

  • 公钥(Public Key):锁,可以复制多份分发出去
  • 私钥(Private Key):钥匙,只有自己手里有

RSA就是最著名的非对称加密算法,由三位数学家Rivest、Shamir、Adleman的名字命名。

RSA是怎么工作的?

  1. 你生成一对密钥:公钥私钥
  2. 公钥(锁)公开,谁都可以拿到
  3. 别人用你的公钥加密信息
  4. 只有你手里的私钥能解密

怎么用?

  1. 你把公钥(锁)寄给朋友
  2. 朋友把信放进盒子里,用锁锁好
  3. 只有你手里的私钥(钥匙)能打开

这样一来,公钥寄出去没关系,反正只能用来"锁",不能用来"开"。

RSA的缺点

  • 非常:比对称加密慢几百甚至上千倍
  • 只能加密少量数据:一般用来加密"密钥",而不是大量内容

这就是为什么不能全程用RSA加密。


HTTPS是怎么结合两者的?

HTTPS很聪明,它把两者结合起来用:

  1. 用RSA等非对称加密,把一把"对话密钥"(会话密钥)安全地传给对方
  2. 之后双方都用"对话密钥"做AES对称加密,速度就快了

这就跟做生意一样:

  • 见面谈判(慢,但安全)→ 确立合作方式,交换暗语
  • 之后用暗语交流(快)→ 正式合作

HTTPS也是这个道理:先"握手"一次确定加密方式(用RSA),之后就快(用AES)了。

具体流程

第一次访问(握手):
1. 浏览器:你好,我想访问 example.com
2. 服务器:你好,这是我的证书(包含RSA公钥)
3. 浏览器:(验证证书)OK,我生成一个随机数作为会话密钥
4. 浏览器:用服务器的RSA公钥加密会话密钥,发给服务器
5. 服务器:用RSA私钥解密,得到会话密钥

后续通信:
6. 浏览器 & 服务器:用会话密钥 + AES算法,加密/解密所有数据

证书:怎么证明"你是你"?

等等!上面的方案有个漏洞。

如果有个坏人假冒服务器呢?

比如他拦截了你的公钥请求,然后把自己的公钥寄给你——这叫"中间人攻击"。

你以为是跟朋友通信,实际上是跟坏人通信!

怎么办?

你需要证明身份

HTTPS引入了证书机制,就像身份证一样。

证书是怎么工作的?

  1. 网站去CA机构(Certificate Authority,证书颁发机构)申请一个证书
  2. CA机构核实网站身份,用自己的私钥给证书"签名"
  3. 证书里包含:网站域名、网站的RSA公钥、CA的签名
  4. 浏览器访问网站时,先验证证书

浏览器内置了一些可信的CA机构(比如DigiCert、Let's Encrypt、GlobalSign),就像公安局一样。

如果证书是假的,或者域名对不上——浏览器会显示"不安全"。

证书链:验证过程

你可能会想:CA机构 themselves 谁来证明?

这就是证书链

  • 根证书:浏览器内置,最可信
  • 中间证书:CA机构颁发
  • 服务器证书:你申请的

浏览器会一级一级验证上去。


TLS握手:到底发生了什么?

你访问一个HTTPS网站时,背后会发生这些事情:

1. 浏览器:你好,我想访问 example.com(用的是HTTPS)
2. 服务器:你好,这是我的证书(包含RSA公钥)
3. 浏览器:(验证证书)OK,这是合法的网站
4. 浏览器:我生成一个随机数(会话密钥),用你的公钥加密后发给你
5. 服务器:用我的私钥解密,得到会话密钥
6. 浏览器 & 服务器:好的,用这个会话密钥 + AES算法,开始加密通信

这就是著名的TLS握手(HTTPS = HTTP + TLS)。

握手完成之后,后续的数据传输就都是加密的、很快的。


SSL/TLS/HTTPS到底是什么关系?

  • SSL(Secure Sockets Layer):最早的安全协议,1994年由Netscape发明
  • TLS(Transport Layer Security):SSL的升级版,1999年发布,SSL的继任者
  • HTTPS:HTTP + TLS,简单说就是"穿上TLS盔甲的HTTP"

现在基本都用TLS,但很多人还是习惯叫HTTPS为SSL。


HTTPS有什么缺点?

虽然HTTPS很好,但不是完美的。

1. 慢一点

TLS握手需要时间,首次访问会慢一些。

但现在有TLS 1.3,0-RTT握手,几乎没影响。

2. 要花钱

HTTPS需要证书,以前很贵。

现在有Let's Encrypt等免费CA,证书基本不要钱。

3. 不是100%安全

HTTPS只加密传输过程,但如果:

  • 服务器被黑客攻破
  • 用户中了木马
  • 用了弱密码

——一样完蛋。

HTTPS不是万能的,但它让"偷看"变得几乎不可能。


总结:HTTP vs HTTPS

\ HTTP HTTPS
传输方式 明文 加密
加密算法 RSA + AES
速度 稍慢
安全性 裸奔 穿盔甲
证书 不需要 需要CA颁发
端口 80 443
用途 不涉及隐私的页面 登录、支付、敏感操作

写在最后

现在你应该懂了:

  • HTTP = 明信片,谁都能看
  • HTTPS = 带锁的盒子,只有你能开
  • RSA = 一把锁配两把钥匙,用来安全地送"钥匙"
  • AES = 用"钥匙"快速加密大量数据
  • 证书 = 身份证,证明"服务器是服务器"

下次看到浏览器显示"不安全",就别在上边输密码了。

看到"安全",也不是100%安全——但至少,不会"裸奔"了。

从一行字到改变世界:HTTP这三十年都经历了什么?

这是一个关于「一行字」如何改变世界的故事。从GET /index.html到QUIC,HTTP用了三十年。


原文地址

墨渊书肆/从一行字到改变世界:HTTP这三十年都经历了什么?


1991年,互联网还是个大农村。

那时候上网的人很少,网页也简陋得可怜。你能想象吗——第一个网页上只有一行字,连张图片都没有。

但就是从这一行字开始,一个帝国崛起了。


HTTP/0.9:一切的开始

1991年,一个叫蒂姆·伯纳斯-李(Tim Berners-Lee)的科学家,发明了HTTP

但你绝对想象不到,最初的HTTP能有多简单。

它只有一个方法GET

对,就一个。

你想获取一个网页?好,给服务器发一行字:

GET /index.html

服务器收到,嗷嗷一顿找,然后直接把内容返回给你。就这么粗暴。

没有响应头,没有状态码,没有POST,没有PUT。服务器返回什么,你就看什么。

像什么?

像一个只会说「好」的人。你问一句,它答一句,多余的一个字都没有。

但这就是HTTP的起点——一个简单到不能再简单的协议,奠定了互联网的基石。


HTTP/1.0:第一次进化

1996年,HTTP迎来了第一次大升级。

这时候的互联网已经开始热闹起来了。网页不再是纯文字,图片、音频、视频都冒出来了。原先那套「一行字」的打法,明显不够用了。

时代呼唤改变

人们开始提需求了:

  • 「我想知道请求成没成功」
  • 「我想传输其他类型的文件,不只是HTML」
  • 「我想知道这个页面有没有更新」
  • 「我想把页面做得更好看」

怎么办?HTTP/1.0来了。

新增了什么?

状态码:服务器现在会告诉你结果了。200是成功,404是找不到,500是服务器挂了——就像你问路别人会指路了一样。

请求头和响应头:你可以告诉服务器你能接受什么格式(Accept),服务器也能告诉你返回的是什么类型(Content-Type)、多大(Content-Length)。

支持多种请求方法GET有了,POST也有了。POST可以用来提交表单,比如你填完用户名密码点「登录」。

缓存机制ExpiresLast-Modified这些概念开始出现。浏览器知道什么该存、什么该用了。

这一升级,HTTP从一个只会说「好」的人,变成了一个会「点头摇头」「递纸条」「看备忘录」的完整的人。

但人们还是不满足。


HTTP/1.1:真正的霸主

1997年,HTTP/1.1发布了。

这是一个极其长寿的版本——它统治了互联网整整20多年,直到今天还有很多网站在用它。

你说它有多厉害?

HTTP/1.1的杀手锏

持久连接(Keep-Alive):这是最关键的改动。

以前的HTTP,每次请求都要建立一次TCP连接。请求完就断,断完再连。就像每次说话都要重新握手一样,累不累?

HTTP/1.1说:「别断了,咱们保持连接。」一个TCP连接可以跑完整个页面的所有请求。

管道化(Pipelining):这个就更狠了。

以前是这样的:发请求A,等响应;发请求B,等响应;发请求C,等响应——一个接一个,串着来。

HTTP/1.1可以这样:发请求A、请求B、请求C,一起发出去!不用等A的响应回来再发B。

想象一下你去麦当劳点餐。以前是:「我要一个汉堡」「好」「我要薯条」「好」「我要可乐」「好」。现在是:「我要一个汉堡、一份薯条、一杯可乐」「好嘞」。

爽不爽?

但是!

管道化有个问题:虽然请求一起发了,但响应必须按顺序回来。

这就叫「队头阻塞」(Head-of-Line Blocking)。

就像你点了三份菜,厨房先做了最简单的薯条,但得等你最想吃的汉堡做好了一起上——你只能看着薯条流口水,不能先吃。

这个问题,困扰了HTTP/1.1很多年。

其他小改进

  • 新增了一堆方法PUT(上传)、DELETE(删除)、HEAD(只获取头部)、OPTIONS(查看支持什么方法)
  • 分块传输编码Transfer-Encoding: chunked,服务器可以一块一块地返回数据,不用等全部算完
  • 缓存机制升级Cache-Control登场,比Expires更智能
  • Host头:一台服务器可以托管多个网站了(虚拟主机)

为什么HTTP/1.1能活这么久?

说白了,就是够用

虽然有队头阻塞的问题,但配合CDN、域名分片、静态资源合并这些「野路子」,1.1还是能打的。

再加上升级协议需要服务器、浏览器、CDN厂商全部配合——这是一个生态问题,不是技术问题。

所以HTTP/1.1硬是撑到了2015年,才等来下一代标准。


HTTP/2:真正的革命

2015年,HTTP/2正式发布。

这是HTTP诞生以来最大的一次升级。如果把HTTP/1.x比作绿皮火车,那HTTP/2就是高铁。

发生了什么变化?

二进制分帧:这是最底层的变化。

以前的HTTP/1.x是「文本协议」——你发的请求、服务器回的响应,都是明文写的,像写信一样。

HTTP/2改成了「二进制」——所有数据都转换成0和1来传输,就像发电报。

这意味着什么?效率更高了,因为计算机处理二进制比处理文本快多了。

而且数据被拆成了一个个「帧」(Frame),可以乱序发送、并行接收,彻底解决了队头阻塞!

多路复用(Multiplexing):这是HTTP/2的核心杀手锏。

一个TCP连接里,可以同时跑多个「流」(Stream)。每个流里可以双向传输数据,帧可以乱序、可以交叉。

还是点餐的例子:以前是点三份菜等服务员一份一份上,现在是服务员端着一个大盘子,三份菜一起给你端上来,而且你还可以边吃边点。

爽到飞起。

服务器推送(Server Push):这个功能也很革命。

以前是这样的:浏览器请求页面HTML → 服务器返回 → 浏览器解析HTML发现要CSS → 再请求CSS → 服务器返回 → 浏览器解析CSS发现要图片……

一套下来,浏览器累得够呛。

HTTP/2说:「别麻烦了,我知道你要什么。」服务器在返回HTML的时候,直接把CSS、图片一起推给你。

就像你去饭店,服务员看你落座就把碗筷、茶水、菜单一起摆好了——不用你开口。

头部压缩(HPACK)HTTP/1.x每次请求都要带一堆header,很多还是重复的。HTTP/2用HPACK算法压缩header,能省70%以上的流量。

HTTP/2的遗憾

HTTP/2解决了应用层的队头阻塞,但TCP层面还有个问题——丢包。

HTTP/2所有请求都跑在一个TCP连接上。如果其中一个包丢了,整个连接都要等它重传成功。

怎么办?

换协议呗。


HTTP/3:UDP登场

2018年,HTTP/3正式发布。

这是HTTP第一次抛弃TCP,拥抱UDP

为什么要用UDP?

TCP太可靠了——它保证数据一定到达、按顺序到达、中途不能出错。

但有时候,我们不需要这么可靠。

比如看直播——丢了一帧画面有什么关系?下一帧就来了。我要的是,不是「绝对不出错」。

UDP就是这样的「愣头青」——我负责发,你负责收,收没收到、有没有乱序,我不管。

这反而成了优势。

QUIC:HTTP/3的核心

HTTP/3用的是QUIC协议(Quick UDP Internet Connections),它是Google发明的,后来被IETF收编。

QUICUDP的方式,实现了TCP的效果:

  • 无队头阻塞:每个「流」是独立的,一个流丢包不影响其他流
  • 0-RTT连接:第一次连接后,后续连接可以瞬间建立(省去握手时间)
  • 连接迁移:你从WiFi切到5G,IP地址变了,连接不会断——因为QUIC用的是连接ID,不是IP地址
  • 内置TLS:TLS握手和QUIC握手一起完成,又省了一轮时间

简单说:TCP的优点我都有,TCP的缺点我避开,我还比TCP快。

HTTP/3带来了什么?

  • 更低的延迟
  • 更好的移动端体验(WiFi/5G切换不断连)
  • 抗丢包能力更强

HTTP/3也有问题:它需要服务器和客户端都支持,而且UDP在某些网络环境下可能被限速或被墙。

所以HTTP/2HTTP/3现在在并存使用,未来可能会慢慢过渡到3。


结尾:从一行字开始,到改变世界

回顾HTTP的进化史,你会发现一条清晰的线:

版本 年份 核心特点
HTTP/0.9 1991 只有一个GET,一行字
HTTP/1.0 1996 状态码、请求头、POST、缓存
HTTP/1.1 1997 持久连接、管道化、虚拟主机
HTTP/2 2015 二进制分帧、多路复用、服务器推送
HTTP/3 2018 QUIC + UDP、0-RTT

一行字到改变世界,从文本到二进制,从TCPUDP——HTTP用了三十多年。

今天,你打开任何一个网站、刷任何一个App、点任何一个链接——背后都是这一行字的子孙后代在为你工作。

这就是技术的魅力:从一个简单的想法出发,最终改变了整个世界。

浏览器到底在偷偷帮你做什么?——HTTP缓存与刷新机制

你的浏览器可能比你想象中更"勤俭持家"。这篇文章聊聊它是怎么帮你省流量、省时间的,以及什么时候该阻止它。


你有没有注意过这样一个现象?

第一次打开一个网页,要等好几秒。第二次打开同一个网页,基本秒开。

你是不是以为浏览器記住了这个页面?它到底是怎么做到的?

今天我们来聊聊浏览器缓存——这个你天天在用,却可能从来没认真了解过的机制。


原文地址

墨渊书肆/浏览器到底在偷偷帮你做什么?——HTTP缓存与刷新机制


缓存到底是个什么东西?

想象一下这个场景。

你每天早上都去楼下的早餐店买豆浆。第一次去的时候,老板娘要问你「要甜的還是甜的」「要不要加鸡蛋」「打包还是在这吃」——问半天,你回答半天。

但如果你连着去了一个星期,每天都点「原味豆浆,不加糖,带走」。

第七天的时候,你刚走到门口,老板娘已经把豆浆打包好了递给你,连话都不用说一句。

这就是缓存。

浏览器做的就是这件事。第一次访问一个网页,它要千里迢迢去服务器「要」资源。第二次访问,它就聪明了——直接从自己的「小仓库」里拿出来给你用,省时又省力。

但问题来了:浏览器怎么知道哪些东西可以直接用?哪些东西已经过期了?

这就涉及到HTTP缓存的两个核心概念:强缓存协商缓存


强缓存:先用了再说

强缓存就像是你跟浏览器达成的一个小协议。

你告诉它:「这个资源在未来一年内都不会变,你就放心大胆地用,别来问我。」

浏览器听了这话,就直接把资源扔给你,连服务器的大门都不带敲的。

那这个"一年"的承诺是怎么实现的呢?

Expires:看时间

最早的方式是用Expires这个响应头:

Expires: Wed, 21 Oct 2026 07:28:00 GMT

这就像在商品上贴了个过期日期:「2026年10月21日之前都有效。」

但这个方式有个bug:如果你的电脑时间和服务器时间不一致,比如你把电脑调快了一个月,那缓存就直接失效了——浏览器会以为已经过期了,实际上还能用。

Cache-Control:更聪明的做法

后来HTTP/1.1推出了Cache-Control,就像给缓存装了个更智能的计时器:

Cache-Control: max-age=3600, public

max-age=3600的意思是:缓存有效期是3600秒,也就是一个小时。

这个比Expires靠谱多了——它是相对时间,不受系统时间影响。

而且Cache-Control还支持一堆指令,让你能更精细地控制缓存行为:

指令 意思 什么时候用
public 缓存可以放在CDN、代理服务器上 静态资源
private 只准浏览器自己缓存 个性化内容
no-cache 每次用之前先问问我 经常变化的资源
no-store 别存了,每次都重新拿 敏感数据
immutable 这东西永远不会变 版本化后的静态资源

这里有个重点:no-cache不是"不缓存",而是"用之前先问一下"。


协商缓存:问一下再决定

强缓存虽然快,但有个问题:如果服务器上的资源已经变了,浏览器可不知道。

你跟浏览器说「这个文件缓存一年」,结果三个月后你更新了网站,浏览器还在用旧的——用户就看不到新内容了。

怎么办?

协商缓存就是这个问题的答案。

它的逻辑是这样的:浏览器还是要去问一下服务器:「我这里有个缓存,还能用吗?」

服务器说「能用」(资源没变),返回304 Not Modified,浏览器继续用缓存。

服务器说「不能用」(资源变了),返回200 OK + 新资源,浏览器更新缓存。

Last-Modified:看修改时间

最早的方式是用Last-Modified

# 服务器返回
Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT

# 浏览器下次请求
If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT

就像你问老板:「这个文件最后改过是什么时候?如果还是那天下午,我就继续用我的版本。」

但这个方式有个缺点:精度只到秒。如果一秒内文件被修改了两次,浏览器可看不出来。

ETag:看"指纹"

后来就有了ETag,它给每个文件生成一个"指纹":

# 服务器返回
ETag: "abc123"

# 浏览器下次请求
If-None-Match: "abc123"

这个指纹通常是文件的MD5哈希值,或者其他能唯一标识内容的东西。

服务器收到请求后,会比较一下ETag:如果指纹一样,说明内容没变, 返回304;如果不一样,返回200 + 新内容。

划重点:ETag的优先级高于Last-Modified。如果服务器同时给了这两个,浏览器会先用ETag。


缓存到底是怎么工作的?

让我给你串起来整个流程:

你访问一个页面
    ↓
浏览器先看强缓存(Cache-Control / Expires)
    ↓
[命中了] → 直接从本地拿 → 页面秒开 ✅
    ↓ [没命中]
浏览器带着缓存标识去问服务器
    ↓
服务器比较ETag / Last-Modified
    ↓
[资源没变] → 返回304 → 浏览器用缓存 → 依然很快 ⚡
    ↓ [资源变了]
服务器返回200 + 新资源 + 新标识
    ↓
浏览器更新缓存,展示新内容

这个流程你理解之后,很多奇怪的现象就能解释了:

  • 为什么更新了CSS但页面没变?——可能被强缓存了
  • 为什么F5刷新后还是旧内容?——正常,优先用强缓存
  • 为什么Ctrl+F5就变了?——强制刷新,绕过了所有缓存

刷新这件事,讲究这么多?

说到刷新,我发现很多人(包括以前的我)对浏览器的刷新按钮有误解。

你以为的刷新:「重新加载这个页面」

实际上的刷新:「emmm,让我先看看缓存有没有过期」

正常刷新(F5 / 点击链接)

这是最常用的方式。

浏览器会先看强缓存,过期了吗?没有就直接用。过期了就去协商,服务器说能用就用。

结果:可能快(304),也可能慢(200),取决于缓存状态。

强制刷新(Ctrl+Shift+R / Ctrl+F5)

这个才是真正的"重新加载"。

浏览器会跟服务器说:「少废话,把所有资源都给我拿新的,别跟我提缓存!」

请求头里会带上Cache-Control: no-cache,或者直接忽略所有的缓存标识。

结果:总是200,慢但保证最新。

开发者工具里的选项

Chrome DevTools里其实有更精细的控制:

  • 禁用缓存:只有DevTools打开时才生效,模拟no-cache
  • 硬性重新加载:等于强制刷新
  • 空缓存并硬性重新加载:先清空所有缓存,再强制刷新——相当于把浏览器的小仓库一把火烧了

说完了缓存,来聊聊安全

缓存虽好,但有时候也会带来安全问题。

比如你登录了一个网站,浏览器缓存了你的个人信息。然后别人用了你的电脑,打开同一个网站——诶,怎么直接就登录了?

这就是缓存的"副作用"。所以有些东西是不能缓存的。

no-store:敏感数据别存

Cache-Control: no-store

这个指令告诉浏览器:「看归看,但别存到硬盘上。」内存里用完就扔,下次重启就没了。

登录后的用户信息、token、支付相关的数据——这些都应该加上no-store

private:只存浏览器

Cache-Control: private

这个的意思是:「可以缓存,但只能存在用户自己的浏览器里,别给CDN、代理那些中间商。」

用户信息存private,静态资源存public——这是基本的安全常识。


聊完缓存,再聊聊HTTPS

既然说到安全,顺便提一下HTTPS。

你可能知道HTTPS是"加密的HTTP",但它跟缓存有什么关系呢?

其实没有直接关系。但HTTPS有一个相关的安全头:

Strict-Transport-Security: max-age=31536000; includeSubDomains

这叫HSTS,简单说就是告诉浏览器:「以后别用HTTP跟我玩了,直接给我用HTTPS。」

防止一种叫"SSL剥离"的攻击——黑客在中间把HTTPS降级成HTTP,偷看你的数据。

还有哪些安全头值得关注?

作用
X-Frame-Options: DENY 防止别人把你的页面嵌在iframe里(点击劫持)
X-Content-Type-Options: nosniff 告诉浏览器别乱猜内容类型
Content-Security-Policy 限制资源加载来源,防止XSS
Referrer-Policy 控制 Referrer 信息泄露

这些安全头配置起来不麻烦,但能挡住很多常见攻击。建议都配置上。


到底该怎么用?

说了一堆原理,最后来点实用的。

不同资源,不同策略

资源类型 推荐策略
JS / CSS / 图片 max-age=31536000, immutable(一年,不用改)
HTML页面 no-cache,每次都协商
API接口 no-cacheprivate
用户敏感数据 no-store

核心原则

  • 静态资源:狠命缓存,文件名带hash,变了就改文件名
  • HTML:别缓存,随时要最新
  • API:看场景,频繁变化的要协商,不变的可以强缓存
  • 敏感数据:有多远滚多远,别缓存

总结一下

这篇文章聊了浏览器缓存和刷新机制的核心概念:

  • 强缓存Cache-Control / Expires):直接用,不过问服务器
  • 协商缓存ETag / Last-Modified):问一下服务器能不能用
  • 刷新:F5看缓存,Ctrl+F5硬刷新
  • 安全no-store防敏感数据泄露,private防中间商缓存
  • HTTPS相关:HSTS、安全响应头

理解这些机制之后,你就能解释很多奇怪的现象,也能更好地优化你的Web应用性能。

❌