网络最早的作用就一条:共享资源——一份数据存一处,大家来取。 但「共享」省的是存储,不是带宽;这两件事经常被混为一谈。
1.1.3 讲的是「信息怎么被理解」,这一节讲「信息为什么值得被传」。 1.2 会从用途转到历史:七个阶段,每一个都是被需求推出来的。
一、三样东西可以被共享
书里列的用途可以归成三类:
| 共享什么 | 典型场景 | 省下了什么 |
|---|---|---|
| 数据 | 文件服务器、网盘 | 磁盘空间 |
| 设备 | 网络打印机、共享摄像头 | 硬件采购 |
| 算力 | 服务器、云主机 | 本地机器性能 |
注意第一列的加粗:三类共享里,只有「数据」这一类会随使用人数线性增加网络流量。 共享打印机不会——打一份文件传输的是几十 KB 的打印指令,不是整台打印机。 这个区别决定了两类系统的设计方向完全不同:数据共享要抗带宽,设备共享要抗并发。
二、共享省的不是带宽
这是最容易错的一句话:「共享文件省磁盘,不省带宽」。
| 做法 | 磁盘占用 | 网络流量 |
|---|---|---|
| 每人存一份 | N 份 | 0 |
| 集中存一份 | 1 份 | N 份(每人取一次) |
表格里两列正好反着:省下的磁盘,变成了必须付出的流量。 所以「上文件服务器」这件事,对磁盘是好事,对网络是压力—— 在没有做缓存的情况下,100 个人同时取一个 1 GB 的文件,网络上就要跑 100 GB。 解决办法不是加大带宽,而是「让数据离用户近一点」:缓存、CDN、边缘节点,本质都是这一句话。
三、共享的反面是依赖
共享一旦成立,就产生了单点依赖。 文件服务器坏了,所有人都干不了活——这是「集中」必然的代价。
| 架构 | 好处 | 代价 |
|---|---|---|
| 每人一份 | 没有单点 | 数据不一致 |
| 集中一份 | 数据一致 | 有单点 |
两行都不完美,所以现实里是混合的:关键数据集中、常用数据本地缓存。 这也是整套分布式系统的起点:一致性、可用性、分区容忍,三者只能挑两个(CAP 定理)。 本书不展开 CAP,但记住「共享必有代价」这句话——后面讲 DNS、讲缓存、讲 CDN 都会用到它。
四、动手 Demo:一台机器上的资源,怎么给多个人用
起一个最小的 HTTP 服务,里面只放一份 760 字节的内容, 让 5 个客户端依次来取,统计每次取到多少、总共花了多久。 服务端的内存里只有一份数据,网络上却送了 5 份。
import http.server, socketserver, socket, threading, time
body = (u'36 课共享测试\n' * 40).encode('utf-8')
class H(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-Length', str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, *a):
pass
httpd = socketserver.TCPServer(('127.0.0.1', 0), H)
port = httpd.server_address[1]
threading.Thread(target=httpd.serve_forever, daemon=True).start()
t0 = time.perf_counter()
for _ in range(5):
c = socket.create_connection(('127.0.0.1', port), timeout=2)
c.sendall(b'GET / HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n')
while c.recv(4096):
pass
c.close()
print('5 次共 %.2f 毫秒' % ((time.perf_counter() - t0) * 1000))
httpd.shutdown()
实跑输出:
--------------------------------------------------------------------
一台机器上的资源,怎么给多个人用
--------------------------------------------------------------------
**计算机网络最早的作用就是共享资源**——
**一份文件存在一台机器上,别人通过网络来取,不必每人存一份。**
服务端只存一份 760 字节,端口 54126。
5 个客户端依次取完,累计 56.84 毫秒,每次拿到 874 字节(含 HTTP 头)。
**磁盘上只有一份,网络上送了 5 份**——**共享的是「存储」,不是「流量」**,这一点常被弄混:
**共享文件省的是磁盘,不是带宽;带宽反而不够用。**
「服务端 760 字节、每次拿到 874 字节」这两个数差 114——多出来的是 HTTP 响应头。 这就是「信息通信」的固定开销:为了让对方看懂,每次都要附带说明。 注意这里 5 个客户端是「依次」取的,不是并发。 并发下的数字会完全不同——本章的 Demo 只验证「一份数据被送多次」这件事,不测并发性能。
30 秒实验
- 把 5 次改成 50 次,看总耗时是不是正好涨 10 倍——如果不是,说明有固定开销在里面。
- 把
body从 760 字节改成 7600 字节,看「每次拿到的字节」与「服务端存的字节」差多少。 - 用
threading把 5 个客户端改成同时跑,看总耗时是变短还是变长,想想为什么。
常见误区
- 以为共享就是「大家都能访问」。 共享真正的代价是「必须有人维护」,而且坏了会影响所有人。
- 以为文件服务器省带宽。 恰恰相反,它把本地的磁盘读取变成了网络传输,带宽压力更大。
- 以为并发一定比串行快。 回环上的并发要处理锁与调度,小数据量下反而更慢。
自测三问(点开对答案)
1. 「共享文件省磁盘不省带宽」这句话怎么理解? —— **存储从 N 份变成 1 份,但每次访问都要走网络**。访问人数越多,网络压力越大。 **省下的磁盘变成了付出的流量。** 2. 服务端只存 760 字节,客户端每次收到 874 字节,差的是什么? —— **差的是 HTTP 响应头**(状态行、Content-Length、日期等)。 **这部分是「让对方看懂」的固定成本**,数据越短占比越高。 3. 集中共享带来了什么必然的代价? —— **单点依赖**。服务器一坏,所有人受影响。 **所以现实里是「关键数据集中、常用数据缓存」的混合结构。**1.1 节到此结束。下一节换个视角看历史:七个阶段,每一步都是被一个具体需求推出来的。
- ☐ (本节完,下一节 1.2.1 批处理)