HTTP
put请求和delete方法是具有幂等性,post请求不是。
幂等性是指一个操作在执行一次和执行多次所产生的最终结果是一致的。它是一个来源于数学的概念,在计算机科学和分布式系统中尤其重要,尤其是在处理重复请求时,例如用户多次点击下单按钮导致重复下单,可以通过设计幂等性来避免此类问题。
keep-alive
keep-alive不是长连接,可以复用tcp连接,websocket是长连接
当第一个请求之后,在timeout时间内,收到第二个请求,会复用tcp,且规定了最大次数,在timeout时间之后没有收到第二个请求,会关闭
带宽和网速
一、我们一般怎么讨论“网速延迟”?
当我们讨论延迟时,我们通常使用以下三个关键指标,尤其是在游戏玩家的语境里:
延迟 (Latency) / Ping 值
- 是什么: 这是最核心的指标。它指的是一个数据包从你的电脑出发,到达游戏服务器,然后再返回到你的电脑所需要的总时间。这个往返时间(Round-Trip Time, RTT)就是我们常说的“Ping值”。
- 单位: 毫秒 (ms)。
- 如何讨论: “你 Ping 多少?” “我 Ping 才30,很流畅。” “我 Ping 200了,卡得瞬移了!”
- 好坏标准:
- < 20ms: 职业选手级的丝滑体验。
- 20ms - 50ms: 非常流畅,绝大多数玩家的理想状态。
- 50ms - 100ms: 可以玩,但高手能感觉到轻微的延迟。
- > 100ms: 明显卡顿,操作“粘滞”,体验很差。
抖动 (Jitter)
- 是什么: 指的是 Ping 值的不稳定性。比如你的 Ping 值在 30ms 和 150ms 之间来回跳动。
- 为什么重要: 不稳定的网络比持续的高延迟更令人抓狂。它会导致游戏画面时而流畅时而卡住,就像看视频一直缓冲一样。稳定的100ms延迟,好过在30-150ms之间跳动的延迟。
丢包 (Packet Loss)
- 是什么: 你发送给服务器的数据包,或者服务器发给你的数据包,在传输过程中丢失了。
- 为什么重要: 丢包会导致游戏中的“瞬移”或“回弹”。比如你明明往前跑了,突然又回到了几秒前的位置,就是因为服务器没收到你“往前跑”的数据包,或者你没收到服务器更新你位置的数据包。
所以,讨论游戏网络好坏时,内行会说:“我这网络延迟很低,Ping常年稳定在30ms,基本不抖动也不丢包。”
二、为什么打游戏卡顿和带宽没关系?
这个问题的核心在于,不同网络应用对“带宽”和“延迟”的需求是完全不同的。
让我们再次使用那个绝佳的比喻:
- 带宽 = 高速公路的车道数量
- 延迟 = 每辆车的行驶速度 + 路程长短
1. 打游戏是什么样的?
打游戏就像是“实时对讲机通话”。
- 你和服务器之间需要快速、持续地交换信息:“我动了”、“我开枪了”、“敌人在这里”。
- 每一条信息的数据量都非常非常小(就像对讲机里说的几个字)。
- 对游戏来说,最重要的是“你说的话多久能被对方听到”,也就是延迟。如果你的话要过1秒才被听到,那对话就无法进行了。
- 你并不需要一次性说一大段话,所以你根本不需要很宽的“公路”。1条车道就绰绰有余了。
2. 下载电影是什么样的?
下载电影就像是“搬家”。
- 你需要把一个巨大的文件(一屋子家具)从服务器搬到你家。
- 你对“每辆卡车开多快”不是最敏感的,你最关心的是“同时能有多少辆卡-车在路上跑”,也就是带宽。
- 用100条车道(100M带宽)同时运家具,肯定比用1条车道快得多。
结论:
一个主流的在线游戏(如LOL,CS:GO),在玩的时候数据流量通常只有 几十到几百 KB/s (注意是 K,不是 M)。1 Mbps = 1000 Kbps。
你的100M宽带,带宽容量是 100,000 Kbps。
拿 100,000 Kbps 的带宽去跑一个只需要 100 Kbps 流量的游戏,就像用一个航空母舰的甲板去起降一架玩具无人机。容量绰绰有余,完全不是瓶颈。
所以,当你打游戏卡的时候,99%的原因是:
- 你的数据包(小汽车)去服务器的路(物理距离)太远了。
- 路上的某些节点(路由器、交换机)堵车了。
- 你家的无线WiFi信号不好,导致数据包在家里就耽搁了。
这都表现为高延迟 (Ping)、抖动、丢包,而不是带宽不够。
三、总结关于带宽的知识
好的,我们来系统地梳理一下所有关于带宽的知识点。
1.【定义】带宽是什么?
带宽(Bandwidth)是在单位时间内,网络连接所能传输的最大数据量。它衡量的是网络的“容量”或“吞吐能力”,不是速度。
- 比喻: 高速公路的车道数量。车道越多,单位时间能通过的汽车越多。
2.【单位】如何衡量带宽?
- 标准单位: bps (bits per second,比特每秒)。我们常说的是 Mbps (Megabits per second,兆比特每秒)。
- 关键换算: 日常下载速度的单位是 MB/s (MegaBytes per second,兆字节每秒)。
- 1 Byte = 8 bits
- 所以,理论下载速度 = 带宽(Mbps) / 8。例如,100M宽带的理论下载速度是
100 / 8 = 12.5 MB/s。
3.【核心区别】带宽 vs. 延迟
这是最重要的概念区分。
- 带宽 (Bandwidth): 容量问题,决定“一次能传多少”。
- 延迟 (Latency/Ping): 时间问题,决定“传一次要多久”。
- 比喻: 带宽是水管的粗细,延迟是水流的速度。一个粗水管(高带宽)不代表水龙头一开水就立刻流出来(低延迟)。
4.【应用场景】什么应用需要什么?
| 需求类型 | 核心指标 | 应用场景 | 比喻 |
|---|---|---|---|
| 高带宽敏感型 | 带宽 (Mbps) | 下载大文件、看4K/8K超高清视频、云盘同步 | 搬家,需要很多卡车同时运输 |
| 低延迟敏感型 | 延迟 (Ping) | 在线竞技游戏、视频通话、远程桌面、股票交易 | 实时对话,需要话音快速传达 |
最终结论:
你办理的“100M宽带”,是在为高带宽付费,它确保了你看视频、下载东西的体验。而你打游戏的流畅度,则由延迟(Ping值)决定,它受到你家到游戏服务器之间所有网络环节的共同影响,与你的带宽大小基本无关。
强缓存和协商缓存
总结:浏览器决策流程图
当浏览器需要一个资源时,它会按以下顺序决策:
- 检查强制缓存 (
Cache-Control/Expires)。- 缓存有效? -> 是 -> 直接从本地读取资源。(流程结束)
- 缓存有效? -> 否 -> 进入下一步。
- 准备发起协商缓存请求。在请求头中加入
If-Modified-Since和/或If-None-Match。 - 向服务器发送请求。
- 服务器进行比较。
- 资源未变? -> 是 -> 服务器返回
304 Not Modified。浏览器从本地读取资源。(流程结束) - 资源未变? -> 否 -> 服务器返回
200 OK和新资源。浏览器下载新资源,并更新本地缓存。(流程结束)
- 资源未变? -> 是 -> 服务器返回
对比表格
| 特性 | 强制缓存 (Strong Cache) | 协商缓存 (Negotiation Cache) |
|---|---|---|
| 核心目的 | 避免请求 | 减少响应体大小 |
| 是否访问服务器 | 否 | 是 |
| 服务器响应 | 无 | 304 Not Modified 或 200 OK |
| 性能 | 极高 (无网络延迟) | 较高 (有网络延迟,但可能无下载) |
| 控制响应头 | Cache-Control, Expires |
Last-Modified, ETag |
| 关联请求头 | 无 | If-Modified-Since, If-None-Match |
1. 强制缓存 (Strong Cache)
- 工作方式: 浏览器拿到资源后,如果缓存没过期,连请求都不会向服务器发送,直接从本地硬盘或内存中读取资源。这是最快的方式,状态码通常是
200 OK (from disk cache)或200 OK (from memory cache)。 - 后端如何控制: 通过设置以下两个响应头之一(
Cache-Control优先)。Cache-Control(HTTP/1.1, 推荐使用)max-age=<seconds>: 告诉浏览器,资源在N秒内是有效的,无需再请求。例如Cache-Control: max-age=31536000表示缓存一年。no-cache: 这个名字有误导性! 它不是“不缓存”,而是“跳过强制缓存,直接进入协商缓存”。即每次都必须向服务器确认一下资源是否有效。no-store: 这个才是“完全不缓存”,浏览器收到后不会在本地留下任何副本。public/private:public表示代理服务器(如CDN)也可以缓存;private表示只有最终用户的浏览器可以缓存。
Expires(HTTP/1.0, 已过时)Expires: Wed, 21 Oct 2025 07:28:00 GMT: 设置一个具体的过期时间点。缺点是依赖客户端本地时间,如果用户时间不准,缓存就会出问题。所以现在都用Cache-Control的相对时间。
2. 协商缓存 (Negotiation Cache)
- 工作方式: 当强制缓存失效后(或者设置了
Cache-Control: no-cache),浏览器会向服务器发送一个请求,但这个请求是去“协商”的,不是直接要数据。- 如果服务器判断资源没有变化,会返回一个极简的
304 Not Modified响应,响应体为空。浏览器收到后,就放心地使用本地的旧资源。 - 如果服务器判断资源已更新,会返回一个完整的
200 OK响应,带着新的资源内容和新的缓存头。
- 如果服务器判断资源没有变化,会返回一个极简的
- 后端如何控制: 这需要后端和浏览器配合,通过两对“请求头-响应头”来实现。
第一对:
Last-Modified和If-Modified-Since- 后端首次响应时,带上
Last-Modified: <文件最后修改时间>。 - 浏览器再次请求时,在请求头里带上
If-Modified-Since: <上次收到的时间>。 - 后端比较这个时间和文件的当前修改时间,如果一致,返回
304。
- 后端首次响应时,带上
第二对:
ETag和If-None-Match(更优)- 后端首次响应时,根据文件内容生成一个唯一的标识符(Hash值),放在
ETag: "<hash-string>"中。 - 浏览器再次请求时,在请求头里带上
If-None-Match: "<上次收到的ETag值>"。 - 后端比较这个 ETag 和当前文件内容的 ETag,如果一致,返回
304。
- 为什么 ETag 更好? 因为它只关心内容是否变化。
Last-Modified有时不靠谱(比如文件内容没变,只是被重新保存了一下,修改时间变了;或者修改间隔小于1秒,无法识别)。
- 后端首次响应时,根据文件内容生成一个唯一的标识符(Hash值),放在
3.为什么我们处理时“似乎根本没有考虑”?
这是因为大部分工作都被 Web 服务器或框架自动完成了!
你用 hexo 生成的是静态网页(HTML, CSS, JS, 图片等)。当你把这些文件部署到生产环境时,通常会使用 Nginx 或 Apache 这样的专业 Web 服务器。
Nginx 会非常智能地帮你处理静态文件的缓存:
- 当你请求一个
style.css文件时,Nginx 会自动计算它的ETag和Last-Modified,并把它们加到响应头里。 - 下一次浏览器再来请求这个文件时,就会带上
If-None-Match和If-Modified-Since。Nginx 收到后,会自动进行比较,如果文件没变,就自动返回304。 - 你甚至可以在 Nginx 的配置里,为不同类型的文件(如图片、CSS、JS)统一设置
Cache-Control: max-age,实现强制缓存。
所以,不是你没考虑,是你的“好帮手”(Nginx)帮你考虑了,并且做得很好。 对于动态内容(比如通过Java/Python/Node.js后端从数据库里查数据生成的页面),框架(如Express.js, Spring)也提供了设置这些缓存头的API,但需要开发者自己去调用。
4.为什么用 Hexo 调试时要 Ctrl+F5?
这正是你遇到的核心痛点,原因在于你使用的环境:hexo server。
- 这是一个开发服务器,不是生产服务器:
hexo s启动的是一个轻量级的本地开发服务器。它的首要目标是方便和快速响应,而不是性能优化。 - 默认的缓存策略:为了让刷新看起来快,这个开发服务器可能会设置一些默认的缓存头(比如一个较短的
max-age),或者干脆不设置,让浏览器自己决定如何缓存(浏览器的默认行为通常是会缓存的)。 - 结果:当你修改了文件内容后,
hexo s会重新生成页面,但你直接刷新浏览器(F5),浏览器可能因为强制缓存还没过期,或者发送协商缓存请求后,开发服务器没能正确处理304逻辑,导致浏览器依然使用了旧的缓存文件。
Ctrl+F5(强制刷新)做了什么?
它发送的请求头里会包含 Cache-Control: no-cache,这个指令会强制浏览器忽略所有本地缓存(强制缓存和协商缓存),完完整整地向服务器请求一个全新的资源。这就是为什么它总能看到最新的内容。
调试时的最佳实践
你不需要每次都 Ctrl+F5!有一个更优雅、更彻底的方法:
打开浏览器开发者工具 (F12),切换到 “Network” (网络) 面板,勾选 “Disable cache” (禁用缓存)。
只要开发者工具开着,这个选项就会一直生效。此时,你每次刷新页面,浏览器都会像第一次访问一样,请求所有资源,完美解决你的调试问题。
总结
- 能控制吗? 能,通过后端的 HTTP 响应头 (
Cache-Control,ETag,Last-Modified)。 - 为什么平时感觉不到? 因为你的 Web 服务器 (Nginx) 或框架 帮你自动处理了静态文件的协商缓存。
- 为什么 Hexo 本地调试要
Ctrl+F5? 因为你用的是开发服务器,它的缓存策略不适合开发-刷新-查看的流程。 - 最佳解决方案: 开发时,打开 **F12 -> Network -> 勾选 “Disable cache”**。部署到生产环境后,你的 Nginx 服务器会为你处理好一切。
DNS和CDN
为了方便理解,我们可以用一个简单的比喻开头:
- DNS 就像是互联网的“114查号台”:你告诉它一个网站的名字(域名,比如
www.google.com),它会告诉你这个网站的地址(IP 地址,比如172.217.160.78)。它的核心任务是“指路”。 - CDN 就像是连锁超市的“前置仓”或“物流网络”:你不用去遥远的工厂(源服务器)取货(网站内容),而是可以直接从离你家最近的连锁店仓库(CDN 边缘节点)拿到。它的核心任务是“加速送货”。
一、核心区别 (What’s the Difference?)
| 方面 (Aspect) | DNS (Domain Name System) | CDN (Content Delivery Network) |
|---|---|---|
| 核心功能 | 域名解析 (Name Resolution) | 内容分发与加速 (Content Delivery & Acceleration) |
| 解决的问题 | “如何通过名字找到服务器?”解决了 IP 地址难记、不固定的问题。 | “如何让用户更快地获取服务器上的内容?”解决了网络延迟、源服务器负载过高的问题。 |
| 工作原理 | 接收域名查询请求,通过分布式数据库查询,返回对应的 IP 地址。 | 将源服务器的内容缓存到全球各地的边缘节点上,引导用户访问最近的节点,直接从缓存中获取数据。 |
| 对用户而言 | 用户无感知,是访问网络前的第一步,负责“导航”。 | 用户能感受到明显的速度提升,是数据传输过程中的“加速器”。 |
| 部署实体 | 由全球无数 DNS 服务器(根、顶级域、权威等)组成的层级系统。 | 由遍布全球的边缘服务器(Edge Server)和一套智能调度系统组成。 |
| 比喻总结 | 电话本 / 导航系统 | 物流网络 / 连锁超市 |
二、相同之处与关联 (What’s the Same & How They Relate?)
虽然功能截然不同,但它们也有共同点,并且关系非常紧密:
共同目标:两者都是为了提升用户的互联网访问体验。一个让“找”的过程变得简单,一个让“取”的过程变得更快。
分布式系统:DNS 和 CDN 都是大规模的分布式系统。DNS 服务器遍布全球,CDN 的边缘节点也遍布全球,这保证了它们的高可用性和高效率。
协同工作:这是最关键的一点。CDN 的高效运行离不开 DNS 的智能调度。 现代网络中,DNS 不再是简单地返回一个固定的 IP 地址。当一个网站使用了 CDN 服务后,DNS 的作用变得更加智能。
- 当用户请求一个启用了 CDN 的域名时,这个域名的解析请求会被交给 CDN 厂商的智能 DNS 系统。
- 这个智能 DNS 系统会根据用户的 IP 地址、网络状况、节点负载等信息,计算出对该用户来说“最佳”的 CDN 边缘节点。
- 最后,DNS 返回的不是源服务器的 IP 地址,而是这个最佳 CDN 边缘节点的 IP 地址。
所以,可以说 DNS 是 CDN 发挥作用的第一环。DNS 负责把用户“指引”到正确的 CDN 仓库门口,然后 CDN 再负责把货物快速地交到用户手上。
三、在计算机网络过程中的位置和过程 (Position and Process)
让我们通过一个完整的用户访问流程,来看看 DNS 和 CDN 是如何一步步工作的。
场景: 用户小明在上海,想要访问一个部署在美国的网站 www.example.com,该网站已经使用了 CDN 服务。
流程图解:用户 -> DNS解析 -> CDN边缘节点 -> (若无缓存) -> 源服务器
详细步骤:
第 1 步:DNS 解析(DNS 的主场)
- 小明在浏览器输入
www.example.com并回车。 - 浏览器首先检查自身缓存,看之前是否访问过这个域名,如有且未过期,则直接使用缓存的 IP 地址(跳到第 3 步)。
- 若无缓存,浏览器向操作系统请求解析,操作系统检查本地
hosts文件和自身缓存。 - 若本地无解,请求会发送到小明的本地 DNS 服务器(通常由运营商提供,如上海电信的 DNS)。
- 本地 DNS 服务器开始递归查询:
- 它会去问根 DNS 服务器:“
.com归谁管?” - 根服务器回答:“去找
.com的顶级域(TLD)DNS 服务器。” - 本地 DNS 再去问
.com的 TLD 服务器:“example.com归谁管?” - TLD 服务器回答:“去找
example.com的权威 DNS 服务器。”(这个权威 DNS 通常就是网站主在购买域名或 CDN 服务时指定的服务器)。
- 它会去问根 DNS 服务器:“
第 2 步:DNS 与 CDN 的智能交接(关键环节)
6. example.com 的权威 DNS 服务器实际上是 CDN 服务商提供的智能 DNS 系统。
7. 这个智能 DNS 系统接收到来自上海电信 DNS 的查询请求,它分析出这个请求源自上海地区。
8. 它会从自己遍布全球的 CDN 节点中,挑选一个离上海最近、延迟最低、负载最轻的节点,比如“CDN 上海节点”。
9. 最终,这个智能 DNS 系统向小明的本地 DNS 服务器返回“CDN 上海节点”的 IP 地址(例如 202.96.209.133),而不是远在美国的源服务器 IP。
10. 本地 DNS 服务器将这个 IP 地址返回给小明的电脑,并缓存起来以备后用。
至此,DNS 的核心任务完成。它成功地把小明“导航”到了最近的 CDN 节点。
第 3 步:内容获取(CDN 的主场)
11. 小明的浏览器拿到了“CDN 上海节点”的 IP 地址,于是向这个 IP 发起 HTTP/HTTPS 请求,索要 www.example.com 的首页内容。
12. “CDN 上海节点” 收到请求后,检查自己的缓存:
- 情况 A(缓存命中 Cache Hit): 如果这个节点已经缓存了首页内容,并且内容没有过期。它会立刻将内容打包,通过高速网络直接发送给小明。整个过程极快,请求不会到达美国。
- 情况 B(缓存未命中 Cache Miss): 如果这是第一次有人从这个节点请求该页面,或者缓存已过期。
- “CDN 上海节点”会扮演一个“代购”的角色,向远在美国的源服务器发起请求,获取首页内容。
- 源服务器将内容发送给“CDN 上海节点”。
- 上海节点收到内容后,先将其缓存在自己的硬盘/内存中(以便下次上海地区的用户访问时可以直接提供),然后再将内容发送给小明。
整个流程结束。 小明最终快速地打开了网站,他完全不知道自己的请求实际上是由上海的一个服务器处理的,而不是直接从美国获取的。