Network Layer & End To End System Design

这一节我们会介绍网络的分层(老熟人了)和 End To End System Design. 计算机网络以分组的方式来提供对物理等层面的抽象。各层的所有协议被称为协议栈(protocol stack),而 internet 提供了 物理层、链路层、网络层、运输层和应用层:

  1. 对于应用层而言,数据是 message
  2. 对于运输层而言,它们在应用 endpoint 中传输上层的 message。我们把这一层的分组叫做 segment。这一层的协议包括 TCP 和 UDP
  3. 网络层负责将 datagram 移动到另一边。这一层包括著名的 IP 协议,同时它包含一些路由选择协议, 给运输层运输 packet
  4. 链路层依靠链路层的服务(还记得我们前两讲介绍的吗)讲消息传给下一个节点,链路层的分组称为 frame / packet.
  5. 物理层中,我们完成了对物理信号等对程序员来说没啥影响,但是必要的电路等信息。这一层向上一层提供了光纤、铜线等提供的物理信号,给上层提供 0/1。

应当说明的是,上面是 Internet 的网络分层,实际上你可能还听说过 OSI 7层模型等分层。

在分层的网络中,对于上层而言,下层类似 api,下层提供一些封装过后的保证,上层用一定的方式和一定的保证来获得下一层的数据。

链路层和网络层

1/2/5 实际上相对来说好理解,大部分人都或多或少有印象。但是 4-5 之间有什么区别呢?我们知道网络层包括 IP 协议,实际上,情况类似下面:

CB61FDA0-C769-4B9E-A2EF-ABDE2535C9D3

We’ll divide the world into switches and routers

  1. Switches will route on your, Link Layer (L2) Addresses
  2. Routers will operate on IP (L3) Addresses

639D4B96-BEB7-407C-B054-22FF26A861D8

这两层使用的 Route 方式不同,这一点我们即将介绍 IP,就会了解了。

实际上,IP 这个抽象相对来说相当重要,它提供了一个比较独立的网络的抽象,同时,对于异质性的网络,网络层也需要作出一定的协调和妥协:

  • 网络的带宽更大,发送的数据更快,而满的网络来不及接受,IP 需要丢弃来自生产快的网络的包
  • IP 层不能保证 loss-free 和消息传递的 order (This is called best effort service.)
  • 有些网络有着更大的 packet,这个时候需要支持 fragementation 来拆分 packet

55771480-6AB4-4711-82FD-617C7F5F46E4

下面继续丢图:

0FD97745-8A4A-43BE-9344-FCCF18DB4F71

同时,对于上层的应用而言,我们也有不同层次的信息(正如我们一开始介绍的):

6CA008EC-D656-423C-8619-79782173A59E

每层的信息有不同的 header, 来表示这一层承载的信息。

End To End arguments in system design

这是 84 年的一篇文章,介绍了那个时候互联网应用设计的一些思考。作者认为应该合理的抽象,在底层实现一些语意以优化性能,在高层实现高层真正想要的语义,因为在底层做抽象是很昂贵的,并且它们提供的语意也不一定真正可靠(当然你是金融公司或者很有钱啥的,都能自己搭海底光缆搞高频交易了,你大概也有钱在下层做优化了)。

文章最开始举了个简单的例子:文件传输程序。

用户从 fs 中读取一个文件,然后经过程序一定处理,发送给网络另一端,另一个用户接收并写入 fs。

这个事件本身各个层次都可能出现错误。我们不仅需要底层各种保证和错误处理,实际上我们需要端到端的确认,即应用确认文件写入完成,并且 checksum 等一致。

1E186DDA-D9B7-4241-90C8-8ED18C84818C

同时,我们虽然有 tcp 之类的协议能保证 order 和内容可靠,但是可靠的内容不一定被处理了,从这个角度来看,仅仅 tcp 是不可靠的。但是相对更底层的协议,或者 UDP 而言,底层实现对应的语义能保证性能上的 bonus. 我们可能需要下列的方案来保证应用层次的可靠:

  1. Encryption
  2. First-in-first-out ordering
  3. Duplicate message surpression
  4. Multi-message transactions

slide 给出了总结,我就不献丑翻译了:

Basic argument: If you can implement functionality correctly and completely at endpoints, do it there and not at a lower layer.

  • It saves on redundant work in the system, and avoids confusion later. Exceptions okay for performance optimizations.

Strong argument: Avoid putting unneeded functionality at lower layers of your system altogether because it’s harmful!

  • Extra functionality at low layers constrains how applications are designed at higher layers.