模块一 · 应用层
代理与负载均衡
你的流量不一定直达目的地 —— 中间可能有个"代理"替你去取。本章会实测本机的代理配置,并且会发现一件很值得注意的事:同一个系统里有三套代理配置,而且它们可以不同,分别作用于不同API和应用。
本章要解决的问题:你的流量不一定直达目的地 —— 中间可能有个"代理"替你去取。本章会实测本机的代理配置,并且会发现一件很值得注意的事:同一个系统里有三套代理配置,而且它们可以不同,分别作用于不同API和应用。
本章的证据来源:历史实测记录(三层代理配置、代理进程监听端口、TUN 网卡与默认路由)。概念定义出自 RFC 9110(代理语义)。
先从一个例子理解概念
你不直接找目标取内容,而是让中间服务替你去取;另一端也可能在入口把请求分给多台机器。这些场景需要分清代表谁、决定什么。
替哪一方工作:正向与反向代理
正向代理代表客户端访问目标;反向代理代表服务端接收请求,再交给内部服务。分类看它代表哪一方,不是简单看箭头朝左还是朝右。
应用不用显式指定:透明处理
透明代理等处理方式可通过路由或过滤接住应用流量,使应用无需显式指定代理。是否发生及最终出口,要看实际路径和配置。
把工作分给多个后端:负载均衡
负载均衡是在多台服务端之间分配连接或请求;这些被分配的服务器叫后端。不是看到多个端口就证明存在均衡器,也不是必定平均分。
按什么信息分配:L4与L7
L4借用OSI第4层号,常指按传输地址/端口等分配;L7借用第7层号,指理解应用内容后决策,比如按网页路径分配。这些层号表达决策范围,不直接保证性能。
把内容放到不同地点:CDN
CDN(内容分发网络)把内容和服务分布到多个位置,通过缓存与调度改善访问。缓存命中表示可复用已存内容,具体节点选择不只靠DNS一种方式。
下面再用这些概念看原理、命令和结果。规范与官方资料列在本章末尾,类比只帮助理解,不代替协议规则。
代理能解决什么问题
代理就是"中间人"—— 你让它去替你取东西。它有几种典型用途:
| 用途 | 说明 |
|---|---|
| 共享出口 | 一个公司几百台机器只用一个公网 IP 出去(和《网络层》模块的 NAT 是同一类需求) |
| 缓存 | 常用的内容代理上存一份,多人访问时不用重复取 |
| 访问控制 | 统一决定"谁能访问哪些网站",并留下日志 |
| 跨网络访问 | 内网穿透、或者访问被限制的资源 |
注意:代理和 NAT 是两件事。 NAT 在网络层改地址(用户完全无感),代理在应用层替你去请求(可能感知得到)。本机两个都装了 —— 后面会看到。
正向代理与反向代理
这是代理最重要的一个分类。
| 正向代理 | 反向代理 | |
|---|---|---|
| 代表谁 | 代表客户端 | 代表服务器 |
| 谁配置它 | 客户端自己(或客户端所在网络) | 服务器方 |
| 客户端知道吗 | 知道(自己是配了代理的) | 通常不知道(以为在直连一个网站) |
| 服务器知道吗 | 通常不知道真实客户端是谁 | 知道背后有代理 |
| 典型场景 | 公司统一出口、访问受限资源 | 负载均衡、CDN、统一入口 |
一句话区分:正向代理知道"我是替客户端去的",反向代理知道"我是替服务器接的"。
实测:本机有三套代理配置,且它们可以因应用范围不同而采用不同配置
这是本章最有意思的一个发现。查三个不同的地方:
第一层:环境变量
http_proxy = http://127.0.0.1:7897
https_proxy = http://127.0.0.1:7897
all_proxy = http://127.0.0.1:7897谁读这个:命令行工具(curl、wget、很多语言的 HTTP 库)。《应用层》模块实测过 —— curl -v 的输出里明确写着 Uses proxy env variable https_proxy。
第二层:WinHTTP(系统级)
netsh winhttp show proxy
→ Current WinHTTP proxy settings: Direct access (no proxy server).谁读这个:Windows 服务、以及使用 WinHTTP API 的程序。
第三层:WinINET(IE / Edge 用的,存在注册表里)
ProxyEnable = 1
ProxyServer = 127.0.0.1:7890
ProxyOverride = ;localhost.*;;*zhihu.com;*zhimg.com;*jd.com;…谁读这个:Internet Explorer、Edge、以及很多"跟随系统设置"的 GUI 程序。
三套配置对照
| 层次 | 指向哪里 | 谁在用 |
|---|---|---|
| 环境变量 | 127.0.0.1:7897 | 命令行工具 |
| WinINET(注册表) | 127.0.0.1:7890 | 浏览器和 GUI 程序 |
| WinHTTP | 无代理(直接访问) | Windows 服务和 WinHTTP 程序 |
三个地方,两个不同的端口,一个没有显式代理配置。
再对照本机实际监听的两个代理进程:
127.0.0.1:7890 FlClashCore
127.0.0.1:7897 verge-mihomo
127.0.0.1:1053 verge-mihomo7890 是 FlClash,7897 是另一个代理软件(verge-mihomo)。这台机器上同时装了两个代理程序,各自占一个端口,而且配置分别指向了不同的那一个。
透明代理与 TUN:不配置也能被接管
《链路层和局域网》模块实测过一个反直觉的现象:向 192.0.2.1:9999(一个永不路由的保留地址)发连接,0.6 毫秒就"成功"了。
原因就在这张网卡:
FlClash 198.18.0.1/30 ← 代理软件建的 TUN 虚拟网卡证据链(都在前面的模块实测过):
| 证据 | 在哪一章 |
|---|---|
| 存在198.18.0.1/30的TUN接口,历史选路选择FlClash;空字段不证明度量0 | 路由章节 |
两条默认路由并存,Find-NetRoute 判定走 FlClash | 《网络层》模块 |
连保留地址也"连接成功",且源地址是 198.18.0.1 | 《全景与基础》模块 |
域名解析出 198.18.x.x 的假地址(fake-IP) | 《应用层》模块 |
| 四个不同的 DNS 服务器返回同一个答案 | 《应用层》模块 |
这些历史记录与TUN接管部分流量相容。 Find-NetRoute选择该接口是观察;具体度量、代理代答机制及每条连接出口需要配置、日志或抓包,不由空字段和保留地址一次连接单独证明。
这叫透明代理 —— 从程序的角度看,它只是在正常地 connect() 一个地址,完全不知道中间有个代理。
负载均衡:一台服务器扛不住怎么办
问题:一个网站有几百万用户,一台服务器无论如何都扛不住。
办法:后面放很多台服务器,前面放一个"调度员"把请求分下去。这个调度员就是负载均衡器。
对外它只有一个地址,用户不知道背后有多少台机器 —— 所以负载均衡通常是反向代理。
L4 与 L7:两种层次的负载均衡
| L4(传输层) | L7(应用层) | |
|---|---|---|
| 看什么 | IP 和端口 | HTTP 内容(路径、Host、Cookie、头部) |
| 能做什么 | 按连接分发 | 按 URL 路径分发、改写请求、按 Cookie 保持会话 |
| 性能 | 高(不需要解析内容) | 需要解析应用字段,实际性能取决于实现与硬件 |
| 典型工具 | LVS、云厂商的 NLB | Nginx、HAProxy、云厂商的 ALB |
这个区分正好接上了《全景与基础》模块讲过的"分层":
常见的调度算法
| 算法 | 说明 |
|---|---|
| 轮询 | 依次轮流分 |
| 加权轮询 | 配置高的机器分更多 |
| 最少连接 | 分给当前连接数最少的 |
| 一致性哈希 | 同一个用户的请求固定打到同一台(用于缓存命中率) |
还有一个必须做的事:健康检查。 负载均衡器要定期探测后端服务器,发现某台挂了就不再往它那里分发。没有健康检查的负载均衡,会把请求送给已经死掉的服务器 —— 用户看到的就是 502(《应用层》模块讲过 502 是"连不上后面的服务器")。
实测:别把"多个端口监听"当成负载均衡
历史实测记录有几个 node 进程在监听端口:
127.0.0.1:3201 node
127.0.0.1:5173 node
127.0.0.1:5174 node这不是负载均衡。 它们是三个不同项目各自的开发服务器(本教程所在的站点就跑在 5174)。
判断依据:历史进程用途与提供内容显示它们是不同开发服务;仅监听127.0.0.1不能排除本机负载均衡。常见对外服务的负载均衡部署会;内部负载均衡也可以只监听私网或本机地址:
- 监听在对外地址上
- 后面挂着多台提供相同服务的服务器
- 有健康检查机制
CDN:地理维度的负载均衡
CDN(内容分发网络)可以理解成"把负载均衡做到地理维度":
把内容缓存在离用户最近的节点上
→ 用户从就近节点取,不用回源
→ 延迟低、源站压力小用户怎么被引导到最近的节点? 可使用地理/策略DNS、Anycast及应用层调度等机制;并非只靠DNS:解析同一个域名时,DNS 根据你的来源返回离你最近的那个节点的 IP。
常见误解
误解一:"系统里只有一个代理设置"
历史实测记录至少有三个(环境变量、WinINET、WinHTTP),而且可以互相矛盾 —— 本机就是环境变量指向 7897、WinINET 指向 7890、WinHTTP 说直连。这就是"有的程序走代理、有的不走"的根本原因。
误解二:"没配代理就不会走代理"
透明代理不需要配置。 历史实测记录:TUN接口被历史选路结果选中,具体连接是否代答以及最终出口仍需确认(《全景与基础》模块那个"连保留地址也能成功"的实验就是证据)。
误解三:"正向代理和反向代理只是方向不同"
本质区别是"替谁办事":正向代理代表客户端(客户端知道自己配了代理),反向代理代表服务器(客户端以为在直连)。
误解四:"负载均衡就是平均分配"
不只是"平均"。实际会用加权(配置高的多分)、最少连接(看实时负载)、一致性哈希(让同一用户固定落在同一台,提高缓存命中率)。而且健康检查比调度算法更重要 —— 没有它,均衡器会一直往挂掉的服务器分发请求。
误解五:"多个端口在监听就是集群或负载均衡"
历史实测记录那几个 node 端口是不同项目各自的开发服务器。判断标准是"它们是否提供相同的服务、前面有没有统一入口",而不是"端口多不多"。
本章小结
| 结论 | 类型 |
|---|---|
| 代理的典型用途:共享出口、缓存、访问控制、跨网络访问 | 标准 |
| 正向代理代表客户端(客户端知情),反向代理代表服务器(客户端不知情) | 标准 |
实测:本机环境变量指向 127.0.0.1:7897,WinINET 指向 127.0.0.1:7890,WinHTTP 为直连 | 实测 |
| 三套代理配置并存且互相矛盾,是"程序走不走代理不一致"的原因 | 实测 |
| 实测:本机同时运行两个代理进程,分别监听 7890 与 7897 | 实测 |
| TUN/路由或过滤机制可透明处理流量,具体度量与最终出口需查配置和日志 | 机制与限制 |
| 透明代理会让部分网络工具(如 tracert)的输出失去意义 | 实测推论 |
| L4 负载均衡看 IP 和端口,L7 看应用层内容,后者更慢也更灵活 | 标准 |
| 常见调度算法:轮询、加权、最少连接、一致性哈希 | 标准 |
| 健康检查比调度算法更关键,缺了它会把请求送给已挂的服务器 | 标准 |
CDN 靠 DNS 把用户引导到最近节点;实测响应含 CF-Cache-Status: HIT、Age: 3 | 实测 |
| 实测:本机三个 node 端口是不同的开发服务器,不是负载均衡 | 实测 |
自测题
7 题 · 先自己答,再展开对照
正向代理和反向代理的本质区别是什么?各举一个场景。
本质区别是"代表谁":正向代理代表客户端,反向代理代表服务器。
- 正向代理:公司给所有员工配一个代理统一出口 —— 客户端知道自己配了代理。
- 反向代理:一个网站前面放一台 Nginx 把请求分给后面 10 台服务器 —— 客户端以为自己只是在直连这个网站,不知道背后有多少台。你的命令行工具走了代理,但浏览器没走。可能是什么原因?
因为它们读的是不同的代理配置。 历史实测记录就有三套:
- 命令行工具(curl 等)读环境变量(本机是127.0.0.1:7897)
- 浏览器(IE/Edge 及跟随系统设置的程序)读 WinINET 注册表(本机是127.0.0.1:7890)
- Windows 服务读 WinHTTP(本机是"直连,无代理")
三套配置互相独立、可以指向不同地方,所以不同程序的行为自然不一致。你什么都没配置,但抓包发现流量经过了某个程序。这可能吗?怎么做到的?
可能,透明代理可通过TUN、路由或过滤机制处理应用流量。应区分程序到TUN、代理新建的外连和最终出口;低度量只是方法之一,空字段不能证明设置为0。L4 和 L7 负载均衡分别能看到什么?为什么 L7 更慢?
L4常按地址和端口等信息分发;L7理解HTTP路径/头部或其他应用内容。按路径选择后端不需等整个请求体,性能要结合实现、配置和硬件。负载均衡器为什么必须做健康检查?如果没有会怎样?
为了及时发现后端服务器故障并停止向它分发请求。
没有健康检查的后果:某台后端服务器崩溃或服务卡死,但负载均衡器不知道,继续把请求分给它 —— 用户就会间歇性地遇到错误(典型表现是 502 Bad Gateway,表示"连不上后面的服务器")。有健康检查的话,故障机器会被自动摘除,用户几乎无感。一个网站的响应头里有
CF-Cache-Status: HIT,说明什么?说明这个响应是从 CDN 的缓存里直接返回的,没有回源到原始服务器。CF-Cache-Status是 Cloudflare 的响应头(CF表示 Cloudflare),HIT表示"命中缓存"。
历史实测记录那个响应还带了Age: 3,表示这份缓存是 3 秒前生成的。这就是 CDN 在起作用 —— 用户从就近节点拿到内容,源站没有被请求。你在自己机器上看到有 5 个端口在监听,能断定在跑负载均衡吗?
不能。 多个端口监听有多种可能:不同项目各自的服务(历史实测记录的 3201、5173、5174 就是三个不同项目的开发服务器)、同一程序的不同功能端口、或者你的机器本身就是个服务器。
判断是否为负载均衡要看:这些服务是否提供相同的内容、前面是否有一个统一入口、是否有健康检查机制。仅仅"端口多"不说明任何问题。
参考资料与适用范围
修订核对日期:2026-10-13。规则按所列协议与实现范围理解;文中的原始命令输出是历史观察,不表示本次重新实测。跨版本、代理/隧道及不同捕获位置需要另行核对。