<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>网络 on 安橙的博客</title><link>https://blog.ans20xx.com/tags/%E7%BD%91%E7%BB%9C/</link><description>Recent content in 网络 on 安橙的博客</description><generator>Hugo -- 0.161.1</generator><language>zh</language><lastBuildDate>Wed, 18 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.ans20xx.com/tags/%E7%BD%91%E7%BB%9C/index.xml" rel="self" type="application/rss+xml"/><item><title>SSE 原理</title><link>https://blog.ans20xx.com/posts/architecture/sse-%E5%8E%9F%E7%90%86/</link><pubDate>Wed, 18 Feb 2026 00:00:00 +0000</pubDate><guid>https://blog.ans20xx.com/posts/architecture/sse-%E5%8E%9F%E7%90%86/</guid><description>&lt;h1 id="1-学习主题"&gt;1. 学习主题&lt;/h1&gt;
&lt;p&gt;我要学习的内容：
SSE 原理&lt;/p&gt;
&lt;p&gt;我为什么要学它：
（写清楚用途、场景、目标，比如面试、项目、论文、考试）&lt;/p&gt;</description></item><item><title>计算机网络</title><link>https://blog.ans20xx.com/posts/infra/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E5%AD%A6%E4%B9%A0/</link><pubDate>Mon, 16 Feb 2026 00:00:00 +0000</pubDate><guid>https://blog.ans20xx.com/posts/infra/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E5%AD%A6%E4%B9%A0/</guid><description>&lt;h1 id="网络分层--端到端路径"&gt;网络分层 + 端到端路径&lt;/h1&gt;
&lt;div
class="mindmap-container"
id="mindmap-16284357"
style="width:100%; height:860px; min-height: 860px;"
&gt;&lt;/div&gt;
&lt;textarea id="mindmap-data-16284357" style="display:none;"&gt;
- 网络分层 &amp;#43; 端到端路径
- 分层模型
- 链路层 (LINK)
- 负责：同一链路/局域网内把 IP 包送到下一跳
- 典型概念：以太网、WIFI、ARP、MAC、MTU
- 网络层 (IP)
- 负责：跨网络把包从源 IP 路由到目的 IP
- 典型概念：IP 地址、路由表、NAT、ICMP、分片
- 传输层 (Transport)
- 负责：端到端进程通信，提供端口与可靠性
- 应用层 (Application)
- 负责：定义应用语义
- 端到端路径（一次 HTTPS URL 发生了什么）
- URL 解析与策略决策（应用层前置）
- 浏览器先拆 URL：
- schema：https -&amp;gt; 需要 TLS
- host：example.com -&amp;gt; 需要 DNS
- port：默认 443
- path：/index.html
- 是否可用缓存
- 是否复用已有连接
- DNS 解析：把域名变成 IP
- 目标：得到服务器的 IP (A=IPv4/AAAA=IPv6)
- 典型流程
- 浏览器/OS 先查本地缓存
- 没命中 -&amp;gt; 向递归解析器发起查询
- 递归解析器询问：根 -&amp;gt; TLD -&amp;gt; 权威 DNS
- 返回 IP &amp;#43; TTL
- TTL 决定缓存时长
- 同一域名可能返回多个 IP：简单的负载均衡，但是不可控
- TCP 连接（传输层）
- 目标：建立一条到服务器IP:443的 TCP 连接
- 典型流程
- 客户端选一个临时端口作为源端口
- 形成 socket 四元组
- 三次握手完成后，连接进入 ESTABLISHED
- 连接的唯一标识符是四元组
- NAT 环境下：srcIP 可能是私网 IP，但是公网会被 NAT 改写
- RTT 大时，建连成本高：三次握手至少消耗 1 个 RTT
- NAT：内网 IP 也能访问公网（网络层/链路层交叉）
- 大多数客户端在 NAT
- 内网 192.168.x.x:ramdomPort
- 出口 NAT 把它映射成：公网 IP:另一个 Port
- NAT 设备维护一张映射表（内网四元组&amp;lt;-&amp;gt;公网四元组）
- 映射有超时：长时间无数据可能被回收
- 并发连接太多可能端口耗尽
- TLS 握手：在 TCP 上建立安全通道
- 目标
- 验证服务器身份
- 协商密钥
- 后续数据用对称加密 &amp;#43; 完整性保护
- TLS 发生在 TCP 建立之后、HTTP 之前
- 证书用于“证明对方是它声称的域名“
- 发送 HTTP 请求并接受响应
- HTTP 内容
- 请求行：GET /index.html
- 头：Host、User-Agent、Accept、Cookie
- 体：GET 通常无，POST 常见
- 服务器返回
- 状态码：200/301/404/500
- 头：Content-Type、Content-Length、Set-Cookie
- 体：HTML/JSON/图片等
- 连接复用与关闭：不是每次都重新握手
- HTTP/1.1 默认倾向长连接（Keep-Alive）
- 浏览器有连接池，会复用到同一个 host:port 的连接
- 关键概念锚点
- RTT：网络交互的时间单位
- RTT = 一个来回的延迟
- 建连/TLS/重传都依赖 RTT
- 高 RTT 下，交互次数越多越慢
- 吞吐与 BDP(带宽-时延积)
- MTU 月 MSS
- MTU：链路层最大承载
- MSS：TCP 单段可承载的应用数据最大值
- 包太大可能被分片或者丢弃
- 合理 MSS 能减少分片风险，提升稳定性
&lt;/textarea&gt;
&lt;h1 id="tcp-精讲"&gt;TCP 精讲&lt;/h1&gt;
&lt;div
class="mindmap-container"
id="mindmap-52714386"
style="width:100%; height:860px; min-height: 860px;"
&gt;&lt;/div&gt;
&lt;textarea id="mindmap-data-52714386" style="display:none;"&gt;
- TCP 精讲
- TCP 本质：在不可靠 IP 上提供可靠字节流
- TCP 提供内容
- 面向连接：双方都维护连接状态（序号、窗口、定时器等）
- 可靠、有序：丢包重传、乱序重排、去重
- 字节流：没有消息边界（粘包/拆包的根源）
- 流量控制：避免把对方接收缓冲打爆（rwnd），端到端
- 拥塞控制：避免把网络打爆，端到网络
- 报文段关键字段
- Sequence Number：本段数据在字节流里的起点序号
- Acknowledgment Number：我期望收到的下一个收到的序号
- Flags：SYN/ACK/FIN/RST/PSH/URG
- Window（rwnd）：接收端通告窗口
- Options：MSS，Window Scale
- 连接建立：三次握手
- 标准流程
- C-&amp;gt;S: SYN（seq=x）
- S-&amp;gt;C: SYN&amp;#43;ACK (seq=y,ack=x&amp;#43;1)
- C-&amp;gt;S: ACK (ack=y&amp;#43;1)
- ![](https://an-img.oss-cn-hangzhou.aliyuncs.com/2026/02/17/20260217111458329.png,514,267)
- 为什么必须三次
- 双方都要确认两件事
- 对方能收：对方收到了我的东西
- 对方能发：对方能把东西发回来让我收到
- 两次握手只能证明客户端 -&amp;gt; 服务端这条路通了；但是服务端无法证明服务端-&amp;gt;客户端也通、且客户端确实收到了服务端的回应，第三次 ACK 就是让服务端拿到这个确认（服务端无法确认客户端能收）
- 如果只有两次握手
- 服务端回 SYN &amp;#43; ACK 丢失了
- 服务端仍为连接建立，开始分配连接资源，等待数据
- 客户端实际上没有收到任何回应，会重试或放弃
- 三次握手还能防止历史重复 SYN 造成的“幽灵连接“
- 历史重复 SYN 指的是：某次旧连接尝试时发出的 SYN，由于网络拥塞、路由绕行、链路重传、设备缓存/异常等原因，在很久之后才到达服务器
- 如果服务器把旧 SYN 当新建连：
- 服务器会分配资源
- 如果后续又出现旧 ACK 包，让服务器误以为连接已建立，交付错误的数据
- 幽灵连接：就是服务端自嗨式建立，客户端不认可
- 半连接队列与 SYN Flood
- 服务端收到 SYN 后进入 SYN_RECV，会占用半连接资源（backlog）
- SYN Flood：大量 SYN 不完成握手 —&amp;gt; 半连接队列被占满 -&amp;gt; 正常连接进不来
- 典型缓解：SYN cookies、增大 backlog、限速、丢弃策略、前置抗 DDoS
- 连接关闭：四次挥手、半关闭
- 主动关闭方 A-&amp;gt;B：FIN（不再发了）
- B -&amp;gt; A：ACK （知道了）
- B -&amp;gt; A：FIN （我也不再发了）
- A -&amp;gt; B：ACK （知道了）
- ![](https://an-img.oss-cn-hangzhou.aliyuncs.com/2026/02/17/20260217113908534.png,440,230)
- 为什么常见是四次
- TCP 是全双工：A 不发 != B 不发
- B 可能还有数据要发完，所以 ACK 和 FIN 分开
- 半关闭
- A 发 FIN 表示 A 的发送方向关闭，但仍然可以接受 B 的数据
- 工程上常见于“请求发送完但继续接受响应流“的场景
- RST：不是正常关闭，是异常打断
- RST（Reset）是 TCP 里面非常硬的控制信号：立刻终止连接/拒绝连接
- 不是正常的四次挥手关闭，告诉对方：“这条连接不存在/状态不一致，马上停“
- RST 常见原因
- 端口没监听
- 应用崩溃/强制关闭
- 中间设备丢弃状态后注入 RST
- TIME_WAIT、CLOSE_WAIT
- 主动关闭方在发送最后一个 ACK 后进入 TIME_WAIT，并等待 2MSL。
- 必须 TIME_WAIT
- 保证对方收到最后 ACK：最后 ACK 丢了，对方重发 FIN；TIME_WAIT 还能再次 ACK
- 让旧连接的延迟报文过期：避免旧数据混入新连接
- 为什么是 2MSL
- MSL = 报文在网络中可能存活的最大时间
- 等待 2MSL 是为了覆盖对方 FIN 重传 &amp;#43; 我 ACK 再次发送等往返的不确定性。
- TIME_WAIT 多了怎么办
- 常见场景：短连接高 QPS
- 治理思路
- 优先做连接复用：HTTP Keep-Alive/连接池
- 调整应用行为：减少主动 close、合并请求、复用长连接
- 系统参数：允许端口更快复用等
- 通常是我方主动关 &amp;#43; 短连接
- CLOSE_WAIT 多是什么
- CLOSE_WAIT 表示：对方已经 FIN 了，但是我方应用还没有 close
- 常见原因：应用层忘记关闭连接、连接泄露、线程阻塞导致没有走到 close
- 通常是我方没关
- 可靠传输机制：序号、ACK、重传、SACK
- 序号与累计 ACK
- TCP 把数据看成连续字节流：每个字节都有序号
- ACK 是累计的：ack = N 表示 0..N-1 都收到了，下一步要 N
- 好处：ACK 开销小
- 坏处：遇到乱序/丢包，单靠累计 ACK 不够精细
- 重传触发机制
- 超时重传（RTO）：等不到 ACK 就重发（RTO 动态估计，基于 RTT 抖动）
- TCP 发送一个数据段后，会期待收到 ACK，如果在某个时间窗口没有等到 ACK，TCP 可能认为丢了，于是触发超时重传。
- 等多久的时间阈值就是 RTO（Retransmission Timeout）。
- 触发条件：发送后，计时器到期，仍未收到能确认该段的 ACK
- 行为：重传未确认的数据段
- RTO 动态估计
- 网络 RTT 会变，而且会抖动，RTO 必须跟随着链路实际 RTT 变化
- SRTT &amp;#43; RTTVAR -&amp;gt; RTO
- 名词解释
- RTT sample：一次测得的 RTT（从发出某段到收到它对应 ACK 的时间）
- SRTT (Smoothed RTT)：平滑后的 RTT 均值。
- RTTVAR：RTT 的波动。
- RTO = SRTT &amp;#43; 4 * RTTVAR
- SRTT 给出正常情况下 ACK 来回要多久
- RTTVAR 给出不确定性有多大
- 乘以 4 是给一个安全幅度：抖动越大，RTO 增长越明显，避免误重传
- 指数退避：超时一次，RTO 翻倍
- RTO 重传 vs 快速重传
- RTO 重传
- 触发：计时器到期，没等到 ACK
- 特点：更“保底“，但通常更慢；而且代表网络更糟糕
- 常伴随：指数退避，cwnd 通常会大幅下降
- Fast Retransmit （快速重传）
- 触发：重复 ACK
- 特点：更快，更轻判拥塞
- 一半比 RTO 更温和
- 快速重传（Fast Retransmit）：收到多个重复 ACK （典型 3 个）推断某段丢失了，立即重传）
- RTO 重传局限性
- 必须等待一段时间没收到 ACK 才重传
- 在 RTT 较大或 RTO 比较保守时，恢复会很慢
- 快速重传的思路
- 不等超时，利用接收端反馈的 ACK 形态更早推断丢包
- 重复 ACK
- 如果接收端收到了更后面的段，但是缺了中间某段
- 不能把乱序段交付给应用
- 会继续发送同一个累计 ACK，告诉发送端还在等从 1000 开始的那段，后面来的我先缓存
- ACK 值没前进，但又反复出现的 ACK 就是重复 ACK
- 3 个重复 ACK 会触发快速重传
- 收到 3 个重复 ACK 代表某段大概率丢了
- 立即重传缺口对应的最早未确认段
- 快恢复
- 原因
- 收到快重传代表完了给没有完全堵死（还能持续收到 ACK）
- 不必像 RTO 那样极度保守把发送速率打到很低
- Reno 直觉
- 触发快速重传后，认为发生拥塞 -&amp;gt; 降低 cwnd
- 但利用重复 ACK 的到来，允许发送端在恢复期间适度继续发，避免完全停摆
- 当收到新的 ACK 后，退出快恢复，回到拥塞避免阶段
- SACK（选择确认）
- 痛点：累计 ACK 信息不够
- 当出现丢包 &amp;#43; 乱序到达时，累计 ACK 只能不断重复同一个 ACK=N，发送端只知道缺口在 N，不知道
- 后面哪些段已经到了
- 究竟丢失了几段，丢失了哪几段
- 重传时是否把已到达的也重传
- 目标是把接收端实际收到的乱序块显式告诉发送端
- SACK 是什么：在 ACK 里带已收到的区间块
- SACK 是 TCP 的一个 Option，启用后
- 接收端在 ACK 报文的 TCP Options 中携带若干个 SACK blocks
- 每个 block 描述一个已经收到的连续字节区间
- SACK block 的语义
- SACK block = (Left Edge, Right Edge)
- 表示接收端已经收到：[LeftEdge, RightEdge) 这个区间
- ACK 字段仍然存在，表示最左侧连续已收前缀的下一个期待序号
- 启用流程：SACK Permitted
- SACK 需要在三次握手时协商
- 双方在 SYN/SYN&amp;#43;ACK 中携带 SACK Permitted 选项
- 只要双方都声明支持，后续才会在 ACK 中携带 SACK blocks
- 乱序与重排
- 网络层可能乱序，TCP 负责在接收端按序交付给应用
- 接收端会缓存乱序段，等缺口补齐再交付
- 滑动窗口
- 痛点
- 如果每发一段就必须等 ACK 再发下一段，吞吐会被 RTT 严重限制：链路大部分时间在等回音。
- 滑动窗口允许发送端在未收到 ACK 前，先发出一批数据，让数据在路上飞，从而把链路利用起来。
- 窗口 = 允许在途未确认数据的上限；窗口越大，在高 RTT 链路上容易跑满带宽
- rwnd（receive window，接收窗口，流量控制）
- 由接收端通告（在 TCP 头的 Window 字段里）
- 表示接收端缓冲区还剩多少空间
- 目的：防止发送端把接收端内存撑爆
- cwnd（congestion window，拥塞窗口，拥塞控制）
- 由发送端维护
- 表示发送端认为网络当前能够承受的在途数据量上限
- 目的：防止把网络打爆
- swnd（send window，实际发送窗口）
- 发送端真正允许“在途未确认“的上限
- 近似于 min(rwnd,cwnd)
- 发送端视角：窗口如何限制发送
- 发送端维护两个关键指针
- SND.UNA：最早未确认的序号(UnACKed)
- SND.NXT：下一个准备发送的序号(Next to send)
- 窗口约束可以理解为：
- 允许发送的序号范围：[SND.UNA, SND.UNA &amp;#43; swnd)
- 已发送未确认的范围：[SND.UNA, SND.NXT)
- 还能继续发送的额度：swnd - (SND.NXT - SND.UNA)
- ACK 到来时发生什么
- 收到 ACK，把 SND.UNA 往前推进
- 已确认数据从窗口左边滑出
- 窗口右边腾出了空间，允许继续发送新的数据
- 接收端视角：为什么会出现 dupACK/乱序缓存
- 接收端维护两个关键指针
- RCV.NXT：下一段按序期望的序号
- 接收缓冲：可以暂存乱序到达的段
- 出现乱序
- 接收端会缓存后到的段，但 ACK 仍然回 RCV.NXT（累计 ACK）
- 发送端看到重复 ACK (dupACK)，可能触发快速重传
- 窗口、吞吐、RTT
- 吞吐上限 = 窗口大小/RTT
- RTT=100ms，窗口=64KB，吞吐=64KB/0.1s=640KB/s
- BDP（带宽-时延积），窗口需要=BDP 才能跑满带宽
- 表示一条网络路径在任意时刻在路上飞着的数据量大概有多少，也叫管道容量
- BDP = 带宽 * 往返时延 (RTT)
- 想要把链路跑满，发送端需要让“在途未确认数据“接近 BDP
- 在途未确认数据主要受窗口限制：in_flight &amp;lt;= min(cwnd, rwnd)
- 要跑满带宽，需要窗口大小 &amp;gt;= BDP
- 零窗口与窗口探测
- 如果接收端缓冲满了，会通告 rwnd=0
- 发送端此时必须停止发送新数据，但是要避免死锁
- TCP 有 persist timer：周期性发送 Zero Window Probe 探测包
- 一旦接收窗口恢复，发送端继续发
- 粘包/拆包
- 粘包：在发送端 send() 了两条业务消息，接收端一次 recv() 读到了两条合在一起的字节。
- 拆包：在发送端 send() 了一条业务消息，接收端需要 recv() 多次才能读完
- TCP 不保证 send 一次就对应端 recv 一次
- 原因
- TCP 的抽象是流
- 像读文件一样读一串字节
- send()：把字节追加到发送缓冲区
- recv()：从接收缓冲区取走当前可读的字节
- 分段由 TCP 决定，不由应用决定
- 接收端读取粒度由应用决定
- 解法
- 在应用层定义消息边界
- 长度前缀（Length-Prefixed，最通用）
- 格式 | 4-byte length (big-endian) | payload bytes... |
- length 表示 payload 长度
- 接收端先读满 4 字节得到 length，再继续读满 length 字节
- 分隔符（Delimiter-Based，适合文本协议）
- 行协议：以 \r\n 结尾
- 固定长度（Fixed-Size）
- 每条消息固定 N 字节
- 拥塞控制
- 拥塞不是对端瘦不下，那是流量控制 rwnd，拥塞是网络路径上的队列/链路承载不住
- 路由器/交换机队列堆积 -&amp;gt; RTT
- 队列溢出 -&amp;gt; 丢包
- 丢包/排队抖动 -&amp;gt; 吞吐下降、延迟暴涨
- 拥塞控制控制的是发送端允许在网络中飞着的未确认数量，cwnd
- Reno 的两个核心状态变量
- cwnd：拥塞窗口（发送端认为网络现在能承受的在途数据量）
- ssthresh：慢启动阈值，决定从指数增长到线性增长的分界点
- 四个阶段
- 慢启动
- 目的：刚开始不知道网络能承受多少，先快速试探
- 规则：
- 初始 cwnd 为一个较小值，历史是 1MSS
- 每收到一个 ACK，cwnd 增加 1MSS
- 因为一个 RTT 内会收到大约 cwnd/MSS 个 ACK，所以每个 RTT cwnd 近似翻倍
- 每 RTT 把在路上的包数翻倍，迅速逼近瓶颈带宽
- 太快可能把队列灌满，引发丢包
- 拥塞避免
- 当 cwnd 到达或超过 ssthresh，从慢启动切换到拥塞避免
- 每 RTT 让 cwnd 大约增加 1 MSS，每个 ACK 增加 MSS*MSS/cwnd
- 大多数时间连接处于的阶段
- 快重传：用 dupACK 提前判断丢包，不等 RTO
- 触发条件
- 收到 3 个重复 ACK dupACK
- ACK 号不前进，连续出现多次
- 快恢复：丢包后减速但不中断，比 RTO 温和
- 发生快重传后的关键动作
- 设定新的值
- ssthresh = cwnd/2
- cwnd 不回到很小，而是进入快恢复逻辑
- 当收到能够推进 ACK 的新 ACK，退出快恢复，进入拥塞避免
- RTO vs dupACK
- RTO：最严重，认为网络可能很糟
- ssthresh = cwnd / 2
- cwnd 下降到很小，经典是 1MSS
- 回到慢启动（重新探测）
- RTO 通常会指数退避，导致恢复更慢
&lt;/textarea&gt;
&lt;h1 id="http-与-web-体系"&gt;HTTP 与 Web 体系&lt;/h1&gt;
&lt;div
class="mindmap-container"
id="mindmap-87451632"
style="width:100%; height:860px; min-height: 860px;"
&gt;&lt;/div&gt;
&lt;textarea id="mindmap-data-87451632" style="display:none;"&gt;
- HTTP 与 Web 体系
- HTTP 基础语义
- HTTP 是无状态应用层协议：每个请求都自包含信息，状态由 Cookie/Token/Session 等机制在应用层实现
- HTTP 定义的语义，具体传输方式由 HTTP/1.1、HTTP/2、HTTP/3 决定
- 方法：语义 &amp;#43; 幂等 &amp;#43; 安全性
- GET：获取资源，应当安全&amp;#43;幂等
- HEAD：只要响应头，不要响应体，用作探测/缓存探测
- POST：提交数据，创建子资源或触发动作，通常非幂等
- PUT：整体替换/创建指定资源，通常幂等
- PATCH：部分更新，是否幂等取决于语义设计
- DELETE：删除资源，通常幂等
- OPTIONS：探测服务器能力（常用于 CORS 预检）
- 状态码
- 1xx：信息（少见）
- 2xx：成功
- 200 OK
- 201 Created 创建成功
- 204 No Content 成功但无响应体
- 3xx：重定向
- 301 永久
- 302 临时(历史语义混乱)
- 303 让客户端用 GET 拿
- 307/308 保持方法不变
- 4xx：客户端错误
- 400 参数/格式问题
- 401 需要认证
- 403 拒绝
- 404 不存在
- 409 冲突
- 429 限流
- 5xx：服务器错误
- 500、502 上游坏/网关问题
- 503 不可用
- 504 上游超时
- Header
- 通用与内容相关
- Content-Type：实体类型（json/html...）
- Content-Length：长度（HTTP/1.1 重要）
- Content-Encoding：gzip/br 等压缩
- Accept/Accept-Encoding/Accept-Language：内容协商
- Host：HTTP/1.1 必须（虚拟主机）
- Connect：连接管理（HTTP/2 中不再使用）
- 会话与安全
- Cookie/Set-Cookie
- Authorization (Bearer/Basic 等)
- Origin/Refer：CORS/CSRF 相关
- Strict-Transport-Security：强制 HTTPS
- Content-Security-Policy(CSP)：前端安全策略
- 缓存相关
- Cahce-Control
- Expires
- ETag/If-None-Match
- Last-Modified/If-Modified-Since
- Vary
- Age （代理缓存的年龄）
- Pragma：no-cache （历史兼容）
- HTTP 缓存
- 两类缓存：强缓存vs协商缓存
- 强缓存
- 命中强缓存时浏览器直接用本地缓存，不走网络
- 典型控制
- Cache-Control: max-age=
- Expires：老机制
- 协商缓存（发请求但可能不下载）
- 浏览器发请求带校验文件，服务器判断资源是否变化
- ETag 流程
- 响应：ETag: &amp;#34;xxx&amp;#34;
- 下次请求：If-None-Match: &amp;#34;xxx&amp;#34;
- 若未变：返回 304 Not Modified
- Last-Modified 流程
- 响应：Last-Modified: ...
- 下次请求：If-Modified-Since：...
- 未变：304
- Cache-Control 关键指令
- max-age=N：资源在 N 秒内视为新鲜（强缓存）
- no-store：绝对不缓存
- no-cache：可以缓存，但每次使用前必须去服务器验证
- must-revalidate：过期后必须验证，不能用陈旧副本
- public：允许被共享缓存（CDN/代理）缓存
- private：只允许浏览器私有缓存，不允许共享缓存缓存
- s-maxage=N：给共享缓存的 max-age
- Vary 存储维度的分桶键
- Vary 告诉缓存，同一个 URL 的响应会因为某些请求头不同而不同
- Vary：Accept-Encoding，gzip/br 不同版本要分开缓存
- Vary：Origin：CORS 常见
- Vary 过多会让缓存碎片化，命中率下降
- ETag 的强弱、代理与一致性
- 强 ETag：字节级一致才算命中
- 若 ETag (W/)：语义上等价即可
- HTTP/1.1：连接、报文、队头阻塞
- HTTP/1.1 报文与传输
- 文本协议：请求行 &amp;#43; 头 &amp;#43; 空行 &amp;#43; body
- 连接默认与持久化：Keep-Alive （减少握手成本）
- Chunked Transfer-Encoding：服务端可流式传输，不提前知道 Content-Length
- HTTP/1.1 的性能问题：应用层 HOL
- 同一连接上请求/响应按顺序进行
- 一个慢请求会阻塞后续的请求（队头阻塞）
- HTTP/2：二进制分帧与多路复用
- HTTP/2 为什么快
- 二进制分帧：把大消息拆成帧
- 多路复用：多个 stream 在同一 TCP 连接上并发交错传输
- 头部压缩：HPACK（减少重复头部开销）
- HTTP/2 性能问题：TCP 层 HOL(队头阻塞)
- TCP 一旦丢包，需要重传并按序交付
- 丢的那段之前的洞补不上，后续数据即使到了也不能交给上层
- 结果：一个丢包会让同连接上所有 stream 都受影响
- HTTP/3/QUIC
- 核心变化
- HTTP/3 跑在 QUIC 上，QUIC 基于 UDP
- QUIC 自己实现可靠传输与拥塞控制
- 按 stream 提供独立的有序交付，一个 stream 丢包不影响其他 stream 的交付
- TLS 与 HTTPS
- 位置与成本
- HTTPS = TCP 建连后再 TLS 握手，再 HTTP
- 首次访问慢常见原因：DNS &amp;#43; TCP &amp;#43; TLS 多次 RTT
- 解决的问题
- 身份认证：验证连接的是域名的真实服务器
- 机密性：传输内容加密
- 完整性：防篡改
- TLS 握手
- TLS 1.2
- ClientHello：客户端支持的版本/套件，随机数，SNI 等
- ServerHello：选定版本/套件、随机数，让双方对本次会话参数单程一致
- Certificate：服务器发送证书链，客户端据此验证：链是否可信、域名是否匹配、是否过期，用途是否正确
- ServerKeyExchange：服务器提供 ECDHE 参数与公钥，客户端通过验证签名，确保密钥协商参数的安全性
- ServerHelloDone：告诉客户端，材料已经发完
- ClientKeyExchange：客户端协商参数，客户端发送自己的 ECDHE 公钥，双方据此计算共享 secret
- ChangeCipherSpec &amp;#43; Finished：双方切换到加密通信并校验握手完整性
- Web 会话：Cookie/Session/Token
- Web 会话解决的问题
- 认证：你是谁
- 授权：你能做什么
- 会话保持：登录态怎么持续、怎么过期、怎么注销
- 安全边界：防窃取、防伪造、防重放、防跨站
- Cookie：浏览器自动携带的会话容器
- Cookie 是浏览器保存的一组 key=value，由服务器通过响应头 Set-Cookie 下发。
- 后续请求中，浏览器会按照规则自动带上 Cookie 头，无需 JS 参与
- Cookie 关键属性
- Domain/Path：决定发送范围
- Domain=example.con：子域也可能携带
- 不设置 Domain：仅当前 host
- Path=/api：只对当前路径生效
- Expires/Max-age：决定生命周期
- Max-Age=0：立即删除
- Session Cookie：不设过期时间，随浏览器进程结束而清理
- Secure：只在 HTTPS 发送
- HttpOnly：禁止 JS 读取
- 有 HttpOnly 的 cookie，JS 读取不到
- 不能防止 CSRF
- SameSite：控制跨站请求是否携带
- Strict：几乎不跨站携带
- Lax：默认常用
- None：允许跨站携带，必须同时设置 Secure
- Session：服务端保存状态，客户端只存门票
- Session 的典型模式
- 服务端维护 session_id -&amp;gt; session_data
- 客户端用 Cookie 存 session_id
- 每次请求：浏览器自动带 cookie -&amp;gt; 服务端查 session store -&amp;gt; 识别用户
- Token（尤其是 JWT）：把身份证明带在请求里
- Token 的核心模式
- 服务端签发 token 给客户端
- 客户端后续请求带 token
- 服务端验证 token 来识别用户
- JWT 结构
- JWT=header.payload.signature
- header：算法等元信息
- payload：claims 声明
- signature：服务端用密钥签名
- Refresh Token 与 Access Token
- Access Token：短有效期，每次用于请求
- Refresh Token：长有效期，用于换取新的 Access Token
- 安全边界：XSS、CSRF、会话固定、重放
- XSS（跨站脚本）
- 若 token/cookie 可以被 JS 读取，xss 可以直接窃取并盗用
- cookie 用 HttpOnly &amp;#43; Secure
- CSP 减少脚本注入
- 输入输出编码 &amp;#43; 模板转义
- CSRF 跨站请求伪造
- CSRF 利用浏览器自动携带 cookie
- 攻击者诱导用户在登录态下访问恶意页面，发起跨站请求到受害站点
- 防护手段
- SameSite Cookie （优先）
- CSRF Token（表单/请求头携带，服务端校验）
- 检查 Origin/Rerfer
- 同源策略与 CORS
- 痛点
- 浏览器安全模型默认假设：不同站点之间互不信任
- 浏览器用同源策略（Same-Origin Policy，SOP）限制一个网页脚本能读取另一个来源的资源内容
- 业务需要跨域调用 API，有了 CORS（CrossOrigin Resource Sharing）：在 SOP 的基础上提供一个受控的放行机制。
- Orgin 源是什么：同源的三元组
- Origin = scheme &amp;#43; host &amp;#43; port
- https://example.com:443
- 同源策略具体限制
- 跨源读被禁止
- JS 用 fetch 请求 https://xxx.com，请求可能能发出去，但是浏览器会阻止 JS 读取响应，除非响应满足 CORS 规则
- 跨源写/发送很多情况下是允许的
- &amp;lt;form action=&amp;#34;xxx.com&amp;#34; method=&amp;#34;POST&amp;#34;&amp;gt; 可以提交，因此 CSRF 能成立，请求可以发出去，但是页面读取不到 bank.com 的响应内容
- 部分资源加载天然跨源允许
- &amp;lt;img&amp;gt; &amp;lt;scirpt&amp;gt; &amp;lt;link&amp;gt; 浏览器允许加载这些资源
- CORS 本质：服务器声明允许，浏览器执行拦截
- 浏览器在请求带上 Origin
- 服务器在响应返回 Access-Control-* 头
- 浏览器据此决定：是否把响应暴露给 JS
- CORS 两种请求路径：简单请求 vs 预检请求
- 简单请求
- 方法是 GET/HEAD/POST
- Content-Type 只能是三种之一
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- 请求头只能是 CORS-safelistedhead，不能随意加自定义头
- 预检请求
- 不满足简单请求条件，浏览器会先发送一个 OPTIONS 请求，询问服务器是否允许
- 预检请求携带关键头
- Origin: https://a.com
- Access-Control-Request-Method：PUT
- Access-Control-Request-Headers：x-token（将要携带的自定义头列表）
- 服务器如果允许，需要在 OPTIONS 响应返回
- Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Max-Age（预检缓存多久）
- 通过后，浏览器才会发真实请求
- CORS 响应头：每个头怎么用
- Access-Control-Allow-Origin
- 指定允许的 Origin
- 可以是精确 Origin 或者 * （允许任意源），如果要带 Cookie/凭证，不能用 *
- Access-Control-Allow-Methods
- 允许的方法列表：GET/POST
- 主要用于预检响应
- Access-Control-Allow-Headers
- 允许的自定义请求头列表
- 必须覆盖预检中 Access-Control-Request-Headers 请求到的那些头
- Access-Control-Allow-Credentials
- true 表示允许携带凭证，例如 Cookie
- 配合前端请求 credentials: &amp;#39;include&amp;#39;
- Access-Control-Expose-Headers
- 默认情况下，JS 能够读取的响应头很有限，如果希望暴露，必须显式添加
- Vary: Origin
- 按 Origin 分桶缓存
- DNS 解析
- 基础对象
- 记录类型
- A(IPv4)
- AAAA(IPv6)
- CNAME(别名)
- NS(权威)
- 解析角色
- Stub resolver（客户端/OS）
- Recursive resolver（递归解析器：运营商/公司 DNS/公共 DNS）
- Authoritative server （权威 DNS）
- 正向代理、反向代理、透明代理与隧道
- 代理：本质上是位于客户端与服务端之间的一种中间节点，代表一侧发起连接、转发数据、并可能施加策略
- 承担职责
- 路由/转发：把请求送到正确上游
- 安全控制：鉴权、WAF、访问控制
- 性能优化：连接复用、压缩、缓存、限流
- 可观测性：日志、指标、追踪、采样
- 协议转换：HTTP &amp;lt;-&amp;gt; grpc 等
- 正向代理
- 正向代理站在客户端一侧，客户端明确知道自己在用代理，由代理代表客户端访问外部资源
- 反向代理
- 反向代理站在服务端一侧，对外它像真正的服务器入口，对内把请求转发到后端服务
- 反向代理常用原因
- 隐藏后端拓扑：外部只有一个入口
- 统一 TLS 终止：证书集中管理
- 统一流量治理：限流、熔断、灰度、路由、鉴权
- 连接复用：对外维持大量连接、对内复用少量连接
- 观测与审计：同一日志/指标/链路追踪
- 透明代理
- 隧道：Connect 到底干了什么
- 隧道：代理不解析上层协议，只做字节透传。
- HTTP Connect 隧道流程
- 客户端先对代理发 CONNECT
- 客户端 -&amp;gt; 代理
- CONNECT bank.com:443 HTTP/1.1
- Host: back.com:443
- 代理建立到目标的 TCP 连接
- 代理 -&amp;gt; bank.com:443：发起 TCP 连接
- 代理回客户端
- HTTP/1.1 200 Connect Established
- 隧道建立，字节透传
- 客户端与 bank.com 的 TLS 握手数据会被原封不动地通过代理转发，代理看不懂也不需要看懂
- TLS 会话在客户端&amp;lt;-&amp;gt;目标服务器之间建立
- 负载均衡：L4 vs L7、算法、会话保持、健康检查
- 目标
- 扩展性：把流量分散到多台实例，提高吞吐
- 高可用：实例故障自动摘除，流量不中断或快速恢复
- 性能：就近、减少重连、减少排队、提升尾延迟
- 治理：灰度、限流、熔断、路由、可观测
- 边界
- LB 解决的是把请求推送到谁，不解决业务正确性
- LB 层任何自动重试/超时，都可能改变业务语义
- L4 与 L7 的区别
- L4 LB（传输层）：基于 IP/端口/连接做转发
- 优点：性能高，对协议透明
- 缺点：无法基于 URL/Header 做路由
- 常见实现：内核转发、四层 VIP、DSR、NAT 模式等
- 适合长连接：WebSocket、MQ、数据库连接等
- L7 LB（应用层）：理解 HTTP，按照 Host/Path/Header/Cookie 路由
- 常见常见：API Gateway、Ingress、CDN 回源入口
- 负载均衡算法
- Round Robin（轮询）
- 依次分发到每个后端
- 适合：请求耗时相近、后端同质、短连接
- 问题
- 后端性能差异大时不均衡
- 长连接场景下连接一旦分配就会粘住，RR 也会失衡
- Weighted Round Robin
- 按权重分配（机器规格不同，冷热分层）
- 适合：异构机器，逐步扩容
- 问题：权重需要维护；负载时间随时间变化时仍然不准
- Least Connections（最少连接）
- 连接数最少的后端连接
- 适合：长连接、连接数与负载相关的业务
- 问题：
- 连接数不等于负载
- 需要 LB 维护连接计数状态
- Least Request/Least Load（最少请求/最小负载）
- 按当前活跃请求数或综合指标选择
- 适合：请求耗时差异大，尾延迟敏感
- 问题：实现复杂、依赖观测准确性；指标延迟可能导致震荡
- Random/Power of Two Choices（随机/二选一）
- 随机挑两个后端，选最优者
- 优点：简单且实际效果接近最优，分布更稳定，大规模下能显著降低热点概率
- 适合：大规模集群、需要避免中心化状态
- Consistent Hash（一致性 hash）
- 按 key 映射到固定节点
- 适合：
- 需要缓存命中（本地 cache）
- 会话保持（不想引入共享 session）
- 分片存储（按 key 分片）
- 关键性质：节点增减时迁移量小
- 问题：
- 热点 key 会压垮单节点（热点拆分/虚拟节点）
- 节点故障时 key 重映射会引发抖动。
- 会话保持
- 为什么需要 sticky
- 后端有状态
- 本地缓存必须命中
- WebSocket/长连接绑定到某实例
- 常见 sticky 手段
- Source IP hash
- 按客户端 IP 做 hash 选节点
- 优点：简单
- 缺点：
- NAT/代理下大量用户共享同一出口 IP -&amp;gt; 严重倾斜
- 用户换网 IP 变化导致漂移
- Cookie 粘性
- LB 注入 cookie ，后续按照 cookie 路由
- 优点：比 IP 稳定
- 缺点：跨域，隐私策略，cookie 清理，灰度/回源复杂
- 一致性哈希（按 userId/会话键）
- 工程风险
- 降低容错：节点挂了，该节点的用户都受影响
- 产生热点：某些用户/租户流量大-&amp;gt;单节点热
- 扩缩容抖动：重新分配导致缓存冷启动、延迟尖刺
- 推荐的替代方案
- 应用无状态 &amp;#43; 共享 session (Redis)
- 把状态外置(DB/Cache)，实例可以随时替换
- 长连接常见：连接层 sticky 不可避免，要做好限流与迁移策略
- 健康检查
- L4 健康检查
- 探测 TCP 能否 connect 成功
- 优点：便宜、通用
- 缺点：应用假活时仍然会通过（线程池满、依赖挂）
- L7 健康检查
- 请求 /healthz 或 /readyz
- 可检查
- 进程存活
- 是否可接新流量
- 关键依赖是否可用
- 设计要点
- liveness vs readliness 分离
- liveness：进程是否需要重启
- readliness：是否接流量
- 避免健康检查过重
- 如果每秒大量探测并且检查依赖，会把依赖也打挂
- 阈值与抖动控制
- 连续 N 次失败才摘除
- 连续 M 次成功才恢复
- 慢启动与预热
- 新实例启动后先不接流量，预热缓存/JIT，再标 ready
- 网络排障
- L3/L4 基础联通与路径
- ping
- 测试的是什么
- ping 用的是 ICMP Echo Request/Echo Reply
- 发 Echo Request（带序号 seq、时间戳等）
- 对端回 Echo Reply
- 测量往返时延 RTT
- ![](https://an-img.oss-cn-hangzhou.aliyuncs.com/2026/02/18/20260218103650584.png,492,184)
- 查看延迟
- 看 avg 和 min/max
- 抖动
- RTT 的波动程度
- stddev（标准差） 大，说明网络队列/无线/拥塞波动明显
- 丢包
- packet loss &amp;gt; 0 说明有包没有收到回包
- tracerout/mtr 的原理
- traceroute：用 TTL 把路径探测出来
- IP 包里有 TTL，每过一跳路由器把 TTL - 1
- 当 TTL 变为 0，路由器丢包并回 ICMP Time Exceeded
- traceroute 依次发 TTL=1,2,3 的探测包
- 可以看到每一跳的地址与该跳的 RTT
- 每一跳显式的 RTT 是你-&amp;gt;该跳-&amp;gt;你的往返，不是单程，也不是该跳-&amp;gt;下一跳的延迟
- mtr：traceroute &amp;#43; ping 的结合
- mtr 会对每一跳持续发探测包并统计
- 丢包率
- 最快/平均/最慢 RTT
- 抖动
- mtr 更适合定位抖动/偶发丢包/拥塞点
- 用 traceroute 看路径与绕路
-
&lt;/textarea&gt;</description></item><item><title>clash 规则配置</title><link>https://blog.ans20xx.com/posts/tools/clash-%E8%A7%84%E5%88%99%E9%85%8D%E7%BD%AE/</link><pubDate>Tue, 27 Jan 2026 00:00:00 +0000</pubDate><guid>https://blog.ans20xx.com/posts/tools/clash-%E8%A7%84%E5%88%99%E9%85%8D%E7%BD%AE/</guid><description>clas 规则配置</description></item></channel></rss>