本文將給出關于互聯網架構演進的一個不同視角。回顧一下互聯網的核心理論基礎產生的背景:
左邊是典型的集中控制通信網絡,很容易被摧毀,而右邊的網絡則沒有單點問題,換句話說它很難被全部摧毀,與此同時,分時計算機無法容忍 “占線”,它希望網絡也是一個分時系統。如何同時處理多個來源的數據包的交織是一個實際問題,最后,萊昂納德克萊因洛克通過排隊論數學分析,使人們相信了分組交換網的可行性。
理論基礎奠定后,時間來到 1970 年代,人們需要將概念工程化,TCP 誕生,但 IP 還沒有。再次通過 RFC675 看 TCP 最初的樣子,4.2 節展示了 TCP 格式:
8 bits: Internet information
2 bits: Reserved for local PSN use
2 bits: Header format (11 in binary)
4 bits: Protocol version number
8 bits: Header length in octets (32 is the current value)
16 bits: Length of text in octets
32 bits: Packet sequence number
32 bits: Acknowledgment number (i.e. sequence number of next octet expected).
16 bits: Window size (in octets)
16 bits: Control InformationListed from high to low order:SYN: Request to synchronize sending sequence numbersACK: There is a valid acknowledgment in the 32 bit ACK fieldFIN: Sender will stop SENDing and RECEIVEing on this connectionDSN: The sender has stopped using sequence numbers and wants to initiate a new sequence number for sending.EOS: This packet is the end of a segment and therefore has a checksum in the 16 bit checksum field. If this bit is not set, the 16 bit checksum field is to be ignored. The bit is usually set, but if fragmentation at a GATEWAY occurs, the packets preceding the last one will not have checksums, and the last packet will have the checksum for the entire original fragment (segment) as it was calculated by the sending TCP.EOL: This packet contains the last fragment of a letter. The EOS bit will always be set in this case.INT: The sender wants to INTERRUPT on this connection.XXX: six (6) unused control bitsOD: three (3) bits of control dispatch:000: Null (the control octet contents should be ignored}001: Event Code is present in the control octet. These were defined in section 2.4.3.010: Special Functions011: Reject (codes as yet undefined)1XX: Unused
8 bits: Control Data OctetIf CD is 000 then this octet is to be ignored.If CD is 001, this octet contains event codes defined in section2.4.3If CD is 010, this octet contains a special function code as defined below:0: RESET all connections between Source and Destination TCPsl: RESET the specific connection referenced in this packet2: ECHO return packet to sender with the special function code ECHOR (Echo Reply).3: QUERY Query status of connection referenced in this packet4: STATUS Reply to QUERY with requested status.5: ECHOR Echo Reply6: TRASH Discard packet without acknowledgment>6: UnusedNote: Special function packets not pertaining to a particular connection [RESET all, ECHO, ECHOR, and TRASH] are normally sent using socket zero as described in section 3.2.If CD is 01l, this octet contains an as yet undefined REJECT code.If CD is 1XX, this octet is undefined.
# 4 bits: Length of destination network address in 4 bit units (current value is 1)
# 4 bits: Destination network address1010-1111 are addresses of ARPANET, UCL, CYCLADES, NPL, CADC, and EPSS respectively.
# 16 bits: Destination TCP address
# 8 bits: Padding
# 4 bits: length of source network address in 4 bit units (current value is 1)
# 4 bits: source network address (as for destination address)
# 16 bits: Source TCP address
# 24 bits: Destination port address
# 24 bits: Source port address
16 bits: Checksum (if EOS bit is set)
看上去和現在的 TCP 一點都不一樣,當時 TCP 和后來的 IP 是同一個協議,統稱 TCP。第 41 行開始(我做了 # 標記)的字段與尋址有關,早期并沒有采用固定 32 位地址,而采用了一種非常變通的方式:
- 4bits 指示網絡地址長度,16bits 尋址該網絡內的具體 TCP 實體。
我們知道,“16 bits: Destination TCP address” 標識的 TCP 實體其實就是主機地址,但在當時,一個 TCP 就表示一個主機,因為沒別的協議。接下來的 24bit 端口有點意思,我們知道最終它變成了 16bit,用于多路復用和解復用。
在 1980 年 RFC760 和 RFC761 試圖分離 IP 并標準化 TCP/IP 時,考慮到當時的實現開銷(慢 CPU,小內存),變長地址轉向固定 32bit,即 IP 地址,這一切終于在 RFC791 和 RFC793 中最終被標準化,就是 TCP/IPv4。
回顧互聯網早期歷史時,雖然分時系統已經預見了后來的 PC 以及隨之而來的內容分發時代遲早到來,但暢想歸暢想,在實踐中仍然傾向于換一種方式 “打電話”,這更實際,所以我們看到 1974 年的 TCP 是一條虛電路,建立 TCP 連接帶著濃厚的 “呼叫”,“連接” 的味道(細看 SYN,ACK/SYN[是這個順序,而不是 SYN/ACK],ACK)。
至于 IP,它只是從 TCP 剝離出來的一個極其穩定的平臺,極其穩定的原因是它極其簡化,它甚至沒有任何語義,但在本質上,IP 依舊源自于 “呼叫”,IP 互聯的意思是,基于 IP 之上端到端傳輸層協議的點對點互聯,一個 IP 地址與另一個 IP 地址之間的 “通信”。換句話說,IP 不負責 “打電話的方式” 這種復雜的帶有邏輯的語義,但 IP 地址似乎就是 “電話號碼” 本身。
離開 TCP/IP 轉向底層分組交換傳輸網絡,我們發現無論是 X.25,幀中繼,還是 ATM,都可歸為 “用分組交換的方式打電話”。當我們說 ATM 帶有電信的影子時我們在說什么,這個問題很有趣。
分組交換傳輸網絡轉發方案分為兩大陣營,分別為利用路由器內轉發狀態(流表)的電信陣營和利用數據包中轉發指示(地址)的互聯網陣營,前者成員直接或間接傳承傳統電話電信系統(ITU),典型作品為 ATM,后者則來自相對較新的開放組織(IEEE/IETF),典型作品為以太網,TCP/IP。下面簡述它們彼此爭論的核心過程和結果。
我們現在知道,ATM 以及其它虛電路傳輸技術都是分離后 IP(即 RFC760 之后) 的反面,看清 IP 后反著看就看清了它們所有。IP 是無狀態,盡力而為(best-effort)的,這意味著路由器不保留任何包或流狀態,所有尋址信息都在數據包本身(即 IP 頭),路由器僅執行 SPF 逐跳轉發。那么反過來,ATM 等網絡就是在交換機保存狀態,數據包中攜帶一個短標識,該標識可以理解為交換機中保存狀態的索引,即虛電路標識。虛電路網絡基于虛電路標識的轉發本質上就是 “標簽交換”。
虛電路網絡采用有狀態交換的好處之一就是 QoS 非常容易實現,有句話說得好,IP 從誕生到現在一直在想辦法支持 QoS,而 QoS 一直是虛電路網絡的核心原則。
IP 除了無狀態交換,其數據包的大小是可變長的,這加劇了時延和抖動的不確定性,對于電話系統的設計者或受其影響的網絡工作者而言不可接受,那么自然而然的,固定大小的信元交換就成了這類虛電路網絡的核心特征。衍生自電話系統的設計,虛電路信元足夠短,這樣才能支持足夠細粒度的信元調度,以確保低時延和低抖動,既然信元足夠短,支持相對大的頭(比如 IP 頭)就顯得昂貴,這又反過來催使信元交換網絡必須采用有狀態交換,每個信元中的地址只是一個簡單的表索引,而不是索引匹配的目的地址,所有的信息都在交換機中。
你看,信元交換和有狀態網絡是相輔相成,相互加強的。相對應的,IP 的無狀態交換和變長包也是相輔相成的。
最后,在一種樸素的哲學意義上,任何相對立的事物最終都會出現某種融合,MPLS 就是典型例子,在變長的數據包而不是定長的信元上使用標簽交換。另一個更加激進的融合實例是 IP NAT,它本質上也是標簽交換,只不過它交換的是 IP 地址本身。
以上我們看到,無論從 TCP/IP 還是底層傳輸網絡來看,“呼叫”,“連接” 是早期互聯網的核心,但隨著 1980 年代后期到 1990 年代全面進入 PC 時代后以及隨著 Web 的發展,“呼叫” 網絡逐漸開始變成 “內容” 網絡,在這種網絡中,一臺計算機程序 “呼叫” 另一臺計算機程序是非常奇怪的,取而代之更合理的是多臺計算機作為客戶端從少數服務器上 “獲取內容”。這導致了前面的文章 TCP Listen 語義與端口失衡 里提到的源端口和目標端口數量偏斜以及與之相關的一系列問題,我也給出了相應的 work around,但在這里,我用更抽象的描述重述同一件事。
TCP 可分為兩類,作為內容服務的 Anycast TCP 以及作為通信連接的 Unicast TCP:
- 內容 TCP:非對稱連接,dport 高 8bit 作為 Anycast 服務進程索引(比如 hash 索引),低 8bit 做 Anycast 地址索引服務類型;
- 通信 TCP:對稱連接,一對一通信,類似呼叫類服務,打電話,遠程登錄等。
無論哪一種,都并非一定需要 Listen,注意,Listen 是 Socket 的,不是 TCP 的。內容 TCP 請求可以直接定向到服務進程,而通信 TCP 請求可以執行喚起服務進程的操作,類似 Unix 系統中 “振鈴” 服務,而 sip + sport 和 dip + dport 可視作主叫和被叫的 “電話號碼”,這就很類似 fork + exec 操作,只是為了實現這個操作,Listen + Accept 非常合適而已。
但 work around 總歸治標不治本,這是因為 TCP 甚至整個 TCP/IP 協議族本就不適合內容分發,它最初是為全球 IP 互聯互通的 “呼叫” 和 “連接” 創立的,但后面的發展表明,類似 Web 這種多對一的 C/S 內容分發應用才是互聯網上最流行的,NAT 之所以可行并大規模鋪開,反面印證了內容分發模式應用確實是普遍的,否則如果真的都是一對一通信應用,NAT 根本無法部署實施。
映射到現實世界,人們去商超購物,去影院看電影,去飯店吃飯這種出入公共場所的頻率遠大于去私人家登門拜訪的頻率,而出入公共場所和出入私人家最本質的區別有兩個:
- 公共場所不需要登記人們是誰或來自哪里,但私人拜訪需要;
- 公共場所不挑地址,比如連鎖店去最近的那家即可,但私人拜訪必須去固定地址。
映射回互聯網絡架構,這導致專門用于內容分發的網絡被提出,即 NDN(Named Data Networking),這是一種以內容為中心的網絡,人們只關心獲取的內容,并不關心該內容來自哪里,同時,內容提供者也過度不關心請求者來自哪里。
NDN 是一種非常激進的網絡架構,它要求路由器記錄每包狀態,卻不強制每包內含任何地址信息,同時,它建議路由器緩存它能盡力緩存的一切內容,比如被很多人請求頻率很高的內容。
包中沒有地址如何路由,還記得虛電路如何做的嗎,包中有個虛電路標號,索引交換機的狀態表即可,對應于 NDN,包里有個 “內容名字”,索引路由器中的狀態表即可:
如果本地沒有請求名字對應的內容,路由器如何知道內容在哪里呢?這涉及到 NDN 復雜的技術細節,比如沿途路由器可以自學習機制,學習過路名字/內容對所對應的端口,或者直接泛洪,還有一種可能就是內容提供者主動泛洪或自定義推送,類似商場搞活動時沿途發傳單推銷,傳單上印有店鋪地址。
至于路由器如何緩存內容,主要看內容的流行度,重要程度以及一些自定義策略。
NDN 延續了 TCP/IP 成功的沙漏模型,保持了沙漏形狀的架構,但用數據名字代替 IP 地址進行數據傳輸。增加路由器的緩存功能也在情理之中,TCP/IP 的年代存儲部件小且昂貴,如今不同了。
NDN 是天然的靜態內容分發網絡,它和現實世界是高度擬合的,在內容的自然選擇下,最流行,最重要,流量最大的內容總會在離人們最近的邊緣節點被緩存,這就是一個無需 GSLB 的 CDN 網絡。至于動態內容,它天然就是一個扇入系統,自帶擁塞屬性,類似直播的流量幾乎就是現實世界演唱會,大型集會的翻版。
由于 CDN 的高速發展和全面部署,回源被聚攏在 CDN 內容提供商極其粗壯的內網,掩蓋了傳統 TCP/IP 的大多數問題,使 NDN 網絡始終停留在概念,但它的理念無疑是先進的,從 NDN 先進的內容分發理念的意義上說,CDN 只是一個 work around,比如它始終解決不了最后一公里擁塞問題,因為本質上 CDN 仍是一個多對一訪問系統,而 NDN 會將內容推向離多個用戶更近的多個位置,沒了帶寬競爭,問題自然消失,交易則是用存儲成本自動機交換獨享內容帶寬。
NDN 是一種完全不同于 TCP/IP 并與之并列的網絡架構,它甚至不使用 IP 這個穩定的平臺。如果說 TCP/IP 適用于點到點通信,它本質上還是一個通信網絡,那么 NDN 就是一個專門的靜態內容分發網絡,非常適用于 Web。如果 1960~1970 年代網絡從理論,概念到工程化的時期,內容分發已經比打電話,遠程登錄,互傳文件更流行了,那么可想而知,如今的互聯網架構大概率就是 NDN 或與之類似的,它可能仍叫 TCP/IP,但含義將完全不同。
醉過風,喝過茶,沒得英雄名諱,掂量個舊事抵酒價,在座皆算老友,碗底便是天涯,作罷。
浙江溫州皮鞋濕,下雨進水不會胖。