Skip to content

[toc]

一、 HTTP 请求方法深度对比

1. GET vs POST

  • 幂等性:GET 是幂等的(多次执行结果相同),POST 是非幂等的(多次执行会创建多个资源)
  • 安全性:GET 参数暴露在 URL 中,会被浏览器历史记录保留;POST 数据在 Body 中,相对更私密
  • 缓存:GET 默认可缓存;POST 除非特别设置,否则不缓存

2. POST vs PUT

  • POST:侧重于“新建”,向服务器发送数据以创建新资源
  • PUT:侧重于“更新”,通过发送完整数据来修改现有资源。PUT 也是幂等的

3. 常见的HTTP请求头和响应头

请求头 (Request Headers)

  1. 基础信息

    • Host: 服务器的域名(和端口号)

    • User-Agent (UA): 浏览器的“名片”,包含操作系统、浏览器版本等信息。常用于反爬虫或区分移动端/桌面端

    • Referer: 告诉服务器当前请求是从哪个页面链接过来的(常用于防盗链)

  2. 内容协商

    • Accept: 浏览器告诉服务器自己能接收的内容类型(如 text/html, application/json

    • Accept-Encoding: 告知服务器支持的压缩算法(如 gzip, br

    • Accept-Language: 优先接收的语言(如 zh-CN,en;q=0.9

  3. 认证与状态

    • Cookie: 客户端存储的会话标识,每次请求会自动带上

    • Authorization: 用于 HTTP 认证(如 Bearer <token>

响应头 (Response Headers)

  1. 实体信息

    • Content-Type: 返回内容的 MIME 类型(如 text/html; charset=utf-8

    • Content-Length: 响应体的字节长度

    • Content-Encoding: 告诉浏览器实际使用的压缩格式(如 gzip

  2. 缓存控制

    • Cache-Control: 强缓存策略(如 max-age=3600, no-cache

    • ETag: 资源的唯一标识符(由服务器生成),用于协商缓存

    • Last-Modified: 资源最后修改时间

  3. 安全与跨域 (CORS)

    • Access-Control-Allow-Origin: 允许跨域访问的源(如 * 或具体的域名)

    • Set-Cookie: 服务器向客户端设置 Cookie

    • Server: 服务器软件名称(出于安全考虑,生产环境通常会隐藏或伪装)

二、HTTP 状态码

1xx 信息性响应

  • 100 Continue:由于请求包含大实体,客户端先发 Header 询问,服务器允许后客户端再发送 Body(避免浪费带宽)
  • 101 Switching Protocols协议切换。服务器同意升级协议,最常用于 WebSocket 握手成功后的确认
  • 103 Early Hints预加载提示。在服务器返回完整响应前,先让浏览器预加载 CSS/JS 资源以优化性能

2xx 成功 (Success)

  • 200 OK:请求成功,数据已正常返回
  • 201 Created:请求成功且服务器创建了新的资源(常用于 POST
  • 204 No Content:请求成功,但响应报文不包含实体主体(常用于 OPTIONS 预检请求)
  • 206 Partial Content部分内容。服务器成功处理了范围请求,常用于 断点续传视频分段加载

3xx 重定向 (Redirection)

  • 301 Moved Permanently永久重定向。浏览器下次会直接请求新 URL(对 SEO 友好)
  • 302 Found临时重定向。资源临时移动,下次还会请求原 URL
  • 304 Not Modified协商缓存命中。告诉浏览器缓存还能用,不返回网页内容,节省流量
  • 307 Temporary Redirect:临时重定向,且不允许浏览器将 POST 请求改为 GET

4xx 客户端错误 (Client Error)

  • 400 Bad Request:请求报文语义错误(参数格式不对)
  • 401 Unauthorized:未授权,需要身份验证(如 Token 失效)
  • 403 Forbidden:服务器理解请求但拒绝执行(没权限)
  • 404 Not Found:服务器上找不到请求的资源
  • 405 Method Not Allowed:请求方法(GET/POST等)不对
  • 408 Request Timeout请求超时。客户端发送数据太慢,服务器等不及先关闭了连接
  • 429 Too Many Requests请求过于频繁。触发了限流机制

5xx 服务器错误 (Server Error)

  • 500 Internal Server Error:服务器代码执行出错(崩溃或报错)
  • 502 Bad Gateway:充当网关或代理的服务器从后端收到了无效响应(通常是 Nginx 找不到 Node.js/Java 后端)
  • 503 Service Unavailable:服务器超载或正在维护
  • 504 Gateway Timeout:网关超时(后端处理太慢,没在规定时间内返回)

三、HTTP 协议版本

版本核心改进解决的问题
HTTP 1.0基本请求-响应模式建立基础连接
HTTP 1.1持久连接 (Keep-Alive)、断点续传、Host 字段减少 TCP 建连开销,支持虚拟主机
HTTP 2.0多路复用、二进制分帧、首部压缩 (HPACK)、服务器推送解决“队头阻塞”,提高并发效率
HTTP 3.0基于 UDP 的 QUIC 协议、0-RTT 建连彻底解决 TCP 层的队头阻塞,提升移动端连接稳定性

HTTP/1.1

  1. Keep-Alive (长连接):默认开启。一个 TCP 连接可以发送多个请求,避免了频繁的三次握手
  2. 虚拟主机:新增 Host 头,允许一台服务器运行多个网站
  3. 缓存处理:引入了ETag、Cache-Control
  4. 缺陷队头阻塞 (Head-of-line blocking)。虽然连接复用了,但请求必须按顺序排队

HTTP/2:

  1. 二进制分帧:不再传输纯文本,而是二进制帧
  2. 多路复用:在一个 TCP 连接里,多个请求可以交错并行发送。彻底解决了 HTTP 层的队头阻塞
  3. HPACK 头部压缩:通过静态表和动态表减少重复的 Header 大小(如每次都带的 User-Agent)

HTTP/3:

  1. 基于 QUIC 协议:放弃 TCP,改用 UDP
  2. 更快的握手:将 TLS 加密和传输握手合并,通常 0-RTT 或 1-RTT 就能建立连接

四、HTTP 与 HTTPS 之间区别

维度HTTP (HyperText Transfer Protocol)HTTPS (HTTP over SSL/TLS)
安全性明文传输,内容可能被窃听或篡改。加密传输,确保数据的私密性与完整性。
证书无需证书。需要从 CA(数字证书认证机构) 申请证书。
默认端口80443
身份认证无,无法确认对方真实身份。有,通过证书验证服务器身份,防止钓鱼。

HTTPS 的工作原理(TLS 握手)

当你访问一个 HTTPS 网站时,背后发生了以下精密的过程:

  1. 客户端发起请求:浏览器向服务器发送 SSL 版本号、支持的加密算法列表和一个随机数 A
  2. 服务器发送证书:服务器确认加密算法,发送自己的 CA 证书和一个随机数 B
  3. 验证证书:浏览器验证证书合法性
  4. 密钥交换(非对称加密):如果没问题,浏览器会生成第三个随机数 C(预主密钥),并用证书里的公钥加密后传给服务器
  5. 数据传输(对称加密):服务器用私钥解密得到随机数 C,此时,双方都有了 A、B、C 三个随机数,双方通过相同的算法,把这三个随机数混合生成最终的对话密钥(Session Key),此后的网页内容传输全部用该密钥进行高效的对称加密

五、当在浏览器中输入 Google.com 并且按下回车之后发生了什么?

  1. **解析URL:**首先会对 URL 进行解析,分析所需要使用的传输协议和请求的资源的路径(生产 HTTP 请求信息)
  2. 缓存判断: 浏览器会判断所请求的资源是否在缓存里,如果请求的资源在缓存里并且没有失效,那么就直接使用,否则向服务器发起新的请求
  3. **DNS解析:**将域名转换成 IP 地址
    • 下一步首先需要获取的是输入的 URL 中的域名的 IP 地址,首先会判断本地是否有该域名的 IP 地址的缓存,如果有则使用,如果没有则向本地 DNS 服务器发起请求。本地 DNS 服务器也会先检查是否存在缓存,如果没有就会先向各级域名服务器发起请求,最终获得域名的 IP 地址后,本地 DNS 服务器再将这个 IP 地址返回给请求的用户(查询优先级:浏览器缓存 -> 系统缓存 (Hosts) -> 路由器缓存 -> ISP 递归 DNS 服务器)
  4. TCP三次握手:首先客户端向服务器发送一个 SYN 连接请求报文段和一个随机序号,服务端接收到请求后向服务器端发送一个 SYN ACK报文段,确认连接请求,并且也向客户端发送一个随机序号。客户端接收服务器的确认应答后,进入连接建立的状态,同时向服务器也发送一个ACK 确认报文段,服务器端接收到确认后,也进入连接建立状态
  5. **HTTPS握手:**如果使用的是 HTTPS 协议,在通信前还存在 TLS 的一个四次握手的过程
    • 首先由客户端向服务器端发送使用的协议的版本号、一个随机数和可以使用的加密方法。服务器端收到后,确认加密的方法,也向客户端发送一个随机数和自己的数字证书。客户端收到后,首先检查数字证书是否有效,如果有效,则再生成一个随机数,并使用证书中的公钥对随机数加密,然后发送给服务器端。服务器端接收后,使用自己的私钥对数据解密。这个时候双方都有了三个随机数,按照之前所约定的加密方法,使用这三个随机数生成一把秘钥,以后双方通信前,就使用这个秘钥对数据进行加密后再传输
  6. 发送 HTTP 请求:浏览器构建请求报文
  7. **服务器处理,返回 HTTP 响应:**当页面请求发送到服务器端后,服务器端会返回一个 html 文件作为响应,浏览器接收到响应后,开始对 html 文件进行解析,开始页面的渲染过程
  8. 页面渲染:浏览器首先会根据 html 文件构建 DOM 树,根据解析到的 css 文件构建 CSSOM 树。当 DOM 树和 CSSOM 树建立好后,根据它们来构建渲染树(Render Tree )。渲染树构建好后,会根据渲染树来进行布局。布局完成后,最后使用浏览器的 UI 接口对页面进行绘制
  9. TCP四次挥手:客户端向服务端发送连接释放请求。服务端收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,当前服务端仍旧可以发送数据给客户端。服务端如果此时还有没发完的数据会继续发送,完毕后会向客户端发送发送 FIN ACK 连接释放请求,然后服务端便进入 LAST-ACK 状态。客户端收到释放请求后,向服务端发送确认应答,此时客户端进入 TIME-WAIT 状态。该状态会持续 2MSL(60s 最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有服务端的重发请求的话,就进入 CLOSED 状态。当服务端收到确认应答后,也便进入 CLOSED 状态

六、HTTP 缓存策略

1. 强缓存 (不发请求)

  • Expires (HTTP/1.0)
    1. 服务器返回一个具体的绝对时间
  • Cache-Control (HTTP/1.1)
    1. 使用相对时间
    2. max-age=3600:代表从接收到资源开始,1小时内有效
    3. 优先级高于 Expires
    4. no-store:不缓存任何内容
    5. no-cache:可以缓存,但每次使用前必须去服务器验证(进入协商缓存流程)
    6. public / private:决定是否允许中间代理(如 CDN)缓存

2. 协商缓存 (发请求询问)

当强缓存失效(过期)后,浏览器会拿着一个“凭证”去问服务器:“我手里的东西还能用吗?”

  • 如果没变,服务器返回 304 Not Modified(没有响应体,极快)
  • 如果变了,服务器返回 200 OK 和最新的资源
    • Etag / If-None-Match: 基于内容 Hash,最精确
    • Last-Modified / If-Modified-Since: 基于最后修改时间,秒级精度

七、HTTP 报文结构

HTTP 报文是前后端交互的载体。无论是请求还是响应,它们都遵循相似的四段式结构

1. HTTP 请求报文 (Request)

  • 请求行:告诉服务器“干什么、去哪干、按什么规矩干”(如 POST /login HTTP/1.1
  • 请求头:补充信息。如 Host(目标域名)、User-Agent(什么浏览器)、Cookie(身份凭证)
  • 空行:法定的分隔符,告诉服务器“头结束了,下面是正文”
  • 请求体:具体的负载数据(如登录时的用户名密码)

2. HTTP 响应报文 (Response)

  • 状态行:告诉客户端“结果如何”(如 HTTP/1.1 200 OK
  • 响应头:服务器信息。如 Content-Type(数据类型)、Set-Cookie(种下凭证)
  • 空行:分隔符
  • 响应体:服务器回传的实际内容(HTML、图片、JSON 等)

七、URL 的解构

URL(统一资源定位符)就像是一个坐标,指引浏览器找到互联网上的特定资源

http://www.example.com:80/news/index.html?id=10#top 为例:

  1. 协议 (http://):通信的语言
  2. 域名 (www.example.com):服务器的名字
  3. 端口 (:80):服务器的“房号”。HTTP 默认 80,HTTPS 默认 443
  4. 路径 (/news/index.html):资源在服务器上的物理或逻辑位置
  5. 查询参数 (?id=10):传递给服务器的额外指令
  6. 锚点 (#top):页面内的“书签”,不会发送给服务器,仅由浏览器跳转位置

八、HTTP 协议的优缺点

优点

  • 简单灵活:报文清晰易懂,且能传输任何类型的数据(图片、视频、文本)
  • 无连接:处理完即断开,节省服务器维持连接的资源(注:HTTP/1.1 后通过 Keep-Alive 优化)
  • 无状态:服务器不记得你是谁,处理速度快,适合大规模并发

缺点

  • 无状态(双刃剑):需要借助 Cookie/Session 才能实现登录状态保持
  • 明文传输:数据在网络中“裸奔”,极易被窃听(Wireshark 抓包可见)
  • 不安全:不验证对方身份(可能连到伪造网站),不验证内容完整性(数据可能被篡改)

九、OSI 七层模型

  1. 应用层 (Application):直接为用户提供网络服务(HTTP, FTP, SMTP, DNS)

  2. 表示层 (Presentation):负责数据格式化、加密解密、压缩解压(如 Base64 编解码、JSON 转化)

  3. 会话层 (Session):负责建立、管理和终止应用程序间的会话连接

  4. 传输层 (Transport):解决数据怎么发的问题(TCP 可靠传输、UDP 尽力而为),关注的是端口

  5. 网络层 (Network):负责 IP 寻址和路由选择,决定数据包走哪条路

  6. 数据链路层 (Data Link):将比特流封装成,通过 MAC 地址在物理媒介上进行差错检测

  7. 物理层 (Physical):传输 0 和 1 的电信号,涉及网线、光纤、集线器等硬件

十、TCP/IP五层协议

  1. 应用层:整合了 OSI 的上三层(应用、表示、会话)
  2. 传输层:核心协议是 TCP(面向连接,稳)和 UDP(无连接,快)
  3. 网络层:核心协议是 IP
  4. 数据链路层:主要负责物理寻址(ARP 协议在此工作)
  5. 物理层:最底层的物理介质

十一、TCP 与 UDP

1. UDP (User Datagram Protocol) —— 用户数据报协议

  1. 特点解析
  • 无连接:像寄平信,不需要预先建立连接,想发就发
  • 面向报文:不拆分、不合并,保留应用层交下来的报文边界。应用层给多大,UDP 就发多大
  • 不可靠但实时:没有确认机制,没有重传。即使网络拥塞,它也按恒定速率发送。这使得它在视频会议、在线游戏等对延迟敏感的场景中表现卓越
  • 开销极小:头部仅 8 字节,包含源端口、目的端口、长度和校验和

2. TCP (Transmission Control Protocol) —— 传输控制协议

  1. 特点解析
  • 面向连接:发送数据前必须进行“三次握手”,确保双方都准备好了
  • 可靠传输
    • 序列号与确认应答 (ACK):给每个包编号,收到后回传确认
    • 超时重传:没收到确认就重发
  • 流量控制与拥塞控制:通过“滑动窗口”调整发送速度,防止把网络或接收方“压垮”
  • 面向字节流:数据像水流一样传输,没有明确的边界
  • 全双工:双方可以同时收发数据

3. 深度对比:TCP vs UDP

特性TCP (传输控制协议)UDP (用户数据报协议)
连接性面向连接(需三次握手)无连接(直接发送)
可靠性可靠(丢包重传、错误校验)不可靠(发完不管,可能丢包)
顺序性有序(按发送顺序排列)无序(先发未必先到)
传输效率较慢(首部大 20 字节,有确认机制)极快(首部小 8 字节,无握手)
通信方式点对点(1对1)支持一对一、一对多、多对多(广播)
流量/拥塞控制有(网络堵塞时会自动减速)无(一直按最高速发)

4. 应用场景的选择

  1. 什么时候选 TCP?
  • 对数据准确性要求 100% 的场景
  • 例如:浏览器网页 (HTTP/HTTPS)文件传输 (FTP)邮件 (SMTP)远程登录 (SSH)。在这些场景中,丢一个字节都可能导致文件损坏或登录失败
  1. 什么时候选 UDP?
  • 对实时性要求高,能容忍少量丢包的场景
  • 例如:视频直播/会议(卡一下能接受,重发旧帧没意义)、语音通话在线竞技游戏(位置同步需要极低延迟)、DNS 查询(请sh求小,UDP 更快)

十二、 三次握手与四次挥手

1. 三次握手:同步与确认

三次握手是为了解决“网络延迟导致旧连接重连”和“同步初始化序列号(ISN)”的问题

流程拆解

  1. 第一次握手 (SYN=1, seq=x):客户端发送连接请求。意义:证明客户端有发送能力
  2. 第二次握手 (SYN=1, ACK=1, seq=y, ack=x+1):服务端收到并同意连接,发回确认。意义:证明服务端有接收能力和发送能力
  3. 第三次握手 (ACK=1, seq=x+1, ack=y+1):客户端再次确认。意义:证明客户端有接收能力,且双方序列号已同步

为什么两次不行?

  • 防止失效的连接请求突然传送到服务端:如你所说,网络拥堵可能导致旧的请求在连接释放后才到达。如果没有第三次握手,服务端一发回确认连接就建立了,会导致服务端一直等待一个早已不存在的客户端,白白浪费资源

2. 四次挥手

TCP 是全双工的,这意味着客户端和服务器都能同时收发数据。断开时,每一方都要单独关闭自己的发送通道

流程拆解

  1. 第一次挥手 (FIN=1, seq=u):客户端告诉服务端:“我没数据要发了。”(客户端进入 FIN_WAIT1
  2. 第二次挥手 (ACK=1, ack=u+1, seq=v):服务端回复:“收到,但我可能还有数据没发完,你等我一下。”(此时处于半关闭状态,服务端进入 CLOSE_WAIT
  3. 第三次挥手 (FIN=1, ACK=1, ack=u+1, seq=w):服务端发完了,告诉客户端:“好了,我也可以关了。”(服务端进入 LAST_ACK
  4. 第四次挥手 (ACK=1, ack=w+1, seq=u+1):客户端回复:“收到,拜拜。”(客户端进入 TIME_WAIT

为什么需要四次?

  • 异步性:当服务端收到 FIN 时,它可能还有数据在缓冲区没发完。它只能先回一个 ACK 告知已收到,等自己处理完了再发 FIN

十三、WebSocket

1. 深度理解 WebSocket

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议

WebSocket原理

  • 客户端向 WebSocket 服务器通知(notify)一个带有所有接收者ID(recipients IDs)的事件(event),服务器接收后立即通知所有活跃的(active)客户端,只有ID在接收者ID序列中的客户端才会处理这个事件

2. 工作原理:握手过程

WebSocket 的建立需要经过一个“握手”阶段,它利用了 HTTP 协议来完成升级

  1. 客户端发起请求:发送一个带有 Upgrade: websocket 头的 HTTP 请求
  2. 服务器响应:如果支持,返回 101 Switching Protocols 状态码
  3. 协议切换:此时 HTTP 连接正式升级为 WebSocket 连接,双方开始自由交谈

核心特点

  • 全双工(双向通信):服务器可以主动发消息给客户端,客户端也可以随时发给服务器
  • 实时性强:省去了 HTTP 的握手和繁琐的 Header,数据包极小(头部仅 2~10 字节)
  • 长连接:连接建立后除非主动关闭或网络断开,否则一直存在
  • 跨域支持:WebSocket 天生支持跨域,不需要像 HTTP 那样配置繁琐的 CORS

缺点

  • 需要额外的开销: WebSocket需要在服务器上维护长时间的连接,这需要额外的开销,包括内存和CPU。在高并发场景下(如十万级用户同时在线),服务器的内存会被大量活着的连接耗尽
  • 安全问题: 由于WebSocket允许服务器主动向客户端发送数据,可能会存在安全问题。服务器必须保证只向合法的客户端发送数据

websocket怎么实现重连

要实现坚固的重连机制,通常需要结合 心跳检测指数退避算法

一个重连方案包含以下三个关键环节:

  1. 心跳检测 (Heartbeat):主动探测连接是否“假死”
  2. 延迟重连 (Delay Retry):避免断开后立即重连造成的“惊群效应”
  3. 重连尝试限制:避免无限循环浪费资源

3. 即时通讯方案比较

技术机制优点缺点
短轮询 (Polling)客户端定时(如每 5s)发 HTTP 请求兼容性极好,实现简单大量无效请求,浪费带宽和 CPU
长轮询 (Long Polling)服务器收到请求后“挂起”,有数据才返回比短轮询节省资源服务器连接依然被占用,体验有延迟
SSE (Server-Sent Events)基于 HTTP,服务器持续发送“流”数据实现简单,自动重连,支持轻量推单向(仅服务器到客户端),IE 不支持
WebSocket独立协议,全双工持久连接全双工,性能最优,延迟最低实现相对复杂,需考虑心跳检测

与SSE区别

SSE 是一种轻量级、易实现的实时通信方案,尤其适用于大模型流式输出(如 ChatGPT 的逐字生成)、实时通知等场景

特性WebSocketSSE
通信方向双向 (Full-Duplex)单向 (Server to Client)
协议自定义二进制协议 (ws://)标准 HTTP (http://)
重连机制需要手动写代码实现浏览器内置自动重连
适用场景游戏、实时聊天ChatGPT 响应、监控大屏、通知推送
二进制数据仅文本(可编码后传输)原生支持二进制

与HTTP 区别

特性HTTP (1.1/2)WebSocket
通信方式单向(半双工)双向(全双工)
发起方只能由客户端发起请求双方均可主动发送数据
连接状态无状态(每次请求需带 Header)有状态(建立后连接一直保持)
开销大(每次请求都有冗长 Header)极小(建立后头部仅 2~10 字节)
实时性低(依赖轮询频率)极高(服务器实时推送)
URL 协议头http:// 或 https://ws:// 或 wss://

4. WebSocket 实战代码片段

客户端 (浏览器端)

javascript
const socket = new WebSocket('ws://chat.example.com');

// 连接成功
socket.onopen = () => socket.send('Hello Server!');

// 接收消息
socket.onmessage = (event) => console.log('收到:', event.data);

// 关闭连接
socket.onclose = () => console.log('连接已关闭');

十四、DNS协议

DNS (Domain Name System,域名系统)

核心任务:将域名解析为IP地址,客户端向DNS服务器(DNS服务器有自己的IP地址)发送域名查询请求,DNS服务器告知客户机Web服务器的 IP 地址

DNS 是一个分布式、层级化的数据库系统:

  • 根域名服务器 (Root DNS):最高层级,知道所有顶级域名(.com, .cn, .org)的去向
  • 顶级域名服务器 (TLD DNS):负责管理特定的后缀,比如所有 .com 结尾的域名都在这里登记
  • 权威域名服务器 (Authoritative DNS):真正保存域名与 IP 对应关系的地方。比如腾讯云或阿里云的 DNS 服务器

DNS 查询

当你输入网址时,会经历两类查询:

  1. 递归查询:你的电脑(客户端)发请求给 本地 DNS 服务器(通常是运营商提供的)

  2. 迭代查询:本地 DNS 如果没缓存,就会去问各个层级的服务器

  • 问根 -> 问 TLD -> 问权威

DNS 的传输层:UDP 还是 TCP?

在域名解析的时候使用UDP协议

  • 原因:DNS 查询包通常很小(小于 512 字节),UDP 不需要握手,速度极快
  • 容错:如果 UDP 丢包了,DNS 客户端会超时重传

特殊情况使用 TCP(端口 53)

  • 区域传输:主从 DNS 服务器之间同步大量数据时
  • 响应超长:如果返回的响应包超过了 512 字节(比如带有大量 IPv6 记录),会切换到 TCP 以保证可靠传输

DNS 缓存机制

  1. 浏览器缓存:Chrome 会缓存 DNS 记录一段时间
  2. 操作系统缓存:读取本地的 hosts 文件
  3. 本地 DNS 服务器缓存:这就是为什么有时候改了域名解析,要等一会儿才能生效(TTL 还没过期)