📚 第一章 网络基础知识
📄 一句话概括

网关与路由器的区别只有一条:路由器只换帧头,网关要换整个报文格式。 网关必须懂两边的语义,所以它既是瓶颈也是单点。

📝 本节和前面几节的关系

这是 1.9 节的最后一个设备,也是「最多义」的一个词。 「默认网关」和「协议网关」是两个不同的东西,文末会说清。

一、它改的是内容

和路由器放一起比就清楚了:

对比项 路由器 网关
改什么 只换帧头 换整个报文格式
懂语义吗 不懂 必须懂两边
是否透明 基本透明 不透明
故障影响 可以绕路 没有绕路

第二行是本质差别: 路由器只认 IP 头里的目的地址,包里装的是 HTTP 还是数据库协议,它完全不管。 网关不行——它得把一种格式「翻译」成另一种,所以它必须同时理解两边的协议。 第四行是架构上的代价:路由器挂了还能走别的路,网关挂了两边就彻底断了。 所以网关要么做冗余,要么就得接受「它是单点」这个事实。 这也是为什么现代系统尽量少用网关——能用统一协议直连,就别翻译。

二、翻译一次要付什么

拿一条 HTTP 请求翻成内部格式看:

项 HTTP 写法 内部格式
长度 63 字节 23 字节
可读性 人能读 只有懂的人能读
扩展性 加个头就行 要改协议

第一行那个「23 比 63 小」很容易让人以为「翻译就是压缩」:不是的。 它小是因为内部格式省掉了大量冗余(重复的头名、可省的空白), 但那 23 个字节里的每个位置都是硬约定,改一个字节就得两边一起改。 第三行才是真正的代价: HTTP 加一个新头,不影响任何现有实现;内部二进制格式加一个字段,所有端点都要重新编译。 这就是「文本协议活得久、二进制协议跑得快」的取舍。 所以「翻译」这个词有两层意思: 一层是「换编码」(可逆、无损),一层是「换语义模型」(可能丢信息)。 网关最难的地方永远是第二层——两种协议的语义不对齐时,网关只能自己编一套折中规则, 这套规则往往就成了新的技术债。

三、「默认网关」是另一个东西

同一个词,两个完全不同的含义:

说法 指的是 干什么
默认网关 一个 IP 地址 出网段时的下一跳
协议网关 一台转换设备 翻译两种协议
API 网关 一个服务 统一入口、鉴权、限流

第一行是日常配置里最常见的:你在网卡设置里填的那个「默认网关」,其实就是一个 IP, 它的作用是「本网段之外的流量都交给它」。 它干的活是路由,不是翻译——严格说它是「默认路由器」,叫「网关」是历史习惯。 第三行是今天最流行的用法: API 网关既不做协议翻译也不做路由转发,它做的是「统一入口」——鉴权、限流、日志、灰度。 这个词的语义已经漂移到「任何统一入口」了。 所以看书时遇到「网关」两个字,先判断是哪个意思: 看上下文里有没有「协议不同」「格式转换」这类词,有就是协议网关,没有多半是「默认下一跳」。

四、动手 Demo:网关做的是「协议翻译」

把一条 HTTP 请求翻成一种假想的内部格式,看字节与结构怎么变。 重点是「变短了,但变硬了」。

http = (b'GET /sensor/temp HTTP/1.1\r\n'
        b'Host: iot.local\r\n'
        b'Accept: */*\r\n\r\n')
inner = b'REQ|sensor.temp|read|v1'

print('HTTP 写法 %d 字节' % len(http))
print('内部格式 %d 字节 → %s' % (len(inner), inner.decode()))
print('比值 %.0f%%' % (len(inner) * 100.0 / len(http)))

back = {'REQ': 'GET', 'sensor.temp': '/sensor/temp'}
verb, path = inner.decode().split('|')[:2]
print('翻回去:%s %s' % (back[verb], back[path]))

实跑输出:

--------------------------------------------------------------------
网关做的是「协议翻译」
--------------------------------------------------------------------
**网关与路由器的区别在于「改不改内容」**:**路由器只换帧头,网关要换整个报文格式。**

下面把一条 HTTP 请求「翻译」成一种假想的内部格式,看字节怎么变:

  **HTTP 写法**:63 字节
  **内部格式**:23 字节 → `REQ|sensor.temp|read|v1`

  项         HTTP         内部格式
  -------------------------------------------
  长度       63 字节      23 字节
  可读性     人能读       **只有懂的人能读**
  扩展性     加头就行     **要改协议**

**网关的价值就在这个「翻译」上**:**把两套完全不同的协议接起来,让两边都以为对面是自己人。**
**代价是网关必须懂两边的语义**——**它不能像路由器那样「只管转发不管内容」。**

**所以网关是瓶颈也是单点**:**它挂了,两边就彻底断了,没有绕路可走。**
**这也是为什么现代系统尽量少用网关**,**能用统一协议直连就别翻译。**

63 字节对 23 字节,只有原来的三成多:省掉的是重复的头名(Host:、Accept:)与 CRLF, 不是把内容压缩了。 注意最后三行的「翻回去」:这里能翻回去,是因为两种格式的语义能一一对应。 真实网关经常遇到对不上的情况——比如 HTTP 的 Accept 在内部格式里根本没有对应字段, 那这个信息就只能丢掉。 「翻译」最大的风险就是这种静默丢失:两边都不报错,但功能悄悄少了一块。 所以设计网关时要先列出「哪些语义必须保留」,对不上的部分要显式拒绝,而不是默默丢掉。

30 秒实验

  1. 给 http 加一个 Cookie 头,看内部格式能不能表达它。
  2. 把 inner 改成用逗号分隔,看解析代码要改几处——这就是「二进制与文本」在扩展性上的差别。
  3. 想一下:你家的光猫算不算网关?它到底做了什么转换?

常见误区

  1. 以为「网关」都是同一个东西。 默认网关、协议网关、API 网关是三回事,看上下文判断。
  2. 以为网关只是「更聪明的路由器」。 路由器不改内容,网关要改,所以它必须懂两边语义。
  3. 以为翻译一定无损。 语义对不上时信息会丢, 而且两边都不报错——设计时要显式列出必须保留的字段。
自测三问(点开对答案) 1. 网关与路由器最本质的区别是什么? —— **路由器只换帧头、不懂内容;网关要换整个报文格式,必须懂两边语义。**所以路由器可以绕路, 网关挂了就彻底断。 2. 为什么内部二进制格式比 HTTP 短得多,却更难扩展? —— **文本协议加个头不影响现有实现;二进制格式加字段要所有端点一起改。**这就是「文本活得久、 二进制跑得快」的取舍。 3. 「默认网关」到底是不是网关? —— **严格说它是「默认路由器」**:干的是路由的活,不是翻译。叫「网关」是历史习惯。

下一节进入 1.10:现代网络实态——把前面这些零件拼成一张真实的网络图。

相关笔记