HTTP 各版本演进与 HTTPS 原理详解

2 阅读19分钟

一、先搞清楚 HTTP 是什么

HTTP(HyperText Transfer Protocol)就是浏览器和服务器之间"对话"的规则。你在浏览器输入一个网址,浏览器按照 HTTP 规则发一个请求,服务器按照 HTTP 规则回一个响应。

浏览器:「我要 /index.html」          →  请求(Request)
服务器:「给你,200 OK,内容如下...」   ←  响应(Response

HTTP 从 1991 年诞生到现在,经历了 5 个大版本。每个版本都是为了解决上一个版本的痛点。


二、HTTP/0.9(1991)—— 最原始的版本

特点

  • 只支持 GET 方法
  • 没有请求头、没有响应头
  • 只能传 HTML 文本
  • 响应完就断开连接

一次对话长这样

请求:GET /hello.html
响应:<html>Hello World</html>
(连接断开)

就这么简单粗暴。没有状态码,没有 Content-Type,啥都没有。

存在的问题

  • 只能传 HTML,不能传图片、CSS、JS
  • 没有任何元数据(不知道内容多大、什么类型、什么编码)
  • 每次请求都要新建连接

三、HTTP/1.0(1996)—— 有模有样了

解决了什么

新增能力说明
请求头 & 响应头可以携带元数据了(Content-Type、Content-Length 等)
多种方法GET、POST、HEAD
状态码200、404、500 等,知道请求成功还是失败了
Content-Type可以传图片、音频、视频,不再局限于 HTML
版本号请求行里带上 HTTP/1.0

一次对话长这样

请求:
GET /logo.png HTTP/1.0
Host: www.example.com
Accept: image/png

响应:
HTTP/1.0 200 OK
Content-Type: image/png
Content-Length: 4096

(图片二进制数据)
(连接断开)

存在的问题

最大的问题:短连接。 每个请求都要经历 TCP 三次握手 → 传数据 → 四次挥手。

一个网页有 1 个 HTML + 10 个图片 + 3 个 CSS + 5 个 JS = 19 个请求,就要建立 19 次 TCP 连接。

连接1[三次握手] → GET /index.html[响应][四次挥手]
连接2[三次握手] → GET /style.css[响应][四次挥手]
连接3[三次握手] → GET /logo.png[响应][四次挥手]
...重复 19

每次握手和挥手都要消耗时间和系统资源,极其浪费

虽然有些实现支持非标准的 Connection: keep-alive,但这不是规范的一部分,行为不统一。


四、HTTP/1.1(1997)—— 用了二十多年的主力

解决了什么

1. 持久连接(Keep-Alive)—— 最重要的改进

默认开启 TCP 连接复用。一个连接可以发多个请求,不用每次都握手挥手。

HTTP/1.0:
  连接1 → 请求1 → 响应1 → 断开
  连接2 → 请求2 → 响应2 → 断开
  连接3 → 请求3 → 响应3 → 断开

HTTP/1.1:
  连接1 → 请求1 → 响应1 → 请求2 → 响应2 → 请求3 → 响应3 → 断开

2. 管线化(Pipelining)

理论上可以不等响应就发下一个请求:

客户端:请求1 → 请求2 → 请求3 →
                                  等待...
服务端:                    ← 响应1 ← 响应2 ← 响应3

但实际几乎没人用(原因见下面的问题)。

3. 分块传输(Chunked Transfer)

不需要预先知道内容的总大小,边生成边发送:

HTTP/1.1 200 OK
Transfer-Encoding: chunked

5\r\n
Hello\r\n
6\r\n
 World\r\n
0\r\n
\r\n

适用场景:服务端流式输出(比如 ChatGPT 的逐字输出)。

4. 其他新增

能力说明
Host 头必选一个 IP 可以托管多个域名(虚拟主机)
Cache-Control更精细的缓存控制(替代 Expires)
Range 请求支持断点续传(下载了一半断了,可以接着下)
100 Continue先问服务器"我要发一个大文件,你准备好了吗?"
PUT / DELETE / OPTIONS / PATCH更多的方法,RESTful API 的基础

存在的问题

问题一:队头阻塞(Head-of-Line Blocking)

这是 HTTP/1.1 最致命的问题。

虽然支持管线化,但响应必须按请求的顺序返回。如果第一个请求处理很慢,后面的请求即使已经处理完了,也必须排队等着。

请求顺序:请求1(慢查询)→ 请求2(静态图片)→ 请求3(CSS)

实际情况:
  请求1 ████████████████████░░░░░(处理中...3秒)
  请求2 ░░░░░░░░░░░░░░░░░░░████░  (早就好了,但必须等请求1)
  请求3 ░░░░░░░░░░░░░░░░░░░░░░██  (也在排队等)

就像高速公路只有一条车道,前面的大卡车开得慢,后面的跑车再快也超不过去。

问题二:并发限制的妥协

为了绕开队头阻塞,浏览器的做法是 对同一个域名开 6 个并行 TCP 连接

但这导致了新的问题:

  • 每个连接都要三次握手 + TLS 握手,开销不小
  • 服务器要维护大量连接
  • 催生了"域名分片"等 hack 手段(把资源分散到 cdn1.xxx.com、cdn2.xxx.com 来突破 6 个限制)

问题三:头部冗余

每个请求都要带上完整的头部(Cookie、User-Agent、Accept 等),这些头部在同一个连接上几乎不变,但每次都要重复发送。一个大 Cookie 可能有 1-2KB,100 个请求就白白多传 100-200KB。

问题四:只能客户端主动

服务器不能主动给客户端推数据,只能客户端请求、服务器响应。想实现"服务器推送"只能用长轮询或 WebSocket。


五、HTTP/2(2015)—— 质的飞跃

核心思想

在一条 TCP 连接上实现真正的并行传输。

解决了什么

1. 二进制分帧(Binary Framing)—— 基础革新

HTTP/1.x 是文本协议(人能直接看懂),HTTP/2 改成了二进制协议。

所有数据被拆分成更小的 帧(Frame),每个帧有一个 Stream ID,标记它属于哪个请求/响应。

HTTP/1.1(文本):
  GET /index.html HTTP/1.1\r\n
  Host: example.com\r\n
  \r\n

HTTP/2(二进制帧):
  ┌──────────┬───────────┬──────────────┐
  │ Length:9Type:HEADStream ID: 1HEADERS 帧
  ├──────────┴───────────┴──────────────┤
  │ :method = GET, :path = /index.html  │
  └─────────────────────────────────────┘

2. 多路复用(Multiplexing)—— 最重要的改进

多个请求/响应可以在同一个 TCP 连接上交错传输,互不阻塞。

HTTP/1.1:6 条连接,每条排队
  连接1: [请求1 ████████████]
  连接2: [请求2 ████]
  连接3: [请求3 ██████]
  连接4: [请求4 ███]
  连接5: [请求5 ████████]
  连接6: [请求6 ██]

HTTP/2:1 条连接,交错并行
  连接1: [帧1a][帧2a][帧3a][帧1b][帧2b][帧3b][帧1c][帧2c]...
          ↑stream1  ↑stream2  ↑stream3  ↑stream1  ↑stream2

类比理解:

HTTP/1.1 就像有 6 条单行道,每条道上车要排队。HTTP/2 就像有一条超宽的高速公路,所有车可以同时跑,通过车牌号(Stream ID)区分。

这彻底解决了 HTTP 层的队头阻塞,也不再需要"域名分片"等 hack 手段。

3. 头部压缩(HPACK)

HTTP/2 用 HPACK 算法压缩头部:

  • 维护一个静态表(61 个常见头部,如 :method: GETcontent-type: text/html),用索引号代替完整字符串
  • 维护一个动态表,记录当前连接用过的头部,后续只发索引号
  • 对值做 Huffman 编码 压缩
第一次请求:
  Cookie: session=abc123def456...   (完整发送,同时存入动态表,索引 62)

第二次请求:
  62                                 (只发一个索引号,省掉了几百字节)

效果:头部大小减少 85-95%

4. 服务器推送(Server Push)

服务器可以主动推送客户端可能需要的资源。

客户端请求 /index.html
服务器响应 /index.html
服务器主动推送 /style.css   ← 不用等客户端解析 HTML 后再请求
服务器主动推送 /app.js      ← 提前到达,减少等待

但实际效果争议较大——很难准确预测客户端需要什么,推错了反而浪费带宽。Chrome 已在 2022 年移除了对 Server Push 的支持。

5. 流优先级(Stream Priority)

可以给不同的请求设置优先级。比如 CSS 优先级高于图片,因为 CSS 会阻塞渲染。

存在的问题

TCP 层的队头阻塞 —— HTTP/2 的阿喀琉斯之踵

HTTP/2 解决了 HTTP 层的队头阻塞,但底下的 TCP 层还有队头阻塞

TCP 保证数据按序交付。如果一个 TCP 包丢失了,即使后面的包已经到达,TCP 也不会把它们交给应用层,而是等丢失的包重传回来。

TCP 传输:包1 → 包2(丢了!) → 包3 → 包4 → 包5

TCP 层:包1 ✓   包2 ?等重传...  包3-5 已到但不能用
         └── 所有 Stream 都被阻塞!

HTTP/1.1 开 6 个连接,一个连接丢包只影响那一个连接上的请求。HTTP/2 所有请求共用一个连接,一个包丢失会阻塞所有请求

在网络质量差(丢包率 > 2%)的环境下,HTTP/2 的表现可能反而不如 HTTP/1.1

TLS 握手开销

HTTP/2 虽然协议本身不强制加密,但所有浏览器都要求 HTTP/2 必须走 HTTPS。TLS 握手需要额外的 1-2 个 RTT。


六、HTTP/3(2022)—— 换掉了 TCP

核心思想

既然 TCP 的队头阻塞无法在 TCP 层面解决,那就 不用 TCP 了,改用 QUIC(基于 UDP)。

QUIC 是什么

QUIC(Quick UDP Internet Connections)是 Google 设计的传输层协议,跑在 UDP 上。你可以把它理解为"重新实现了一个更好的 TCP"。

HTTP/2 的协议栈:          HTTP/3 的协议栈:
┌──────────┐              ┌──────────┐
│  HTTP/2  │              │  HTTP/3  │
├──────────┤              ├──────────┤
│   TLS    │              │   QUIC   │ ← 把 TLS 融合进来了
├──────────┤              ├──────────┤
│   TCP    │              │   UDP    │
├──────────┤              ├──────────┤
│    IP    │              │    IP    │
└──────────┘              └──────────┘

解决了什么

1. 彻底消灭队头阻塞

QUIC 在传输层就支持多路复用。每个 Stream 独立管理自己的数据包顺序,一个 Stream 丢包不影响其他 Stream

HTTP/2 + TCP:
  Stream 1 的包丢了 → 所有 Stream 被阻塞等重传

HTTP/3 + QUIC:
  Stream 1 的包丢了 → 只有 Stream 1 等重传,Stream 2/3/4 正常收发

2. 0-RTT 连接建立

TCP + TLS 需要的握手:

TCP 三次握手:   1 RTT(客户端→服务器→客户端)
TLS 1.2 握手:  2 RTT
TLS 1.3 握手:  1 RTT
──────────────────
总计:TCP + TLS 1.3 = 2 RTT(数据才能开始传)

QUIC 的握手:

首次连接:1 RTT(QUIC 把传输层握手和加密握手合并了)
重连(0-RTT):0 RTT(第一个包就可以带数据!)

类比理解:

TCP + TLS 就像打电话:先拨号等接通(TCP),再输密码验证身份(TLS),然后才能说话。QUIC 就像发微信:直接把消息和身份验证一起发出去,对方收到就能回。重连时更像对方还认识你,直接开聊。

3. 连接迁移

TCP 连接用"源IP + 源端口 + 目标IP + 目标端口"四元组标识。你手机从 WiFi 切到 4G,IP 变了,TCP 连接就断了,必须重新握手。

QUIC 用一个 Connection ID 标识连接。IP 变了没关系,只要 Connection ID 不变,连接就能无缝切换。

TCP:WiFi → 4G = 连接断开 → 重新三次握手 + TLS 握手 → 恢复
QUIC:WiFi → 4G = IP 变了 → Connection ID 没变 → 无缝继续

对移动端体验提升巨大(电梯、地铁、从室内走到室外)。

4. 改进的头部压缩(QPACK)

HPACK 依赖严格的包顺序(因为动态表需要同步更新),和 QUIC 的乱序特性冲突。QPACK 解决了这个问题,允许在乱序到达的情况下也能正确解压头部。

存在的问题

问题说明
UDP 被运营商/防火墙限制部分网络环境会限速或丢弃 UDP 包,需要回退到 TCP
中间设备不友好很多老旧的路由器、防火墙对 UDP 支持不好
CPU 开销QUIC 在用户态实现(不在内核里),加解密和拥塞控制消耗更多 CPU
生态还在成熟服务端支持(Nginx 2022 才正式支持)、调试工具都还在完善
无法利用 TCP 的内核优化TCP 经过几十年优化,内核的 TCP 栈非常高效;QUIC 在用户态,暂时没法比

七、各版本一张图对比

        HTTP/0.9    HTTP/1.0    HTTP/1.1      HTTP/2        HTTP/3
年份      1991        1996        1997         2015          2022
传输层    TCP         TCP         TCP          TCP           UDP(QUIC)
连接方式  短连接      短连接      持久连接      多路复用       多路复用
并发能力  无          无          管线化(废了)   Stream并行     Stream并行
头部格式  无          文本        文本          HPACK压缩      QPACK压缩
加密      无          可选        可选          事实强制       强制(内置TLS)
队头阻塞  -           有          有(HTTP层)    有(TCP层)      无!
握手RTT   1(TCP)      1(TCP)      1(TCP)       2-3(TCP+TLS)  0-1(QUIC)
服务器推  无          无          无            支持(已废弃)    无

八、HTTPS 详解

8.1 为什么需要 HTTPS?

HTTP 是明文传输,存在三大安全风险:

风险场景后果
窃听连公共 WiFi 时,路由器能看到所有内容密码、银行卡号泄露
篡改运营商在网页中插入广告页面被注入恶意代码
冒充钓鱼网站伪装成银行用户被骗输入密码

HTTPS 就是 HTTP + TLS,用加密解决这三个问题:

安全需求解决方案
防窃听对称加密(AES),加密传输内容
防篡改消息认证码(MAC),验证数据完整性
防冒充数字证书 + 非对称加密(RSA/ECDSA),验证服务器身份

8.2 对称加密 vs 非对称加密

理解 HTTPS 之前,必须搞清楚这两种加密方式。

对称加密

加密和解密用同一把钥匙

明文 "Hello" + 密钥 K → 加密 → 密文 "x7$f2"
密文 "x7$f2" + 密钥 K → 解密 → 明文 "Hello"
  • 优点:速度快(AES 可达 GB/s 级别)
  • 缺点:密钥怎么安全地传给对方?如果密钥被截获,加密就白搭

常见算法:AES、ChaCha20

非对称加密

有两把钥匙:公钥(公开)和 私钥(保密)。公钥加密的只有私钥能解,私钥加密的只有公钥能解。

公钥加密:明文 + 公钥 → 密文(只有私钥能解)
私钥签名:数据 + 私钥 → 签名(公钥可验证)
  • 优点:不需要传递私钥,天然解决密钥分发问题
  • 缺点:速度极慢(比对称加密慢 100-1000 倍)

常见算法:RSA、ECDSA、Ed25519

HTTPS 的选择:混合加密

既然对称加密快但密钥分发难,非对称加密安全但太慢,那就结合使用

① 用非对称加密安全地交换一个"临时密钥"(只需要一次,慢就慢吧)
② 之后所有数据都用这个临时密钥做对称加密(快!)

8.3 TLS 握手流程(TLS 1.2)

这是 HTTPS 最核心的部分——建立安全连接的过程。

客户端                                              服务器
  │                                                    │
  │ ① ClientHello                                      │
  │    - 支持的 TLS 版本                                 │
  │    - 支持的加密套件列表                               │
  │    - 客户端随机数(Client Random)                    │
  │ ─────────────────────────────────────────────────►  │
  │                                                    │
  │                              ② ServerHello         │
  │    - 选定的 TLS 版本                                 │
  │    - 选定的加密套件                                   │
  │    - 服务器随机数(Server Random)                    │
  │                              ③ 服务器证书            │
  │                              ④ ServerHelloDone     │
  │ ◄─────────────────────────────────────────────────  │
  │                                                    │
  │ ⑤ 验证证书(证书链 → 根证书)                          │
  │ ⑥ 生成预主密钥(Pre-Master Secret)                  │
  │ ⑦ 用服务器公钥加密预主密钥                             │
  │ ⑧ ClientKeyExchange(发送加密后的预主密钥)            │
  │ ⑨ ChangeCipherSpec("我准备好了,之后都加密")         │
  │ ⑩ Finished(第一条加密消息)                          │
  │ ─────────────────────────────────────────────────►  │
  │                                                    │
  │                    ⑪ 用私钥解密得到预主密钥             │
  │                    ⑫ 双方各自计算会话密钥               │
  │                       = f(Client Random +           │
  │                          Server Random +            │
  │                          Pre-Master Secret)         │
  │                    ⑬ ChangeCipherSpec                │
  │                    ⑭ Finished                       │
  │ ◄─────────────────────────────────────────────────  │
  │                                                    │
  │ ═══════ 之后所有数据用会话密钥做对称加密 ═══════════    │

需要 2 个 RTT 才能开始传数据。

为什么要用三个随机数?

最终的会话密钥由三个随机数共同生成:

会话密钥 = PRF(Pre-Master Secret, Client Random, Server Random)
  • Client Random:防止服务器重放攻击
  • Server Random:防止客户端重放攻击
  • Pre-Master Secret:只有双方知道的秘密(通过非对称加密安全交换)

三个随机数混合,即使其中一个被猜到,也无法推导出会话密钥。

8.4 TLS 1.3(2018)—— 更快更安全

TLS 1.3 是对 TLS 1.2 的大幅简化和优化。

主要改进

改进TLS 1.2TLS 1.3
握手 RTT2 RTT1 RTT(首次),0 RTT(重连)
密钥交换RSA 或 ECDHE只支持 ECDHE(前向安全)
加密套件几十种精简到 5 种
废弃的算法-砍掉 RC4、DES、3DES、MD5、SHA-1 等不安全算法
握手加密握手过程明文握手消息也加密(ServerHello 之后)

TLS 1.3 握手流程(只需 1 RTT)

客户端                                              服务器
  │                                                    │
  │ ClientHello                                        │
  │    - 客户端随机数                                    │
  │    - 支持的加密套件                                   │
  │    - 客户端的 ECDHE 公钥 ← 关键!直接带上了            │
  │ ─────────────────────────────────────────────────►  │
  │                                                    │
  │                              ServerHello           │
  │                              + 服务器的 ECDHE 公钥   │
  │                              + 证书                 │
  │                              + Finished            │
  │ ◄─────────────────────────────────────────────────  │
  │                                                    │
  │ 双方用 ECDHE 算出相同的密钥                           │
  │ Finished                                           │
  │ ─────────────────────────────────────────────────►  │
  │                                                    │
  │ ═══════ 1 RTT 后就可以传数据了 ═══════════           │

为什么快了? 因为 TLS 1.2 客户端要等拿到服务器证书和公钥后才能开始密钥交换,而 TLS 1.3 客户端直接在 ClientHello 里就把自己的 ECDHE 公钥发出去了(赌服务器会接受),省了一个来回。

0-RTT 重连

如果之前连过这个服务器,客户端缓存了一个 PSK(Pre-Shared Key):

客户端:ClientHello + PSK + 加密的应用数据 →
                                           服务器直接解密处理

第一个包就能带业务数据,延迟降到极致。

安全代价: 0-RTT 数据没有前向安全性,而且可能被重放攻击。所以只适合幂等请求(GET),不适合会产生副作用的操作(POST 转账)。

8.5 数字证书:怎么证明"你是你"

问题

非对称加密解决了"传密钥"的问题,但引入了新问题:你怎么知道拿到的公钥是真的?

中间人攻击:

客户端 ←→ 中间人(伪装成服务器) ←→ 真正的服务器

中间人把自己的公钥发给客户端
客户端以为这是服务器的公钥,用它加密数据
中间人解密 → 看到明文 → 用服务器真正的公钥重新加密 → 发给服务器

解决:数字证书 + CA

引入一个双方都信任的第三方 —— CA(Certificate Authority,证书颁发机构)

① 服务器生成公私钥对
② 服务器把公钥 + 域名信息提交给 CA
③ CA 验证服务器确实拥有这个域名
④ CA 用自己的私钥对"服务器公钥 + 域名信息"做数字签名
⑤ CA 颁发证书(包含:服务器公钥 + 域名 + CA 签名 + 有效期等)
⑥ 客户端收到证书后,用 CA 的公钥验证签名
⑦ 签名正确 → 公钥可信 → 建立加密连接

类比理解:

就像你去政务大厅办事,需要身份证(证书)。身份证是公安局(CA)发的,上面有你的照片(公钥)和钢印(CA 签名)。办事员通过钢印确认身份证是真的,从而相信你就是本人。

证书链

CA 的公钥又是谁来保证的?答案是证书链

根证书(Root CA)         预装在操作系统/浏览器中,无条件信任
  
  └── 中间证书(Intermediate CA)  CA 签发的
        
        └── 服务器证书(End Entity)    中间 CA 签发的

验证过程从下往上:

  1. 用中间 CA 的公钥验证服务器证书的签名
  2. 用根 CA 的公钥验证中间 CA 证书的签名
  3. 根 CA 证书在本地受信任列表中 → 整条链可信

为什么要分层?如果根 CA 直接签发所有证书,一旦根 CA 私钥泄露,后果不堪设想。分层后,即使中间 CA 出问题,只需要吊销这个中间 CA,不影响其他。

8.6 前向安全(Forward Secrecy)

问题

如果用 RSA 做密钥交换(TLS 1.2 的一种模式),一旦服务器私钥泄露,攻击者可以:

  1. 解密之前录制的所有流量中的 Pre-Master Secret
  2. 从而推导出所有历史会话密钥
  3. 所有历史通信全部暴露

解决:ECDHE 密钥交换

每次连接都生成临时的(Ephemeral) 公私钥对,用完即销毁。

连接1:临时密钥对 A → 会话密钥 X → 销毁临时密钥对 A
连接2:临时密钥对 B → 会话密钥 Y → 销毁临时密钥对 B
连接3:临时密钥对 C → 会话密钥 Z → 销毁临时密钥对 C

即使服务器的长期私钥泄露,也无法解密之前的通信,因为临时密钥已经不存在了。

这就是"前向安全"(Forward Secrecy)。TLS 1.3 强制要求使用 ECDHE,所有连接都具有前向安全性。

8.7 HTTPS 的性能影响

开销说明缓解方案
握手延迟TLS 1.2 多 2 RTT,TLS 1.3 多 1 RTT升级 TLS 1.3、会话复用、0-RTT
加解密 CPUAES 加解密消耗 CPU现代 CPU 都有 AES-NI 硬件加速,开销几乎可忽略
证书传输证书链可能 3-5KBOCSP Stapling 减少验证开销
内存每个连接需要维护加密上下文影响很小

现代环境下 HTTPS 的额外开销已经非常小了,Google 的数据显示 HTTPS 只增加了不到 2% 的 CPU 负载和不到 10ms 的延迟。

8.8 常见 HTTPS 相关概念

概念解释
HSTS服务器告诉浏览器"以后只用 HTTPS 访问我",防止降级攻击
OCSP Stapling服务器主动把证书有效性证明发给客户端,省去客户端向 CA 查询
CT(Certificate Transparency)所有颁发的证书必须公开记录,防止 CA 偷偷签发恶意证书
SNI客户端在 TLS 握手时告诉服务器要访问哪个域名(一个 IP 上多个 HTTPS 站点)
ESNI / ECH加密 SNI,防止中间人知道你在访问哪个网站
证书固定(Pinning)App 内置预期的证书指纹,防止中间人使用合法但非预期的证书
Let's Encrypt免费、自动化的 CA,推动了 HTTPS 的全面普及
双向认证(mTLS)不仅服务器要证书,客户端也要证书(常见于企业内部、金融系统)

九、一张图总结

1991  HTTP/0.9 ─── 只能传 HTML,连个状态码都没有
        
1996  HTTP/1.0 ─── 有了头部、状态码、多媒体,但每次请求都要新建连接
        
1997  HTTP/1.1 ─── 持久连接、缓存控制、断点续传,但有队头阻塞
                     └── HTTPS(TLS 1.0~1.2) 解决安全问题
        
2015  HTTP/2 ──── 二进制分帧、多路复用、头部压缩,但 TCP 层仍有队头阻塞
                     └── TLS 1.3:1-RTT 握手、前向安全
        
2022  HTTP/3 ──── 换用 QUIC(UDP),彻底消灭队头阻塞,0-RTT 连接,连接迁移

每一代都在解决上一代留下的问题,同时也带来了新的挑战。技术演进就是这样一步步往前走的。